Experiment 2 development of Snake game

1. Project overview

1.1 project objectives and main contents
Objective: the overall program is bug free and realizes the basic functions of greedy Snake game;

1) To achieve the basic functions of the greedy Snake game, a "food" called beans appears randomly on the screen. Players can use the up, down, left and right keys to control the movement of the "snake". After the "snake" eats the "beans", the "snake" body lengthens by one section, and the score increases. The "snake" touches the boundary or the head of the snake collides with the body of the snake. The "snake" dies, and the game is over.

2) The interactive interface should be designed with the options of start key, pause key and stop exit, so as to control the process of the game. Calculate the score of the beans eaten by the snake. You can set the game speed, game music and other expansion elements.

Use Java programming language to develop on IntelliJ IDEA Community Edition.

Main content: a "food" called beans randomly appears on the screen. Control the movement of the "snake" up, down, left and right. After eating the "beans", the body of the "snake" is lengthened and the score increases. When the "snake" touches the boundary or, the head of the snake collides with the body of the snake, the snake dies and the game ends. Design the initial welcome interface, game interface and game end interface for the game.

2. Project design


3. Program operation results and analysis:
 

analysis;

It can realize the basic functions of Snake game;  

It has the function of scoring (add 1 point for each food), and the score for starting the game is zero. The game start interface, the space controls the pause / start function of the game, and the WASD controls the direction. The game end interface.

Complete code

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

class Grid {
    int x;
    int y;

    public Grid(int x0, int y0) {
        x = x0;
        y = y0;
    }
}

public class Snakes extends JComponent {
    private final int MAX_SIZE = 400;//The longest body of a snake is 400 knots
    private final Grid temp = new Grid(0, 0);
    private final Grid temp2 = new Grid(0, 0);
    private Grid head = new Grid(227, 170);//The position of the head is initialized to (227170)
    private final Grid[] body = new Grid[MAX_SIZE];
    private boolean first_launch = false;
    private int body_length = 5;//Body length initialized to 5
    private boolean isRun = true;
    private int RandomX, RandomY;
    private Thread run;
    private String direction = "R";//Default right
    private String current_direction = "R";//Current direction
    private final JLabel Score = new JLabel("0");
    private final JLabel Time = new JLabel("");
    private int hour = 0;
    private int min = 0;
    private int sec = 0;
    private boolean pause = false;


    public Snakes() {
        //layout
        JLabel label = new JLabel("POINT:");
        add(label);
        label.setBounds(5, 15, 80, 20);
        label.setFont(new Font("Microsoft YaHei ", Font.PLAIN, 15));
        add(Score);
        Score.setBounds(90, 15, 80, 20);
        Score.setFont(new Font("Microsoft YaHei ", Font.PLAIN, 15));
        JLabel label2 = new JLabel("TIME:");
        add(label2);
        label2.setBounds(5, 45, 80, 20);
        label2.setFont(new Font("Microsoft YaHei ", Font.PLAIN, 15));
        add(Time);
        Time.setBounds(90, 45, 80, 20);
        Time.setFont(new Font("Microsoft YaHei ", Font.PLAIN, 15));

        for (int i = 0; i < MAX_SIZE; i++) {
            body[i] = new Grid(0, 0);
        }

        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);

                if (e.getKeyCode() == KeyEvent.VK_D) {
                    if (isRun && !current_direction.equals("L")) {
                        direction = "R";
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_A) {
                    if (isRun && !current_direction.equals("R")) {
                        direction = "L";
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_W) {
                    if (isRun && !current_direction.equals("D")) {
                        direction = "U";
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_S) {
                    if (isRun && !current_direction.equals("U")) {
                        direction = "D";
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    direction = "R";//Default right
                    current_direction = "R";//Current direction
                    first_launch = false;
                    isRun = true;
                    body_length = 5;
                    head = new Grid(227, 100);
                    Score.setText("0");
                    hour = 0;
                    min = 0;
                    sec = 0;
                    for (int i = 0; i < MAX_SIZE; i++) {
                        body[i].x = 0;
                        body[i].y = 0;
                    }


                    System.out.println("Start again");
                }
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    if (!pause)//suspend
                    {
                        pause = true;
                        isRun = false;
                    } else//start
                    {
                        pause = false;
                        isRun = true;
                    }
                }
            }
        });

        new Timer();

