Practical development of Java games -- greedy Snake games

Practical development of Java games -- greedy Snake games

1. Direction class

Direction: used to store up, down, left and right keys.

package com.games;

/*
 *Enumeration: just a few fixed constants
 */
public enum  Direction{
    UP,DOWN,LEFT,RIGHT
 }

2. Snake class

Snake, Snake: a snake has multiple nodes. Use LinkedList to collect storage nodes
Initialize the snake body. The snake birthplace has 6 nodes

package com.games;

import java.util.LinkedList;

/**
 *Snake Class represents snake
 * A snake has multiple nodes. Use the LinkedList set to store Node nodes
 * The place where the snake was born has six nodes
 */
public class Snake {
    //Snake body
    private LinkedList<Node> body;
    //The direction of motion of the snake
    private Direction direction = Direction.LEFT;
    //Is the snake alive
    private boolean isLiving = true;

    //Construction method, which is executed when creating Snake object
    public Snake(){
        //Initialize snake body
        initSnake();
    }

    //Initialize snake body
    private void initSnake(){
        //Create collection
        body= new LinkedList<>();
        //Create 6 nodes and put them in the collection
        body.add(new Node(16,20));
        body.add(new Node(17,20));
        body.add(new Node(18,20));
        body.add(new Node(19,20));
        body.add(new Node(20,20));
        body.add(new Node(21,20));
    }

    //The snake moves in the direction of its head
    //Control Snake Movement: add a node in the movement direction of snake head, and then delete the last node of snake tail
    public void move(){
        if(isLiving) {

            //Get snake head
            Node head = body.getFirst();
            switch (direction) {
                case UP:
                    //Add node on snakehead
                    body.addFirst(new Node(head.getX(), head.getY() - 1));
                    break;
                case DOWN:
                    body.addFirst(new Node(head.getX(), head.getY() + 1));
                    break;
                case LEFT:
                    body.addFirst(new Node(head.getX() - 1, head.getY()));
                    break;
                case RIGHT:
                    body.addFirst(new Node(head.getX() + 1, head.getY()));
                    break;
            }

            //Delete the last node of snaketail
            body.removeLast();

            //Judge whether the snake hit the wall
            head = body.getFirst();
            if(head.getX() < 0 || head.getY() < 0 || head.getX() >= 40 || head.getY() >= 40){
                isLiving = false;
            }

            //Judge whether the snake touches its body
            for(int i = 1; i < body.size(); i++){
                Node node = body.get(i);
                if(head.getX() == node.getX() && head.getY() == node.getY()){
                    isLiving = false;
                }
            }


        }
    }



    public LinkedList<Node> getBody() {
        return body;
    }

    public void setBody(LinkedList<Node> body) {
        this.body = body;
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    //Eat food; Add a node along the moving direction of the snake head
    public void eat(Node food){
        //Get snake head
        Node head = body.getFirst();
        switch (direction) {
            case UP:
                //Add node on snakehead
                body.addFirst(new Node(head.getX(), head.getY() - 1));
                break;
            case DOWN:
                body.addFirst(new Node(head.getX(), head.getY() + 1));
                break;
            case LEFT:
                body.addFirst(new Node(head.getX() - 1, head.getY()));
                break;
            case RIGHT:
                body.addFirst(new Node(head.getX() + 1, head.getY()));
                break;
        }
    }
}

3. Node class

Node class: each snake is composed of several nodes, and each node has abscissa and ordinate to determine its position

package com.games;

import java.util.Random;

/**
 *Node class: each snake is composed of several nodes, and each node has abscissa and ordinate to determine its position
 */
public class Node {
    private int x;
    private int y;

    public Node(){

    }

    public Node(int x,int y){
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    //Randomly generated location
    public void random(){
        //Create Random object
        Random r = new Random();
        //Randomly generated abscissa
        this.x = r.nextInt(40);
        //Randomly generated ordinates
        this.y = r.nextInt(40);
    }
}

4. MainFrame class

