The Snake Game Using Java

Awannerd
5 min readDec 3, 2023

--

# Introduction :-

In the realm of classic arcade games, the Snake game stands out as an enduring favorite. Its simple yet addictive gameplay has transcended generations. In this journey, we’ll explore the development of a Snake game using Java and the Swing library — a foray into the fundamentals of game programming.

java class for a snake game :-

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;

public class Game extends JPanel implements ActionListener {
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
static final int DELAY = 75;
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
int bodyParts = 6;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random;

Game() {
random = new Random();
this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
this.setBackground(Color.black);
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
}
// add retry button

public void startGame() {
newApple();
running = true;
timer = new Timer(DELAY, this);
timer.start();
}

public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}

public void draw(Graphics g) {
if (running) {
/*
* for(int i=0;i<SCREEN_HEIGHT/UNIT_SIZE;i++){
* g.drawLine(i*UNIT_SIZE, 0, i*UNIT_SIZE, SCREEN_HEIGHT);
* g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH, i*UNIT_SIZE);
* }
*/
g.setColor(Color.red);
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);

for (int i = 0; i < bodyParts; i++) {
if (i == 0) {
g.setColor(Color.green);
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
} else {
g.setColor(new Color(45, 180, 0));
// g.setColor(new
// Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
}
}
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("Score: " + applesEaten, (SCREEN_WIDTH - metrics.stringWidth("Score: " + applesEaten)) / 2,
g.getFont().getSize());
} else

{
gameOver(g);
}
}

public void newApple() {
appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
}

public void move() {
for (int i = bodyParts; i > 0; i--) {
x[i] = x[i - 1];
y[i] = y[i - 1];
}

switch (direction) {
case 'U':
y[0] = y[0] - UNIT_SIZE;
break;
case 'D':
y[0] = y[0] + UNIT_SIZE;
break;
case 'L':
x[0] = x[0] - UNIT_SIZE;
break;
case 'R':
x[0] = x[0] + UNIT_SIZE;
break;
}
}

public void checkApple() {
if ((x[0] == appleX) && (y[0] == appleY)) {
bodyParts++;
applesEaten++;
newApple();
}
}

public void checkCollisions() {
// checks if head collides with body
for (int i = bodyParts; i > 0; i--) {
if ((x[0] == x[i]) && (y[0] == y[i])) {
running = false;
}
}
// check if head touches left border
if (x[0] < 0) {
running = false;
}
// check if head touches right border
if (x[0] > SCREEN_WIDTH) {
running = false;
}
// check if head touches top border
if (y[0] < 0) {
running = false;
}
// check if head touches bottom border
if (y[0] > SCREEN_HEIGHT) {
running = false;
}
if (!running) {
timer.stop();
}
}

public void gameOver(Graphics g) {
// Score
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("Score: " + applesEaten, (SCREEN_WIDTH - metrics1.stringWidth("Score: " + applesEaten)) / 2,
g.getFont().getSize());
// Game Over text
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 75));
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("Game Over", (SCREEN_WIDTH - metrics2.stringWidth("Game Over")) / 2, SCREEN_HEIGHT / 2);
}

@Override
public void actionPerformed(ActionEvent e) {
if (running) {
move();
checkApple();
checkCollisions();
}
repaint();
}

public class MyKeyAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_RIGHT:
if (direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_UP:
if (direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_DOWN:
if (direction != 'U') {
direction = 'D';
}
break;
}
}
}
}

Main method

import javax.swing.JFrame;

public class LaunchGame {
public static void main(String[] args) {
JFrame frame = new JFrame();
Game Game = new Game();
frame.add(Game);
frame.setTitle("Snake");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}

# Concepts used in the GAME :-

Setting the Stage

Our canvas is a Java Swing application, providing a graphical user interface for the Snake game. The game unfolds within a grid, where a snake maneuvers to consume apples and grow longer. Let’s delve into the key components that bring this digital serpent to life.

The Game Class

At the core of our creation is the Game class. It encapsulates the game logic, handling everything from snake movement to collision detection. Constants define the game’s dimensions, and arrays track the coordinates of the snake’s body parts. A timer ensures regular updates, triggering the actionPerformed method.

Initialization Rituals

Upon initiation, the game initializes its state, creates a randomizer for apple placement, and sets up the graphical interface. The user’s keyboard input is captured through a custom KeyAdapter — MyKeyAdapter — which allows the snake to change direction based on arrow key presses.

Artistry in Motion

The paintComponent method serves as our artistic canvas. It draws the snake’s body, apples, and the ever-increasing score. A carefully crafted algorithm ensures that each movement of the snake is mirrored visually on the screen. The game doesn’t just run; it dances.

A Dance of Logic

Our snake’s ballet involves intricate logic. The move method elegantly updates the snake’s position, and checkApple verifies if an apple has been consumed, signaling the snake to grow. Collisions with the snake’s own body or the screen borders are meticulously monitored by the checkCollisions method.

The Grand Finale: Game Over

When the dance concludes, and the snake meets its demise, the gameOver method takes center stage. It displays the final score with a touch of flair, signaling the end of the performance.

# Conclusion:-

In crafting this digital symphony, we’ve stitched together the fabric of a classic Snake game using Java and Swing. The intricacies of user input, game state management, and graphical representation have converged into a nostalgic yet timeless experience. This journey through the code has not just unveiled the mechanics; it has celebrated the artistry of game development.

As we bid farewell to our digital serpent, we acknowledge the enduring allure of these classic games, forever etched in the annals of gaming history. The journey continues, and the dance of code persists — always evolving, always engaging.

Thank you for joining this exploration of Java game development. If you enjoyed this journey, stay tuned for more adventures in the vast landscape of programming.

THE GAMEE

--

--