        setFocusable(true);
    }

    public void paintComponent(Graphics g1) {
        super.paintComponent(g1);
        Graphics2D g = (Graphics2D) g1;

        //Draw head
        g.setColor(Color.BLACK);
        g.fillRoundRect(head.x, head.y, 20, 20, 5, 5);
        if (!first_launch) {
            //Initialize body
            int x = head.x;
            for (int i = 0; i < body_length; i++) {
                x -= 22;//The distance between two adjacent blocks is 2 pixels, and the width of each block is 20 pixels
                body[i].x = x;
                body[i].y = head.y;
                g.fillRoundRect(body[i].x, body[i].y, 20, 20, 5, 5);
            }
            //Initialize food location
            ProduceRandom();
        } else {
            //Every refresh of the body
            for (int i = 0; i < body_length; i++) {
                g.fillRoundRect(body[i].x, body[i].y, 20, 20, 5, 5);
            }

            if (EatFood())//It was eaten to regenerate food
            {
                ProduceRandom();
            }
        }
        g.fillOval(RandomX, RandomY, 19, 19);
        first_launch = true;
        //wall
        g.setStroke(new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        g.setBackground(Color.WHITE);
        g.drawRect(2, 77, 491, 469);

        //Grid line
        for (int i = 1; i < 22; i++) {
            g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
            g.setColor(Color.WHITE);
            g.drawLine(5 + i * 22, 79, 5 + i * 22, 542);//The wall width is 4, and 1 pixel is reserved to avoid snake rubbing against the wall.
            if (i <= 20) {
                g.drawLine(4, 80 + i * 22, 491, 80 + i * 22);
            }
        }
    }

    public void ProduceRandom() {
        boolean flag = true;
        Random rand = new Random();
        RandomX = (rand.nextInt(21) + 1) * 22 + 7;
        RandomY = (rand.nextInt(20) + 1) * 22 + 82;
        while (flag) {
            for (int i = 0; i < body_length; i++) {
                if (body[i].x == RandomX && body[i].y == RandomY) {
                    RandomX = (rand.nextInt(21) + 1) * 22 + 7;
                    RandomY = (rand.nextInt(20) + 1) * 22 + 82;
                    flag = true;
                    break;
                } else {
                    if (i == body_length - 1) {
                        flag = false;
                    }
                }
            }
        }
    }

    public void HitWall() {//Judge whether to hit the wall
        if (Objects.equals(current_direction, "L")) {
            if (head.x < 7) {
                new Snake().start();
                isRun = false;
                int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "remind", JOptionPane.YES_NO_OPTION);
                if (result == JOptionPane.YES_NO_OPTION) {
                    direction = "R";//Default right
                    current_direction = "R";//Current direction
                    first_launch = false;
                    isRun = true;
                    body_length = 5;
                    head = new Grid(227, 170);
                    Score.setText("6");
                    hour = 0;
                    min = 0;
                    sec = 0;
                    for (int i = 0; i < MAX_SIZE; i++) {
                        body[i].x = 0;
                        body[i].y = 0;
                    }

                    System.out.println("Start again");
                }
            }
        }
        if (Objects.equals(current_direction, "R")) {
            if (head.x > 489) {
                new Snake().start();
                isRun = false;
                int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "remind", JOptionPane.YES_NO_OPTION);
                if (result == JOptionPane.YES_NO_OPTION) {
                    direction = "R";//Default right
                    current_direction = "R";//Current direction
                    first_launch = false;
                    isRun = true;
                    body_length = 5;
                    head = new Grid(227, 170);
                    Score.setText("0");
                    hour = 0;
                    min = 0;
                    sec = 0;
                    for (int i = 0; i < MAX_SIZE; i++) {
                        body[i].x = 0;
                        body[i].y = 0;
                    }


                    System.out.println("Start again");
                }
            }
        }
        if (Objects.equals(current_direction, "U")) {
            if (head.y < 94) {
                new Snake().start();
                isRun = false;
                int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "remind", JOptionPane.YES_NO_OPTION);
                if (result == JOptionPane.YES_NO_OPTION) {
                    direction = "R";//Default right
                    current_direction = "R";//Current direction
                    first_launch = false;
                    isRun = true;
                    body_length = 5;
                    head = new Grid(227, 100);
                    Score.setText("0");
                    hour = 0;
                    min = 0;
                    sec = 0;
                    for (int i = 0; i < MAX_SIZE; i++) {
                        body[i].x = 0;
                        body[i].y = 0;
                    }
                    System.out.println("Start again");
                }
            }
        }
        if (Objects.equals(current_direction, "D")) {
            if (head.y > 542) {
                new Snake().start();
                isRun = false;
                int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "remind", JOptionPane.YES_NO_OPTION);
                if (result == JOptionPane.YES_NO_OPTION) {
                    direction = "R";//Default right
                    current_direction = "R";//Current direction
                    first_launch = false;
                    isRun = true;
                    body_length = 5;
                    head = new Grid(227, 170);
                    Score.setText("0");
                    hour = 0;
                    min = 0;
                    sec = 0;
                    for (int i = 0; i < MAX_SIZE; i++) {
                        body[i].x = 0;
                        body[i].y = 0;
                    }
                    System.out.println("Start again");
                }
            }
        }
    }

    public void HitSelf() {//Judge whether you hit yourself
        for (int i = 0; i < body_length; i++) {
            if (body[i].x == head.x && body[i].y == head.y) {
                new Snake().start();
                isRun = false;
                int result = JOptionPane.showConfirmDialog(null, "Game over! Try again?", "remind", JOptionPane.YES_NO_OPTION);
                if (result == JOptionPane.YES_NO_OPTION) {
                    direction = "R";//Default right
                    current_direction = "R";//Current direction
                    first_launch = false;
                    isRun = true;
                    body_length = 5;
                    head = new Grid(227, 170);
                    Score.setText("0");
                    hour = 0;
                    min = 0;
                    sec = 0;
                    for (int j = 0; j < MAX_SIZE; j++) {
                        body[j].x = 0;
                        body[j].y = 0;
                    }
                    System.out.println("Start again");
                }
                break;
            }
        }
    }

    public boolean EatFood() {

        return head.x == RandomX && head.y == RandomY;
    }
