Tutorial [Java]: Creating a Snake Game [Part 06] - Fruit and Scoring

Note: I have completely rewritten and improved this game. Most of my traffic comes from these posts, so I've not deleted them. Please use the new version which can be found here.

Games get boring rather quickly if there's no goal to it. For this reason, our game is about as entertaining as watching paint dry. To change this, we need to introduce the scoring system, and a steadily increasing difficulty. This section solves both of these problems in one quick swoop.
Like the last section on controller input, this section will probably be quite short as most of the groundwork has been setup for us in previous chapters. The main goals for this chapter are to spawn fruit randomly around the board, increment the score by 10 points each time, and to increase the length of the snake by one each round.

Let's start by creating a new variable in the Engine class called score. We can use this variable to track how many points we have earned throughout the course of the game, which will be displayed in the top left corner of the screen.

private int score;

Next, we need to create a way of creating fruit. This can easily be accomplished by generating a random number between 0 and the number of tiles on the board minus the size of the snake. Then we traverse the board and find the nth EMPTY tile on the board, and set it to FRUIT. This way, we won't have an issue with  the game hanging when players get far into the game because we can't find an empty tile randomly. In the Snake class, we need to create a method that will return the number of points that exist in the list.

public int getSnakeLength() {
 return points.size();

Now we can start working on generating fruit! Since I already explained the process for generating the fruit's location, I'll just post the code and let you have a look for yourself.

private void spawnFruit() {
 int random = (int)(Math.random() * ((GameBoard.MAP_SIZE * GameBoard.MAP_SIZE)
- snake.getSnakeLength()));
 int emptyFound = 0;
 int index = 0;
 while(emptyFound < random) {
  if(board.getTile(index % GameBoard.MAP_SIZE, index / GameBoard.MAP_SIZE)
.equals(TileType.EMPTY)) {
 board.setTile(index % GameBoard.MAP_SIZE, index / GameBoard.MAP_SIZE, TileType.FRUIT);

If you recall, we added a call to updateSnake in the update method of the Engine class at the end of Part 4. The method returns the TileType that was at the location of the snake's head before it moved. We can use this to determine what type of tile we hit. Let's go back to the Engine's update method and implement scoring now.

private void update() {
 TileType snakeTile = snake.updateSnake();
 if(snakeTile == null || snakeTile.equals(TileType.SNAKE)) {
  //We're dead, but wont implement this until later.
 } else if(snakeTile.equals(TileType.FRUIT)) {
  score += 10;

The last thing we need to do with scoring is display our score onto the screen. We can do this in the render method rather easily.

private static final Font SMALL_FONT = new Font("Times New Roman", Font.BOLD, 20);

private void render(Graphics2D g) {

 g.drawString("Score: " + score, 10, 20);

Now our game is really starting to shape up. We have controls, scoring, and difficulty progression. In order to kick the game off, we need to create a method that we can call whenever we want to start a new game. The method needs to reset the board, snake, and score. Afterwards, we need to spawn a new fruit and let the user start playing. We've already got all of this setup, so let's just create a new method for calling all of the methods at once.

private void resetGame() {
 score = 0;

Now all we need to do is add a call to this method in the Engine's constructor, and we're good to go, with the exception of death, the game is pretty much finished. The next part of the tutorial will finish the game up, and provide the full source code for the game, so look out for it.

Posted in , , , , , . Bookmark the permalink. RSS feed for this post.

Leave a Reply


Swedish Greys - a WordPress theme from Nordic Themepark. Converted by LiteThemes.com.