Snake (Programmier Stil)

Status
Nicht offen für weitere Antworten.

Newgame

Mitglied
Hallo,
Endlich habe ich mich dazu durchgerungen mich anzumelden! 🙂
Ich habe einen Snake Clon programmiert der auch ganz okay funktioniert. Da ich aber noch nicht so die Erfahrung in Java habe, frage ich mich immer, ob mein Programmierstil beziehungsweise meine spezielle Art und Weise Snake in Java zu programmieren überhaupt "elegant" ist.
Hier
könnt ihr euch das Snake Spiel mitsamt Sources herunterladen.
Also von allgemeinen zu speziellen Fragen:
1. Was gibt es allgemein an meinem Stil auszusetzen?
2. Ist meine Klassenaufteilung sinnvoll oder ginge es besser/einfacher?
3. Wie gehe ich an GameEvents heran? Ich habe mir einige Sources zu Tetris angeschaut. Bei einem wurde z.B. das Event "Grund erreicht" mit booleans und switch-abfragen erledigt, bei dem anderen wurden EventListener benutzt (wo ich immernoch nicht ganz durchblicke). Ich habe zum Beispiel eine SnakeEvent Klasse erstellt. In ihr sind die Abfragen enthalten (also: "Ist Snake noch im Spielfeld") aber auch die Befehle (z.B. "Addiere ein Segment zur Schlange").
Wäre es hier zum Beispiel sinnvoll EventListeners einzusetzten? Wenn ja wie?
4. Gibt es irgendwo ein MusterSnakeJavaBeispiel (Ich weiß ich kann bei google oder hier in der Suche nachschauen, aber vielleicht kennt jemand ein ganz besonders gutes)?

Ich hoffe jemand hat Lust und Zeit sich das mal anzuschauen :wink:
 
Falls jemand keine lust hat sich die zip Datei runterzuladen hier der source:


Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class SnakeGame extends JPanel implements Runnable{
	private static final long serialVersionUID = 1L;
	int W = 400;
	int H = 400;
	int numberOfBlocks = (int)Math.sqrt(10*10);
	boolean[][] gameField = new boolean[numberOfBlocks][numberOfBlocks];
	private Snake snake;
	private SnakeEvent snakeEvent;
	int foodX;
	int foodY;
	Thread t;
	JFrame frame;
	
	public static void main(String[] args) {
		new SnakeGame();
	}
	
	public SnakeGame() {
		this.setPreferredSize(new Dimension(W,H));
		frame = new JFrame();
		frame.setVisible(true);
		frame.setLocation(100, 100);
		frame.setTitle("Easy Snake");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(this);
		frame.pack();
		frame.setResizable(false);
		init();
		//frame.addKeyListener(new SnakeKeyAdapter(this, snake));
	}
	
	public void init() {
		for(int x = 0; x < gameField.length; x++) {
			for(int y = 0; y < gameField[x].length; y++) {
				gameField[x][y] = false;
			}
		}
		snake = new Snake(0,0,this);
		snake.setRandomDirection();
		snake.addSegment();
		snakeEvent = new SnakeEvent(this);
		putFoodRandomly();
		t = new Thread(this);
		t.start();
		frame.addKeyListener(new SnakeKeyAdapter(this, snake));
	}

	@Override
	public void run() {
		while(!t.isInterrupted()) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {}
			snake.Update();
			snakeEvent.checkEvents();
			repaint();	
		}
		snakeEvent.newGame();
	}
	
	@Override
	public void paint(Graphics g) {
		//clear the "screen"
		g.setColor(new Color(190,255,110));
		g.fillRect(0, 0, W, H);
		g.setColor(Color.black);
		//draw the gameField
		int blockSize = (int)(W/numberOfBlocks);
		for(int x = 0; x < gameField.length; x++) {
			for(int y = 0; y < gameField[x].length; y++) {
				if (!gameField[x][y]) {
					g.setColor(new Color(230,230,230));
					//g.drawRect(x*blockSize, y*blockSize, blockSize, blockSize);
				}
				else {
					g.setColor(Color.green);
					g.fillRect(x*blockSize, y*blockSize, 
							blockSize, blockSize);
				}
			}
		}
		drawFood(g, blockSize);
	}
	
	//FOOD
	public void drawFood(Graphics g, int blockSize) {
		g.setColor(new Color(255,255,0));
		g.fillOval(foodX*blockSize, foodY*blockSize, blockSize, blockSize);
	}
	
	public void putFoodRandomly() {
		//Create a List of free places on the gameField, randomize the index of the list
		//and assign free and random place for food
		ArrayList<Integer> x = new ArrayList<Integer>();
		ArrayList<Integer> y = new ArrayList<Integer>();
		for(int i = 0; i < gameField.length; i++) {
			for(int j = 0; j < gameField[i].length; j++) {
				if(!gameField[i][j]) {
					x.add(i);
					y.add(j);
				}
			}
		}
		int randomIndex = (int)(Math.random()*(x.size()-1));
		foodX = x.get(randomIndex);
		foodY = y.get(randomIndex);
	}
	
	public Snake getSnake() {
		return snake;
	}
}