public int s=0;
    public void Thread() {
        long millis = 300;//Refresh every 300 milliseconds
        run = new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                if (!pause) {
                    temp.x = head.x;
                    temp.y = head.y;
                    //Head movement
                    if (Objects.equals(direction, "L")) {
                        head.x -= 22;
                    }
                    if (Objects.equals(direction, "R")) {
                        head.x += 22;
                    }
                    if (Objects.equals(direction, "U")) {
                        head.y -= 22;
                    }
                    if (Objects.equals(direction, "D")) {
                        head.y += 22;
                    }
                    current_direction = direction;//Refresh current heading
                    //Body movement
                    for (int i = 0; i < body_length; i++) {
                        temp2.x = body[i].x;
                        temp2.y = body[i].y;
                        body[i].x = temp.x;
                        body[i].y = temp.y;
                        temp.x = temp2.x;
                        temp.y = temp2.y;
                    }

                    if (EatFood()) {
                        body_length++;
                        s++;
                        body[body_length - 1].x = temp2.x;
                        body[body_length - 1].y = temp2.y;
                        Score.setText("" + (s));
                        new Snake().start();
                    }

                    repaint();

                    HitWall();
                    HitSelf();
                }
            }
        });

        run.start();
    }

    //Timer Class 
    class Timer extends Thread {
        public Timer() {

            this.start();
        }

        @Override
        public void run() {
            while (true) {
                if (isRun) {
                    sec += 1;
                    if (sec >= 60) {
                        sec = 0;
                        min += 1;
                    }
                    if (min >= 60) {
                        min = 0;
                        hour += 1;
                    }
                    showTime();
                }

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }

        private void showTime() {
            String strTime;
            if (hour < 10)
                strTime = "0" + hour + ":";
            else
                strTime = "" + hour + ":";

            if (min < 10)
                strTime = strTime + "0" + min + ":";
            else
                strTime = strTime + "" + min + ":";

            if (sec < 10)
                strTime = strTime + "0" + sec;
            else
                strTime = strTime + "" + sec;

            //Set the display time on the form
            Time.setText(strTime);
        }
    }
    public static void main(String[] args) {
        Snakes t = new Snakes();
        t.Thread();
        JFrame game = new JFrame();
        game.setTitle("Greedy snake.GluttonousSnake");
        game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        game.setSize(510, 590);
        game.setResizable(false);
        game.setLocationRelativeTo(null);
        game.add(t);
        game.setVisible(true);
    }
}

class Snake extends Thread {

    public Snake() {
    }
}


 


 
4. Summary
4.1 difficulties and key points of the project
The display interface needs to be implemented by JFrame and Jpanel. Use a global variable to record the length of the current snake, which is convenient for drawing the correct snake. In collision detection, you only need to compare the coordinates of snake head node with the coordinates of snake body, food and wall. When the snake is moving, you need to assign each element of the array storing the snake to the next element, and finally calculate the first element. At this time, the value of the last element is discarded. If you eat food, you will continue to assign the last element backward, and set the length of the snake plus one.
4.2 project evaluation:
The main functions of greedy snake can be well realized. On the basis of it, interesting pictures are added to make the game more playable.
4.3 experience
Through this project, I practiced the usage of frame framework and GUI programming.
5. References
Using Java to develop Snake game @ a snow wolf

 

 

 

Keywords: Java

Added by nuying117 on Wed, 29 Dec 2021 21:32:05 +0200