Last active
April 2, 2021 09:14
-
-
Save Iranon/9e55883215922d44a6dcdb9e976d437e to your computer and use it in GitHub Desktop.
A Java exercise that aims to reproduce the classic snake game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Random; | |
public class Garden { | |
private Unit[][] grid; //The grid represents the game field | |
private int[] gridSize = new int[2]; | |
private boolean isGameOver = false; | |
private String lastMove = "0"; | |
//Create a new Snake instance defining initial length and coordinates | |
private Snake snakePlayer = new Snake(3, 7, 2); | |
//Constructor | |
public Garden (int r, int c) { | |
this.grid = new Unit[r][c]; | |
this.gridSize[0] = r; | |
this.gridSize[1] = c; | |
for (int y = 0; y < this.grid.length; y++) { | |
for (int x = 0; x < c; x++) { | |
this.grid[y][x] = new Unit(x, y); | |
} | |
} | |
} | |
public void spawnFood() { | |
Random random = new Random(); | |
//Defining food coordinates range | |
int foodX = Math.max(1, random.nextInt(this.gridSize[1])-1); | |
int foodY = Math.max(1, random.nextInt(this.gridSize[0])-1); | |
//Remember this.grid[y][x] ( rows(y) come before columns(c) ) | |
if (!this.snakePlayer.getSnakeBody().contains(this.grid[foodY][foodX])) { | |
this.grid[foodY][foodX].setFood(true); | |
} | |
else { | |
spawnFood(); | |
} | |
} | |
public boolean limitBreak(int xCoord, int yCoord) { | |
//Remember that in this.grid[y][x] the 'y'[1](rows) comes before than 'x'[0](columns) | |
if (xCoord < 0 || xCoord >= this.gridSize[1] || | |
yCoord < 0 || yCoord >= this.gridSize[0]) { | |
System.out.println("- GAME OVER -"); | |
this.isGameOver = true; | |
return true; | |
} | |
return false; | |
} | |
public void snakeMovement(char m) { | |
switch (m) { | |
//The first 'if' statement verify movement conditions and call the gameOver function | |
case 'w' : | |
if (this.limitBreak(this.snakePlayer.getSnakeHead().getCoords()[0], | |
this.snakePlayer.getSnakeHead().getCoords()[1] - 1) || | |
this.lastMove.charAt(0) == 's') { | |
return; | |
} | |
this.snakePlayer.move(this.snakePlayer.getSnakeHead().getCoords()[0], | |
this.snakePlayer.getSnakeHead().getCoords()[1] - 1); | |
this.lastMove = String.valueOf(m); | |
break; | |
case 'a' : | |
if (this.limitBreak(this.snakePlayer.getSnakeHead().getCoords()[0] - 1, | |
this.snakePlayer.getSnakeHead().getCoords()[1]) || | |
this.lastMove.charAt(0) == 'd') { | |
return; | |
} | |
this.snakePlayer.move(this.snakePlayer.getSnakeHead().getCoords()[0] - 1, | |
this.snakePlayer.getSnakeHead().getCoords()[1]); | |
this.lastMove = String.valueOf(m); | |
break; | |
case 's' : | |
if (this.limitBreak(this.snakePlayer.getSnakeHead().getCoords()[0], | |
this.snakePlayer.getSnakeHead().getCoords()[1] + 1) || | |
this.lastMove.charAt(0) == 'w') { | |
return; | |
} | |
this.snakePlayer.move(this.snakePlayer.getSnakeHead().getCoords()[0], | |
this.snakePlayer.getSnakeHead().getCoords()[1] + 1); | |
this.lastMove = String.valueOf(m); | |
break; | |
case 'd' : | |
if (this.limitBreak(this.snakePlayer.getSnakeHead().getCoords()[0] + 1, | |
this.snakePlayer.getSnakeHead().getCoords()[1]) || | |
this.lastMove.charAt(0) == 'a') { | |
return; | |
} | |
this.snakePlayer.move(this.snakePlayer.getSnakeHead().getCoords()[0] + 1, | |
this.snakePlayer.getSnakeHead().getCoords()[1]); | |
this.lastMove = String.valueOf(m); | |
break; | |
} | |
//Eating if the cell has food | |
//Remember this.grid[y][x] ('y' comes before than 'x') | |
if (this.grid[this.snakePlayer.getSnakeHead().getCoords()[1]] | |
[this.snakePlayer.getSnakeHead().getCoords()[0]].getFood()) { | |
//Remove food | |
this.grid[this.snakePlayer.getSnakeHead().getCoords()[1]] | |
[this.snakePlayer.getSnakeHead().getCoords()[0]].setFood(false); | |
//Add element body in the right direction (it depends on the last movement) | |
switch (m) { | |
case 'w' : | |
this.snakePlayer.addElement(this.snakePlayer.getSnakeHead().getCoords()[0], | |
this.snakePlayer.getSnakeHead().getCoords()[1] - 1); | |
break; | |
case 'a' : | |
this.snakePlayer.addElement(this.snakePlayer.getSnakeHead().getCoords()[0]-1, | |
this.snakePlayer.getSnakeHead().getCoords()[1]); | |
break; | |
case 's' : | |
this.snakePlayer.addElement(this.snakePlayer.getSnakeHead().getCoords()[0], | |
this.snakePlayer.getSnakeHead().getCoords()[1] + 1); | |
break; | |
case 'd' : | |
this.snakePlayer.addElement(this.snakePlayer.getSnakeHead().getCoords()[0]+1, | |
this.snakePlayer.getSnakeHead().getCoords()[1]); | |
break; | |
} | |
//Respawn food | |
this.spawnFood(); | |
} | |
} | |
public boolean gameOver() { | |
if (this.snakePlayer.checkHeadWithBody()) { | |
this.isGameOver = true; | |
System.out.println("((( Self-Injury )))"); | |
} | |
return this.isGameOver; | |
} | |
@Override | |
public String toString() { | |
// ❑ ▣ ● ⊙ | |
String out = ""; | |
if (this.isGameOver) { | |
return "| You Lose |"; | |
} | |
for (int y = 0; y < this.grid.length; y++) { | |
for (int x = 0; x < this.grid[y].length; x++) { | |
if (snakePlayer.getSnakeBody().contains(this.grid[y][x])) { | |
out += (snakePlayer.getSnakeHead().equals(this.grid[y][x])) ? " ● " : " ▣ "; | |
} | |
else { | |
out += (this.grid[y][x].getFood()) ? " ⊙ " : " ❑ "; | |
} | |
} | |
out += "\n"; | |
} | |
return out; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Scanner; | |
public class Main { | |
public static void main(String[] args) { | |
Scanner userInput = new Scanner(System.in); | |
//Creating the game field | |
Garden gard = new Garden(8, 15); | |
//First food spawn | |
gard.spawnFood(); | |
System.out.println(gard); | |
//Playing | |
while(!gard.gameOver()) { | |
System.out.println("Digita mossa: "); | |
char playerMove = userInput.next().charAt(0); | |
gard.snakeMovement(playerMove); | |
System.out.println(gard); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
public class Snake { | |
private ArrayList<Unit> snakeBody = new ArrayList<Unit>(); | |
//Constructor | |
public Snake(int sl, int sx, int sy) { | |
//Initial size and coordinates | |
for (int x = 0; x < sl; x++) { | |
this.snakeBody.add(new Unit(sx-x, sy)); //Add new elements behind the first one (sx-x) | |
} | |
//Set snake head | |
this.snakeBody.get(0).setHead(true); | |
} | |
public ArrayList<Unit> getSnakeBody() { | |
return this.snakeBody; | |
} | |
public Unit getSnakeHead() { | |
//Return the head in order to draw it correctly | |
return this.snakeBody.get(0); | |
} | |
public boolean checkHeadWithBody() { | |
for (int i = 1; i < this.snakeBody.size(); i++) { | |
//Comparing head and body elements coordinates | |
if (this.getSnakeHead().getCoords()[0] == this.snakeBody.get(i).getCoords()[0] && | |
this.getSnakeHead().getCoords()[1] == this.snakeBody.get(i).getCoords()[1]) { | |
return true; | |
} | |
} | |
return false; | |
} | |
public void move(int x, int y) { | |
//The movement is based on the head coordinates | |
int[] previousPos = {this.getSnakeHead().getCoords()[0], this.getSnakeHead().getCoords()[1]}; | |
int[] posMemo = new int[2]; | |
this.getSnakeHead().setCoords(x, y); //Set new head position | |
//Shift body elements | |
for (int i = 1; i < snakeBody.size(); i++) { | |
posMemo[0] = this.snakeBody.get(i).getCoords()[0]; | |
posMemo[1] = this.snakeBody.get(i).getCoords()[1]; | |
this.snakeBody.get(i).setCoords(previousPos[0], previousPos[1]); | |
previousPos[0] = posMemo[0]; | |
previousPos[1] = posMemo[1]; | |
} | |
} | |
//Growth function | |
public void addElement(int x, int y) { | |
this.snakeBody.add(0, new Unit(x, y)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Unit { | |
private int[] coords = new int[2]; | |
private boolean head = false; | |
private boolean food = false; | |
//Constructor | |
public Unit(int x, int y) { | |
this.coords[0] = x; | |
this.coords[1] = y; | |
} | |
public void setHead(boolean value) { | |
this.head = value; | |
} | |
public void setFood(boolean value) { | |
this.food = value; | |
} | |
public boolean getFood() { | |
return this.food; | |
} | |
public void setCoords(int x, int y) { | |
this.coords[0] = x; | |
this.coords[1] = y; | |
} | |
public int[] getCoords() { | |
return this.coords; | |
} | |
@Override | |
public boolean equals(Object o) { | |
Unit objectIn = (Unit) o; | |
if (objectIn.getCoords()[0] == this.coords[0] | |
&& objectIn.getCoords()[1] == this.coords[1]) { | |
return true; | |
} | |
else { | |
return false; | |
} | |
} | |
@Override | |
public String toString() { | |
return "X coord : " + this.coords[0] + "\n" + "Y coord: " + this.coords[1]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment