patternjavaMinor
Java Snake game
Viewed 0 times
gamesnakejava
Problem
I am a self - taught coder, and have been learning Java / C# for the last 2 1/2 years (inconsistently).
I have recently created a snake game in Java with the help of an online tutorial. I have rearranged the program into separate classes & methods. I am skeptical on how good of a programmer I am, and I code messy.
I don't really want help on how to make the game better in visuals, levels, or anything like that. I am asking those who are more advanced programmers to help me with implementing programming techniques, better organization, how to comment better, etc. Pretty much anything that will help me become a better programmer.
Also, I have commented a few things out of pure guess, so if it appears as if I have gotten something wrong, please correct me!
Also, any extra tips for my future projects would be much appreciated!
Game.Java
Snake.Java
```
public class Snake {
// Stores the joints / body part locations for our snake
private final int[] x = new int[Board.getAllDots()];
private final int[] y = new int[Board.getAllDots()];
// Stores direction of our snake
private boolean movingLeft = false;
private boolean movingRight = false;
private boolean movingUp = false;
private boolean movingDown = false;
private int joints = 0; // Stores # of dots / joints the snake has (starts
// with 3)
public int getSnakeX(int index) {
return x[index];
}
public int getSnakeY(int index)
I have recently created a snake game in Java with the help of an online tutorial. I have rearranged the program into separate classes & methods. I am skeptical on how good of a programmer I am, and I code messy.
I don't really want help on how to make the game better in visuals, levels, or anything like that. I am asking those who are more advanced programmers to help me with implementing programming techniques, better organization, how to comment better, etc. Pretty much anything that will help me become a better programmer.
Also, I have commented a few things out of pure guess, so if it appears as if I have gotten something wrong, please correct me!
Also, any extra tips for my future projects would be much appreciated!
Game.Java
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Game extends JFrame {
Game() {
add(new Board());
setResizable(false);
pack();
setTitle("Snake");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
// Creates a new thread so our GUI can process itself
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new Game();
frame.setVisible(true);
}
});
}
}Snake.Java
```
public class Snake {
// Stores the joints / body part locations for our snake
private final int[] x = new int[Board.getAllDots()];
private final int[] y = new int[Board.getAllDots()];
// Stores direction of our snake
private boolean movingLeft = false;
private boolean movingRight = false;
private boolean movingUp = false;
private boolean movingDown = false;
private int joints = 0; // Stores # of dots / joints the snake has (starts
// with 3)
public int getSnakeX(int index) {
return x[index];
}
public int getSnakeY(int index)
Solution
Welcome to Code Review! There's lots that can be improved about this code, so lets get started.
Use the Random class instead of Math.random()
Instead of this
Do this
The reason for this is that
Enums instead of booleans
Instead of having four booleans representing the direction that the snake is moving, instead make these into an enum. It could look like this:
Then, instead of this redundant code:
You can just have
I would also recommend replacing this one
With a
Separate Game Model from Rendering
Looking at the
It is good programming practice to separate the input and rendering from the underlying game model. This will allow you to switch out the rendering and input and still use the game model code almost unchanged. You can also port the game over to another language much more easily.
To achieve this, you will need a class that just handles the rendering and input. You could call this
Object Oriented design
Following the idea of separating the game model from the rendering, there are many places where the code could be made more object oriented. It is not mandatory to write code in an object oriented way, but it is especially helpful when you are a beginner, and I personally find that it makes code easier to write and understand.
Below the
The
Eventually you could change these integers to something more self documenting, such as an enum with values for
The window class would get information about the
I would put the collision methods for the walls and food in the
The Food class
The fact that the max position of the food is 40 but then that number is multiplied by the dot size is confusing. It is also strange that the
Shouldn't there only be one instance of the
Use the Random class instead of Math.random()
Instead of this
Math.random() * RANDOMPOSITIONDo this
int randomNumber = this.random.nextInt(RANDOMPOSITION)The reason for this is that
random.nextInt is more efficient and less biased (see here https://stackoverflow.com/questions/738629/math-random-versus-random-nextintint for more information about that).Enums instead of booleans
Instead of having four booleans representing the direction that the snake is moving, instead make these into an enum. It could look like this:
public enum Direction {
RIGHT,
LEFT,
UP,
DOWN;
}Then, instead of this redundant code:
if ((key == KeyEvent.VK_LEFT) && (!snake.isMovingRight())) {
snake.setMovingLeft(true);
snake.setMovingUp(false);
snake.setMovingDown(false);
}You can just have
snake.setDirection(Direction.LEFT)I would also recommend replacing this one
// Check to see if the game is running
private boolean inGame = true;With a
GameState enum. That way, you can easily add a PAUSED and a GAME_OVER state depending on your needs.Separate Game Model from Rendering
Looking at the
Board class, it appears to be responsible for tying many different parts of the game together. I see the rendering, input, game state, game speed, game setup, game rules, and collision checking all in this one class. It is good programming practice to separate the input and rendering from the underlying game model. This will allow you to switch out the rendering and input and still use the game model code almost unchanged. You can also port the game over to another language much more easily.
To achieve this, you will need a class that just handles the rendering and input. You could call this
SnakeWindow. This class would be responsible for rendering the contents of the game board to the screen each frame, and for calling methods of the game model when receiving input. It would also update the game model each tick.Object Oriented design
Following the idea of separating the game model from the rendering, there are many places where the code could be made more object oriented. It is not mandatory to write code in an object oriented way, but it is especially helpful when you are a beginner, and I personally find that it makes code easier to write and understand.
Below the
SnakeWindow class there would be the SnakeGame class that would be responsible for the rules of the game. This class would have things like the speed of the game, or the speed that food spawns. It would have fields for the Snake object as well as the Board object. The window would update the SnakeGame each tick, and the game object would call the necessary methods of the snake and the board.The
Board object could have a simple int[][], and each position on the board could have a 0 for empty space, a 1 for a wall, and a 2 if a food is present. I think it would be best if it were responsible for the creation of food, so it could have a variable such as maxFood, and the Board would be called each tick to create the food.Eventually you could change these integers to something more self documenting, such as an enum with values for
FOOD, WALL, and EMPTY.The window class would get information about the
Snake and the Board from the game object and display this information on the screen. Related to this, I would remove all information about the dotSize from the game model and keep this information in the window. It's best to treat the board as discrete [x][y] locations and let the window be responsible for what size to draw them.I would put the collision methods for the walls and food in the
SnakeGame class, checking the positions of the snake against the positions of walls and food in the Board object. You could put the collision method for the snake against itself in this class, or alternatively put it inside the Snake class. For clarity though I would put it in the game class to keep all of the main game logic and rules in a central location.The Food class
private final int RANDOMPOSITION = 40;
int location = (int) (Math.random() * RANDOMPOSITION);
foodX = ((location * Board.getDotSize()));The fact that the max position of the food is 40 but then that number is multiplied by the dot size is confusing. It is also strange that the
Food object has a field for the max position on the board at all. It means that this class is dependent on information that is actually contained in another class. I think it would be better to initialize the food object with values for the width and height of the board.private Snake snake = new Snake();Shouldn't there only be one instance of the
Snake object? I'm not sure, but it appears that you are creating a snake object every time you create a food object. If you don't wantCode Snippets
Math.random() * RANDOMPOSITIONint randomNumber = this.random.nextInt(RANDOMPOSITION)public enum Direction {
RIGHT,
LEFT,
UP,
DOWN;
}if ((key == KeyEvent.VK_LEFT) && (!snake.isMovingRight())) {
snake.setMovingLeft(true);
snake.setMovingUp(false);
snake.setMovingDown(false);
}// Check to see if the game is running
private boolean inGame = true;Context
StackExchange Code Review Q#129719, answer score: 8
Revisions (0)
No revisions yet.