I'm making baby steps in java programming and I just ended coding basic game: Snake. Could you share with me what is needed to improve in this code? What about OOP here? **Code:** **GameBoard.java** import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.LinkedList; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class GameBoard extends JFrame { //setting board size public static int boardWidth = 1000; public static int boardHeight = 800; private JPanel scorePanel; public static void main(String[] args) { new GameBoard(); } public GameBoard() { super("Snake Game"); this.setSize(boardWidth, boardHeight); this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_LEFT) { DrawingTheBoard.theSnake.changeDirection(Direction.LEFT); } else if (e.getKeyCode() == KeyEvent.VK_UP) { DrawingTheBoard.theSnake.changeDirection(Direction.UP); } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { DrawingTheBoard.theSnake.changeDirection(Direction.RIGHT); } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { DrawingTheBoard.theSnake.changeDirection(Direction.DOWN); } } @Override public void keyReleased(KeyEvent e) { } }); DrawingTheBoard gamePanel = new DrawingTheBoard(); this.add(gamePanel, BorderLayout.CENTER); scorePanel = new JPanel(); scorePanel.add(gamePanel.scoreLabel, BorderLayout.CENTER); this.add(scorePanel, BorderLayout.PAGE_END); ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5); executor.scheduleAtFixedRate(new RepaintTheBoard(this), 0, 1000, TimeUnit.MILLISECONDS); // updating board each 100MS this.setVisible(true); } } class RepaintTheBoard implements Runnable { private GameBoard theBoard; public RepaintTheBoard(GameBoard theBoard) { this.theBoard = theBoard; } public void run() { theBoard.repaint(); } } class DrawingTheBoard extends JComponent { static Snake theSnake = new Snake(GameBoard.boardWidth, GameBoard.boardHeight); static SnakeState theState = new SnakeState(); private LinkedList<Point> body; private Point apple; public JLabel scoreLabel; public int score = 0; public DrawingTheBoard() { apple = new Apple().getPointOfApple(); scoreLabel = new JLabel("Score: " + Integer.toString(score)); scoreLabel.setFont(new Font("Serif", Font.PLAIN, 40)); } public void paint(Graphics g) { body = theSnake.getBody(); // making copy of List from Snake to draw it on screen Graphics2D g2D = (Graphics2D) g; g2D.setBackground(Color.BLACK); g2D.fillRect(0, 0, getWidth(), getHeight()); g2D.setPaint(Color.WHITE); for (Point partOfBody : body) { g2D.fillRect(partOfBody.getX(), partOfBody.getY(), 10, 10); // painting body of rectangles 10x10 } theSnake.update(apple); // checking if is gameOver if (theState.checkIfSnakeIsDead(body)) { theSnake.restartSnake(); score = 0; setScoreLabel(score); } if (theSnake.hasEaten()) { apple = new Apple().getPointOfApple(); // if snake has eaten apple creating new one theSnake.setHasEatenApple(false); score += 10; setScoreLabel(score); // adding 10 to score } g2D.fillRect(apple.getX(), apple.getY(), 10, 10); } public void setScoreLabel(int newScore) { scoreLabel.setText("Score: " + Integer.toString(newScore)); } } **Apple.java** import java.util.Random; public class Apple { private int bWidth = GameBoard.boardWidth; private int bHeight = GameBoard.boardHeight; private int randomXPos; private int randomYPos; private Point pointOfApple; Random r = new Random(); public Apple(){ randomXPos = r.nextInt((bWidth-10)/10)*10; randomYPos = r.nextInt((bHeight-110)/10)*10; pointOfApple = new Point(randomXPos,randomYPos); } public Point getPointOfApple(){ return pointOfApple; } public int getRandomXPos(){ return randomXPos; } public int getRandomYPos(){ return randomYPos; } } **Snake.java** import java.awt.*; import java.util.LinkedList; public class Snake extends Rectangle { private LinkedList<Point> body; // list holding points(x,y) of snake body private Direction headDirection; private boolean hasEatenApple = false; private int bWidth; private int bHeight; public Snake(int bWidth, int bHeight) { this.bWidth = bWidth; this.bHeight = bHeight; body = new LinkedList<>(); restartSnake(); } public LinkedList<Point> getBody() { return (LinkedList<Point>) body.clone(); } public void restartSnake() { body.clear(); //creating 3-part starting snake body.addFirst(new Point(this.bWidth / 2, this.bHeight / 2)); body.add(new Point((this.bWidth / 2) - 10, this.bHeight / 2)); body.add(new Point((this.bWidth / 2) - 20, this.bHeight / 2)); this.headDirection = Direction.RIGHT; } public void changeDirection(Direction theDirection) { if (theDirection != headDirection.opposite()) this.headDirection = theDirection; } //updating localisation of snake public void update(Point applePoint) { if (headDirection == Direction.DOWN) { addPartOfBody(0, 10, applePoint); } else if (headDirection == Direction.UP) { addPartOfBody(0, -10, applePoint); } else if (headDirection == Direction.LEFT) { addPartOfBody(-10, 0, applePoint); } else if (headDirection == Direction.RIGHT) { addPartOfBody(10, 0, applePoint); } } public void addPartOfBody(int x, int y, Point applePoint) { body.addFirst(new Point(body.get(0).getX() + x, body.get(0).getY() + y)); //if new point of head of snake is point of apple don't reduce last part of snake if (body.get(0).getX() != applePoint.getX() || body.get(0).getY() != applePoint.getY()) { body.removeLast(); } else { hasEatenApple = true; } } public boolean hasEaten(){ return hasEatenApple; } public void setHasEatenApple(boolean hasEatenApple){ this.hasEatenApple = hasEatenApple; } } **SnakeState.java** import java.util.LinkedList; public class SnakeState { private int bWidth = GameBoard.boardWidth; private int bHeight = GameBoard.boardHeight; private static boolean isDead = false; public boolean checkIfSnakeIsDead(LinkedList<Point> body) { //checking if head of snake is out of board if (body.get(0).getX() < 0 || body.get(0).getX() > bWidth-10 || body.get(0).getY() < 0 || body.get(0).getY() > bHeight-110) { return true; } //checking if head of the snake have collision with others parts of his body for (int i = 1; i < body.size(); i++) { if (body.get(i).getX() == body.get(0).getX() && body.get(i).getY() == body.get(0).getY()) return true; } return false; } } **Point.java** public class Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } } **Direction.java** public enum Direction { LEFT { Direction opposite() { return RIGHT; } }, RIGHT { Direction opposite() { return LEFT; } }, UP { Direction opposite() { return DOWN; } }, DOWN { Direction opposite() { return UP; } }; abstract Direction opposite(); }