public class Block {
	private int x;
	private int y;
	private int oldx;
	private int oldy;
	
	public Block(int x, int y) {
		this.x = x;
		this.y = y;
		this.oldx = x;
		this.oldy = y;
	}
	
	public void setPosition(int x, int y) {
		oldx = this.x;
		oldy = this.y;
		this.x = x;
		this.y = y;
	}
	
	public void setOldPosition(int x, int y) {
		oldx = x;
		oldy = y;
	}
	
	public void translate(int x, int y) {
		oldx = this.x;
		oldy = this.y;
		this.x += x;
		this.y += y;
	}
	
	public int getX() {
		return x;
	}
	
	public int getY() {
		return y;
	}
	
	public int getOldX() {
		return oldx;
	}
	
	public int getOldY() {
		return oldy;
	}
}

import java.util.ArrayList;


public class Snake {
	ArrayList<Block> blocks;
	private boolean moveRight, moveLeft, moveUp, moveDown;
	private SnakeGame game;
	private Block leader;
	private long pause;
	private long lastTime;
	private long currentTime;
	
	public Snake(int x, int y, SnakeGame game) {
		this.game = game;
		blocks = new ArrayList<Block>();
		blocks.add(new Block(x,y));
		leader = blocks.get(0);
		pause = 200;
		lastTime = 0;
	}
	
	public void setRandomDirection() {
		if(Math.random() < 0.5) {
			resetDirection();
			moveRight = true;
		} else {
			resetDirection();
			moveDown = true;
		}
	}
	
	public void Update() {
		currentTime = System.currentTimeMillis();
		if(currentTime - lastTime > pause) {
			//Move the head
			Move();
			//Update positions of segments
			for(int i = 0; i < blocks.size()-1; i++) {
				blocks.get(i+1).setPosition(blocks.get(i).getOldX(), blocks.get(i).getOldY());
			}
			//Update gameField
			for(Block i : blocks) {
				try {
					game.gameField[i.getOldX()][i.getOldY()] = false;
					game.gameField[i.getX()][i.getY()] = true;
				} catch (ArrayIndexOutOfBoundsException e) {
					
				}
				
			}
			
			lastTime = currentTime;
		}
	}
	
	public void addSegment() {
		//blocks.size()-1: In order to get the latest element
		int x = blocks.get(blocks.size()-1).getOldX();
		int y = blocks.get(blocks.size()-1).getOldY();
		blocks.add(new Block(x, y));
	}
	
	private void resetDirection() {
		moveRight = false;
		moveLeft = false;
		moveUp = false;
		moveDown = false;
	}
	
	private void Move() {
		if(moveRight) {
			leader.translate(1, 0);
		}
		if(moveLeft) {
			leader.translate(-1, 0);
		}
		if(moveUp) {
			leader.translate(0, -1);
		}
		if(moveDown) {
			leader.translate(0, 1);
		}
	}
	
	public void moveRight() {
		if(!moveLeft) {
			resetDirection();
			moveRight = true;
		}
	}
	
	public void moveLeft() {
		if(!moveRight) {
			resetDirection();
			moveLeft = true;
		}
	}
	
	public void moveUp() {
		if(!moveDown) {
			resetDirection();
			moveUp = true;
		}
	}
	