  • realization:
  • (1) initFrame() method: initialize form parameters; Set the width and height of the form, the default position of the form, the function of the close button and the immutable size of the form.
  • (2) initGamePanel() method: inherit the JPanel() class, rewrite the paint() method, initialize the game board, draw the contents of the board in the paint() method, that is, empty the board, draw horizontal and vertical lines, draw snakes and food, and finally add the board to the form.
  • (3) initSnake() method: initialize Snake; Create a Snake class, initialize the initial position of the Snake in the Snake class, and construct the move() method and eat() method. The move() method realizes the functions of the Snake moving along the direction of the Snake's head, judging whether the Snake hits the wall and touches its own body; The eat() method realizes that when the food coincides with the Snake head, a node will be added along the moving direction of the Snake head..
  • (4) initFood() method: initialize food; Create a Node class, in which the random number is used to realize the random generation of food location.
  • (5) initTimer() method: initialize the timer; Set the timing task, set the snake movement operation according to the game state and direction variable, determine the food, and judge whether the food coincides with the snake head. If so, call the eat() method and randomly generate the food again. Using the timer, call the repaint() method to update the interface in real time.
  • (6) setKeyListener() method: set keyboard listening. When the keyboard is pressed, call the keyPressed(KeyEvent e) method to obtain the keyboard input, and make the snake move in the Direction according to the keyboard input.
    The code is as follows:
package com.games;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.LinkedList;
import java.util.TimerTask;

public class MainFrame extends JFrame {
    //snake
    private Snake snake;
    //game board 
    private JPanel jPanel;
    //Timer, which calls the method of snake movement within the specified time
    private Timer timer;
    //food
    private Node food;

    public MainFrame() throws HeadlessException {
        //Initialize form parameters
        initFrame();
        //Initialize game board
        initGamePanel();
        //Initialize snake
        initSnake();
        //Initialize food
        initFood();
        //Initialization timer
        initTimer();
        //Set keyboard monitoring to make the snake move up, down, left and right
        setKeyListener();
    }

    private void initFood(){
        food = new Node();
        food.random();
    }

    private void setKeyListener(){
        addKeyListener(new KeyAdapter() {
            //This method is called automatically when the keyboard is pressed
            @Override
            public void keyPressed(KeyEvent e) {
                //Each key in the keyboard has its own number
                switch (e.getKeyCode()){
                    case KeyEvent.VK_UP://Up key
                        if(snake.getDirection() != Direction.DOWN){
                            //Modify the direction of motion of the snake
                            snake.setDirection(Direction.UP);
                        }
                        break;
                    case KeyEvent.VK_DOWN://Down key
                        if(snake.getDirection() != Direction.UP){
                            snake.setDirection(Direction.DOWN);
                        }
                        break;
                    case KeyEvent.VK_LEFT://Left key
                        if(snake.getDirection() != Direction.RIGHT){
                            snake.setDirection(Direction.LEFT);
                        }
                        break;
                    case KeyEvent.VK_RIGHT://Right click
                        if(snake.getDirection() != Direction.LEFT){
                            snake.setDirection(Direction.RIGHT);
                        }
                        break;
                }
            }
        });
    }

    private void initTimer(){
        timer = new Timer();

        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                snake.move();
                //Judge whether the food coincides with the snake head
                Node head = snake.getBody().getFirst();
                if(head.getX() == food.getX() && head.getY() == food.getY()){
                    snake.eat(food);
                    food.random();
                }
                //Redraw game board
                jPanel.repaint();
            }
        };

        //Perform a scheduled task every 100 milliseconds
        //The moving speed of the snake. If you want to change the moving speed, you can change the last parameter
        timer.scheduleAtFixedRate(timerTask,0,200);
    }

    private void initSnake(){
        snake = new Snake();
    }

    public void initGamePanel(){
         jPanel = new JPanel(){

            //Draw the contents of the chessboard
            public void paint(Graphics g){
                //Empty chessboard
                g.clearRect(0,0,600,600);

                //Graphics g can be regarded as a brush, which provides many methods to draw some basic graphics (lines, rectangles)
                //Draw 40 horizontal lines
                for(int i = 0;i <= 40; i++){
                    g.drawLine(0,i*15,600,i*15);
                }

                //Draw 40 vertical lines
                for(int i = 0; i <= 40; i++){
                    g.drawLine(i*15,0,i*15,600);
                }

                //Draw snake
                LinkedList<Node> body = snake.getBody();
                for(Node node : body){
                    g.fillRect(node.getX()*15,node.getY()*15,15,15);
                }

                //Draw food
                g.fillRect(food.getX()*15,food.getY()*15,15,15);

            }

        };

        //Add checkerboard to form
        add(jPanel);

    }

    //Initialize form parameters
    public void initFrame(){
        //Set the width and height of the form
        setSize(610,640);
        //Set the default location of the form
        setLocation(408,408);
        //Set the function of the close button
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Set form size immutable
        setResizable(false);
    }

    public static void main(String[] args) {
        //Create a form object and display it
        new MainFrame().setVisible(true);
    }
}

Keywords: Java

Added by cheatboy00 on Sun, 30 Jan 2022 17:12:17 +0200