Snake Game
Preview

Code
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class SnakeGame {
public static void main(String[] args) {
SnakeFrame frame = new SnakeFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class StatusRunnable implements Runnable {
public StatusRunnable(Snake snake, JLabel statusLabel, JLabel scoreLabel) {
this.snake = snake;
this.statusLabel = statusLabel;
this.scoreLabel = scoreLabel;
}
public void run() {
String sta = "";
String spe = "";
while (true) {
switch (snake.status) {
case Snake.RUNNING:
sta = "Running";
break;
case Snake.PAUSED:
sta = "Paused";
break;
case Snake.GAMEOVER:
sta = "Game Over";
break;
}
statusLabel.setText("Status: " + sta);
scoreLabel.setText("Score: " + snake.score);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private JLabel scoreLabel;
private JLabel statusLabel;
private Snake snake;
}
class SnakeRunnable implements Runnable {
public SnakeRunnable(Snake snake, Component component) {
this.snake = snake;
this.component = component;
}
public void run() {
while (true) {
try {
snake.move();
component.repaint();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Snake snake;
private Component component;
}
class Snake {
boolean isRun = false;
ArrayList<Node> body = new ArrayList<>();
Node food = null;
int direction;
int score;
int status;
int speed;
public static final int SLOW = 500;
public static final int MID = 300;
public static final int FAST = 100;
public static final int RUNNING = 1;
public static final int PAUSED = 2;
public static final int GAMEOVER = 3;
public static final int LEFT = 1;
public static final int UP = 2;
public static final int RIGHT = 3;
public static final int DOWN = 4;
public Snake() {
speed = Snake.SLOW;
score = 0;
isRun = false;
status = Snake.PAUSED;
direction = Snake.RIGHT;
body = new ArrayList<>();
body.add(new Node(60, 20));
body.add(new Node(40, 20));
body.add(new Node(20, 20));
makeFood();
}
private boolean isEaten() {
Node head = body.get(0);
if (direction == Snake.RIGHT && (head.x + Node.W) == food.x && head.y == food.y) {
return true;
} else if (direction == Snake.LEFT && (head.x - Node.W) == food.x && head.y == food.y) {
return true;
} else if (direction == Snake.UP && head.x == food.x && (head.y - Node.H) == food.y) {
return true;
} else if (direction == Snake.DOWN && head.x == food.x && (head.y + Node.H) == food.y) {
return true;
} else {
return false;
}
}
private boolean isCollision() {
Node node = body.get(0);
if (direction == Snake.RIGHT && node.x == 280) {
return true;
} else if (direction == Snake.LEFT && node.x == 0) {
return true;
} else if (direction == Snake.UP && node.y == 0) {
return true;
} else if (direction == Snake.DOWN && node.y == 380) {
return true;
}
Node temp = null;
int i = 0;
for (i = 3; i < body.size(); i++) {
temp = body.get(i);
if (node.x == temp.x && node.y == temp.y) {
return true;
}
}
if (i == body.size()) {
return true;
} else {
return false;
}
}
public void makeFood() {
Node node = new Node(0, 0);
boolean isInBody = true;
int x = 0;
int y = 0;
int X = 0;
int Y = 0;
int i = 0;
while (isInBody) {
x = (int) (Math.random() * 15);
y = (int) (Math.random() * 20);
X = x * Node.W;
Y = y * Node.H;
for (i = 0; i < body.size(); i++) {
if (X == body.get(i).x && Y == body.get(i).y) {
break;
}
}
if (i < body.size()) {
isInBody = true;
} else {
isInBody = false;
}
}
food = new Node(X, Y);
}
public void changeDirection(int newDer) {
if (direction % 2 != newDer % 2) {
direction = newDer;
}
}
public void move() {
if (isEaten()) {
body.add(0, food);
score += 10;
makeFood();
// } else if (isCollision()) {
// isRun = false;
// status = Snake.GAMEOVER;
} else if (isRun) {
Node node = body.get(0);
int X = node.x;
int Y = node.y;
switch (direction) {
case Snake.LEFT:
X -= Node.W;
break;
case Snake.UP:
Y -= Node.H;
break;
case Snake.RIGHT:
X += Node.W;
break;
case Snake.DOWN:
Y += Node.H;
break;
}
body.add(0, new Node(X, Y));
body.remove(body.size() - 1);
}
}
}
class Node {
public static final int W = 20;
public static final int H = 20;
public int x;
public int y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
class SnakePanel extends JPanel {
Snake snake;
public SnakePanel(Snake snake) {
this.snake = snake;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Node node = null;
for (int i = 0; i < snake.body.size(); i++) {
g.setColor(Color.BLACK);
node = snake.body.get(i);
g.fillRect(node.x, node.y, Node.W, Node.H);
}
node = snake.food;
g.setColor(Color.RED);
g.fillRect(node.x, node.y, Node.W, Node.H);
}
}
class SnakeFrame extends JFrame {
private JLabel statusLabel;
private JLabel speedLabel;
private JLabel scoreLabel;
private JPanel snakePanel;
private Snake snake;
private JMenuBar bar;
JMenu gameMenu;
JMenu helpMenu;
JMenu speedMenu;
JMenuItem newItem;
JMenuItem pauseItem;
JMenuItem beginItem;
JMenuItem helpItem;
JMenuItem aboutItem;
JMenuItem slowItem;
JMenuItem midItem;
JMenuItem fastItem;
public SnakeFrame() {
init();
ActionListener l = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == pauseItem) {
snake.isRun = false;
}
if (e.getSource() == beginItem) {
snake.isRun = true;
}
if (e.getSource() == newItem) {
newGame();
}
// menu controller speed
if (e.getSource() == slowItem) {
snake.speed = Snake.SLOW;
speedLabel.setText("Speed: Slow");
}
if (e.getSource() == midItem) {
snake.speed = Snake.MID;
speedLabel.setText("Speed: Mid");
}
if (e.getSource() == fastItem) {
snake.speed = Snake.FAST;
speedLabel.setText("Speed: Fast");
}
}
};
pauseItem.addActionListener(l);
beginItem.addActionListener(l);
newItem.addActionListener(l);
aboutItem.addActionListener(l);
slowItem.addActionListener(l);
midItem.addActionListener(l);
fastItem.addActionListener(l);
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case java.awt.event.KeyEvent.VK_LEFT:
snake.changeDirection(Snake.LEFT);
break;
case java.awt.event.KeyEvent.VK_UP:
snake.changeDirection(Snake.UP);
break;
case java.awt.event.KeyEvent.VK_RIGHT:
snake.changeDirection(Snake.RIGHT);
break;
case java.awt.event.KeyEvent.VK_DOWN:
snake.changeDirection(Snake.DOWN);
break;
case java.awt.event.KeyEvent.VK_SPACE:
if (snake.isRun) {
snake.isRun = false;
snake.status = Snake.PAUSED;
} else {
snake.isRun = true;
snake.status = Snake.RUNNING;
}
}
}
public void keyReleased(java.awt.event.KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
});
}
private void init() {
speedLabel = new JLabel();
snake = new Snake();
setSize(380, 460);
setLayout(null);
this.setResizable(false);
bar = new JMenuBar();
gameMenu = new JMenu("Game");
newItem = new JMenuItem("New Game");
gameMenu.add(newItem);
pauseItem = new JMenuItem("Pause");
gameMenu.add(pauseItem);
beginItem = new JMenuItem("Continue");
gameMenu.add(beginItem);
helpMenu = new JMenu("Help");
aboutItem = new JMenuItem("About");
helpMenu.add(aboutItem);
speedMenu = new JMenu("Speed");
slowItem = new JMenuItem("Slow");
midItem = new JMenuItem("Mid");
fastItem = new JMenuItem("Fast");
speedMenu.add(slowItem);
speedMenu.add(midItem);
speedMenu.add(fastItem);
bar.add(gameMenu);
bar.add(helpMenu);
bar.add(speedMenu);
this.setJMenuBar(bar);
statusLabel = new JLabel();
scoreLabel = new JLabel();
snakePanel = new JPanel();
snakePanel.setBounds(0, 0, 300, 400);
snakePanel.setBorder(BorderFactory.createLineBorder(Color.darkGray));
add(snakePanel);
statusLabel.setBounds(300, 25, 60, 20);
add(statusLabel);
scoreLabel.setBounds(300, 20, 60, 20);
add(scoreLabel);
JLabel temp = new JLabel("Status");
temp.setBounds(310, 5, 60, 20);
add(temp);
temp = new JLabel("Score");
temp.setBounds(310, 105, 60, 20);
add(temp);
temp = new JLabel("Speed");
temp.setBounds(310, 55, 60, 20);
add(temp);
speedLabel.setBounds(310, 75, 60, 20);
add(speedLabel);
}
private void newGame() {
this.remove(snakePanel);
this.remove(statusLabel);
this.remove(scoreLabel);
speedLabel.setText("Slow");
statusLabel = new JLabel();
scoreLabel = new JLabel();
snakePanel = new JPanel();
snake = new Snake();
snakePanel = new SnakePanel(snake);
snakePanel.setBounds(0, 0, 380, 400);
snakePanel.setBorder(BorderFactory.createLineBorder(Color.darkGray));
Runnable r1 = new SnakeRunnable(snake, snakePanel);
Runnable r2 = new StatusRunnable(snake, statusLabel, scoreLabel);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
add(snakePanel);
statusLabel.setBounds(310, 25, 60, 20);
add(statusLabel);
scoreLabel.setBounds(310, 125, 60, 20);
add(scoreLabel);
}
}