From 6a2015a7192ec4735eab5c4a66f982ae424a2e52 Mon Sep 17 00:00:00 2001 From: George Bouroutzoglou Date: Sat, 23 Jan 2021 20:55:11 +0200 Subject: [PATCH 1/3] replaced int snake directions with directions enum --- src/KeyboardListener.java | 16 +++++------ src/SnakeDirections.java | 3 +++ src/ThreadsController.java | 54 +++++++++++++++++++------------------- 3 files changed, 38 insertions(+), 35 deletions(-) create mode 100644 src/SnakeDirections.java diff --git a/src/KeyboardListener.java b/src/KeyboardListener.java index 0271729..d4e459a 100644 --- a/src/KeyboardListener.java +++ b/src/KeyboardListener.java @@ -7,22 +7,22 @@ public void keyPressed(KeyEvent e){ switch(e.getKeyCode()){ case 39: // -> Right //if it's not the opposite direction - if(ThreadsController.directionSnake!=2) - ThreadsController.directionSnake=1; + if(ThreadsController.snakeDirection!=SnakeDirections.LEFT) + ThreadsController.snakeDirection=SnakeDirections.RIGHT; break; case 38: // -> Top - if(ThreadsController.directionSnake!=4) - ThreadsController.directionSnake=3; + if(ThreadsController.snakeDirection!=SnakeDirections.DOWN) + ThreadsController.snakeDirection=SnakeDirections.UP; break; case 37: // -> Left - if(ThreadsController.directionSnake!=1) - ThreadsController.directionSnake=2; + if(ThreadsController.snakeDirection!=SnakeDirections.RIGHT) + ThreadsController.snakeDirection=SnakeDirections.LEFT; break; case 40: // -> Bottom - if(ThreadsController.directionSnake!=3) - ThreadsController.directionSnake=4; + if(ThreadsController.snakeDirection!=SnakeDirections.UP) + ThreadsController.snakeDirection=SnakeDirections.DOWN; break; default: break; diff --git a/src/SnakeDirections.java b/src/SnakeDirections.java new file mode 100644 index 0000000..1934a97 --- /dev/null +++ b/src/SnakeDirections.java @@ -0,0 +1,3 @@ +public enum SnakeDirections { + UP, DOWN, LEFT, RIGHT +} diff --git a/src/ThreadsController.java b/src/ThreadsController.java index 3df2d3d..14b7e46 100644 --- a/src/ThreadsController.java +++ b/src/ThreadsController.java @@ -7,39 +7,39 @@ public class ThreadsController extends Thread { Tuple headSnakePos; int sizeSnake=3; long speed = 50; - public static int directionSnake ; + public static SnakeDirections snakeDirection; ArrayList positions = new ArrayList(); Tuple foodPosition; - - //Constructor of ControlleurThread + + //Constructor of ControlleurThread ThreadsController(Tuple positionDepart){ //Get all the threads Squares=Window.Grid; - + headSnakePos=new Tuple(positionDepart.x,positionDepart.y); - directionSnake = 1; + snakeDirection = SnakeDirections.RIGHT; //!!! Pointer !!!! Tuple headPos = new Tuple(headSnakePos.getX(),headSnakePos.getY()); positions.add(headPos); - + foodPosition= new Tuple(Window.height-1,Window.width-1); spawnFood(foodPosition); } - + //Important part : public void run() { while(true){ - moveInterne(directionSnake); + moveInterne(snakeDirection); checkCollision(); moveExterne(); deleteTail(); pauser(); } } - + //delay between each move of the snake private void pauser(){ try { @@ -48,7 +48,7 @@ private void pauser(){ e.printStackTrace(); } } - + //Checking if the snake bites itself or is eating private void checkCollision() { Tuple posCritique = positions.get(positions.size()-1); @@ -58,17 +58,17 @@ private void checkCollision() { stopTheGame(); } } - + boolean eatingFood = posCritique.getX()==foodPosition.y && posCritique.getY()==foodPosition.x; if(eatingFood){ System.out.println("Yummy!"); sizeSnake=sizeSnake+1; foodPosition = getValAleaNotInSnake(); - spawnFood(foodPosition); + spawnFood(foodPosition); } } - + //Stops The Game private void stopTheGame(){ System.out.println("COLISION! \n"); @@ -76,38 +76,38 @@ private void stopTheGame(){ pauser(); } } - + //Put food in a position and displays it private void spawnFood(Tuple foodPositionIn){ Squares.get(foodPositionIn.x).get(foodPositionIn.y).lightMeUp(1); } - + //return a position not occupied by the snake private Tuple getValAleaNotInSnake(){ Tuple p ; - int ranX= 0 + (int)(Math.random()*19); - int ranY= 0 + (int)(Math.random()*19); + int ranX= 0 + (int)(Math.random()*19); + int ranY= 0 + (int)(Math.random()*19); p=new Tuple(ranX,ranY); for(int i = 0;i<=positions.size()-1;i++){ if(p.getY()==positions.get(i).getX() && p.getX()==positions.get(i).getY()){ - ranX= 0 + (int)(Math.random()*19); - ranY= 0 + (int)(Math.random()*19); + ranX= 0 + (int)(Math.random()*19); + ranY= 0 + (int)(Math.random()*19); p=new Tuple(ranX,ranY); i=0; } } return p; } - + //Moves the head of the snake and refreshes the positions in the arraylist //1:right 2:left 3:top 4:bottom 0:nothing - private void moveInterne(int dir){ - switch(dir){ - case 4: + private void moveInterne(SnakeDirections direction){ + switch(direction){ + case DOWN: headSnakePos.ChangeData(headSnakePos.x,(headSnakePos.y+1)%20); positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); break; - case 3: + case UP: if(headSnakePos.y-1<0){ headSnakePos.ChangeData(headSnakePos.x,19); } @@ -116,17 +116,17 @@ private void moveInterne(int dir){ } positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); break; - case 2: + case LEFT: if(headSnakePos.x-1<0){ headSnakePos.ChangeData(19,headSnakePos.y); } else{ headSnakePos.ChangeData(Math.abs(headSnakePos.x-1)%20,headSnakePos.y); - } + } positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); break; - case 1: + case RIGHT: headSnakePos.ChangeData(Math.abs(headSnakePos.x+1)%20,headSnakePos.y); positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); break; From ebe607d95646b82fa9d5cadcdd80b4cac97b73b5 Mon Sep 17 00:00:00 2001 From: George Bouroutzoglou Date: Sat, 23 Jan 2021 22:28:45 +0200 Subject: [PATCH 2/3] added game restart loop in Main and minor changes to accommodate that in Window and ThreadsController. Ensured proper termination of the ThreadsController thread and timely disposing of previous JFrames --- src/Main.java | 60 ++++++++++++++++++++++++++++++++------ src/ThreadsController.java | 7 ++--- src/Window.java | 19 ++++++++---- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/Main.java b/src/Main.java index e2da510..9b0134c 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,17 +1,59 @@ -import javax.swing.JFrame; +import javax.swing.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; public class Main { + private static int attempt = 1; + private static Window currentWindow; + public static void main(String[] args) { + startGame(); + } + + private static void startGame() { + // game restart loop + do { + if (attempt > 1) { + clearBoard(); + } + //Creating the window with all its awesome snaky features + currentWindow = new Window(); + + //Setting up the window settings + currentWindow.setTitle("Snake attempt " + attempt++); + currentWindow.setSize(300,300); + currentWindow.setVisible(true); + currentWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + // Wait until the current game is finished + currentWindow.waitForGameEnd(); + + } while (restartRequested()); + clearBoard(); + } + + private static void clearBoard() { + currentWindow.dispose(); + } + + private static boolean restartRequested() { - //Creating the window with all its awesome snaky features - Window f1= new Window(); - - //Setting up the window settings - f1.setTitle("Snake"); - f1.setSize(300,300); - f1.setVisible(true); - f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + FutureTask restartQuestion = new FutureTask( + ()->JOptionPane.showConfirmDialog( + null, + "Play again?", + "You played yourself", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE)); + restartQuestion.run(); + try { + int response = restartQuestion.get(); + return response == JOptionPane.YES_OPTION; + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + return false; + } } } diff --git a/src/ThreadsController.java b/src/ThreadsController.java index 14b7e46..f8fb871 100644 --- a/src/ThreadsController.java +++ b/src/ThreadsController.java @@ -8,6 +8,7 @@ public class ThreadsController extends Thread { int sizeSnake=3; long speed = 50; public static SnakeDirections snakeDirection; + private boolean gameOver = false; ArrayList positions = new ArrayList(); Tuple foodPosition; @@ -31,7 +32,7 @@ public class ThreadsController extends Thread { //Important part : public void run() { - while(true){ + while(!gameOver){ moveInterne(snakeDirection); checkCollision(); moveExterne(); @@ -72,9 +73,7 @@ private void checkCollision() { //Stops The Game private void stopTheGame(){ System.out.println("COLISION! \n"); - while(true){ - pauser(); - } + gameOver = true; } //Put food in a position and displays it diff --git a/src/Window.java b/src/Window.java index 518fa9e..b572ea5 100644 --- a/src/Window.java +++ b/src/Window.java @@ -10,9 +10,10 @@ class Window extends JFrame{ public static ArrayList> Grid; public static int width = 20; public static int height = 20; + private ThreadsController controllerThread; public Window(){ - + // Creates the arraylist that'll contain the threads Grid = new ArrayList>(); ArrayList data; @@ -26,7 +27,7 @@ public Window(){ } Grid.add(data); } - + // Setting up the layout of the panel getContentPane().setLayout(new GridLayout(20,20,0,0)); @@ -36,13 +37,13 @@ public Window(){ getContentPane().add(Grid.get(i).get(j).square); } } - + // initial position of the snake Tuple position = new Tuple(10,10); // passing this value to the controller - ThreadsController c = new ThreadsController(position); + controllerThread = new ThreadsController(position); //Let's start the game now.. - c.start(); + controllerThread.start(); // Links the window to the keyboardlistenner. this.addKeyListener((KeyListener) new KeyboardListener()); @@ -54,4 +55,12 @@ public Window(){ //c2.start(); } + + public void waitForGameEnd() { + try { + controllerThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } From 8e464cf15f52852693d458f4f2331b5db9f0ec9a Mon Sep 17 00:00:00 2001 From: George Bouroutzoglou Date: Sat, 23 Jan 2021 22:32:54 +0200 Subject: [PATCH 3/3] made the game window centered by default Quality of life improvement to avoid players having to center manually after restarts --- src/Main.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Main.java b/src/Main.java index 9b0134c..10ad15c 100644 --- a/src/Main.java +++ b/src/Main.java @@ -23,6 +23,7 @@ private static void startGame() { //Setting up the window settings currentWindow.setTitle("Snake attempt " + attempt++); currentWindow.setSize(300,300); + currentWindow.setLocationRelativeTo(null); currentWindow.setVisible(true); currentWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);