	public void moveDown() {
		if(!moveUp) {
			resetDirection();
			moveDown = true;
		}
	}
	
	public int getX() {
		return leader.getX();
	}
	
	public int getY() {
		return leader.getY();
	}
	
}

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;


public class SnakeKeyAdapter extends KeyAdapter{
	
	Snake snake;
	
	SnakeGame game;
	
	public SnakeKeyAdapter(SnakeGame game, Snake snake) {
		this.game = game;
		this.snake = snake;
	}
	
	public void keyPressed(KeyEvent e) {
		
		switch(e.getKeyCode()) {
		case KeyEvent.VK_LEFT:
			snake.moveLeft();
			break;
		case KeyEvent.VK_RIGHT:
			snake.moveRight();
			break;
		case KeyEvent.VK_DOWN:
			snake.moveDown();
			break;
		case KeyEvent.VK_UP:
			snake.moveUp();
			break;
		case KeyEvent.VK_A:
			snake.addSegment();
			break;
		case KeyEvent.VK_ESCAPE:
			System.exit(0);
			break;
		}
		
	}
}

import java.util.ArrayList;

import javax.swing.JOptionPane;


public class SnakeEvent {
	
	SnakeGame game;

	public SnakeEvent(SnakeGame game) {
		this.game = game;
	}
	
	public void checkEvents() {
		bitItself();
		ateFood();
		outOfGameField();
	}
	
	private void ateFood() {
		Snake snake = game.getSnake();
		if(snake.getX() == game.foodX && snake.getY() == game.foodY) {
			game.putFoodRandomly();
			snake.addSegment();
			System.out.println("segment added");
		}
	}
	
	private void bitItself() {
		Snake snake = game.getSnake();
		int leaderX = snake.getX();
		int leaderY = snake.getY();
		ArrayList<Block> others = snake.blocks;
		
		for(Block i: others) {
			if(!i.equals(others.get(0))) {
				if(i.getX() == leaderX && i.getY() == leaderY) {
					gameOver();
				}
			}
		}
	}
	
	private void outOfGameField() {
		Snake snake = game.getSnake();
		int leaderX = snake.getX();
		int leaderY = snake.getY();
		int width = game.numberOfBlocks - 1;
		int height = game.numberOfBlocks - 1;
		
		if(leaderX < 0) {
			gameOver();
		}
		if(leaderX > width) {
			gameOver();
		}
		if(leaderY < 0) {
			gameOver();
		}
		if(leaderY > height) {
			gameOver();
		}
	}
	
	private void gameOver() {
		game.t.interrupt();
	}
	
	public void newGame() {
		new Thread() {
			public void run() {
				int n = JOptionPane.showConfirmDialog(
					    game.frame,
					    "New Game?",
					    "Question",
					    JOptionPane.YES_NO_OPTION);
				
				if(n == JOptionPane.OK_OPTION) {
					game.init();
				}
				else {
					System.exit(0);
				}
			}
		}.start();
	}
}
 
Zuletzt bearbeitet von einem Moderator:
Mit welchem Programm hast du den das geschrieben?
Könntest du mir vielleicht die Datei senden von dem Programm mit dem du es geschrieben hast?
lg
 
da geht jeder Texteditor, oder komplizierter mit einer IDE wie Eclipse,

um auch mal was passendes in diesem Thema zu schreiben:
der Code sieht unauffällig aus, bis auf groß geschriebene Update()-Methode,
setVisible(true); besser NACH Einfügen aller GUI-Elemente
 
ich persönlich nicht, und während die erste Frage noch so halbwegs passt dass sie nicht gleich gelöscht werden sollte
kannst du allgemeine Diskussionen um Programmiertools bitte in einem eigenen Thema führen,
hier hast du sowieso 90% weniger Publikum, falsche Area, alter Thread
 
hey kannst du mir nochmal genau schreiben wie du das programmiert hast? also mir viielleicht sogar den quelltext schicken und was genau muss ich dafür dann noch einrichten damit das geht?

lg.🙂
 
Schon mal auf das Datum geachtet bzw. gelesen was hier so gepostet wurde?

*geschlossen*
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben