java写贪吃蛇

村边大麦地 / 2023-08-22 / 原文

两个包:GamePanel和Snake

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GamePanel extends JPanel {

        private static final long serialVersionUID = 1L;

        Snake snakehead = null;// 蛇头

        Snake snakebody = null;// 蛇身

        Snake food = null;// 食物

        static JFrame mf = null;// 主窗体

        GameThread gt = new GameThread();// 主线程

        ArrayList<Point> snakeroad = new ArrayList<>();// 蛇走过的路径数组

        ArrayList<Snake> snakes = new ArrayList<>();// 蛇头及蛇身的数组

        static int width = 600;// 窗体大小

        int row = width / 20;// 按窗体大小及蛇的大小分成上下左右各30格

        int col = row;

        int step = 1;// 蛇每次移动间隔

        int threadspeed = 150;// 主线程sleep间隔

        int score = 0; // 分数

        boolean dir = false;// 蛇移动方向

        boolean gameflag = false;// 游戏暂停或开始判断

        boolean dead = false;// 游戏失败判断

// 构造函数

        public GamePanel() {

            setBounds(0, 0, width, width);// 窗体大小

            setOpaque(false);// 窗体透明

            createKeyListener();// 监听键盘

            gt.start();// 线程开始

            init();// 初始化

        }

// 入口

        public static void main(String[] args) {

            mf = new JFrame();// frame实例化

            mf.setSize(width + 18, width + 15 + 30);// frame大小

            mf.setLocationRelativeTo(null);// 屏幕居中显示

            mf.setLayout(null);// 布局无

            mf.setTitle("Sanke");// 标题

            mf.setResizable(false);// 不可放大

            mf.getContentPane().setBackground(new Color(0, 139, 0));// 设置背景色

            GamePanel gp = new GamePanel();// panel实例化

            mf.add(gp);// panel加入frame

            mf.setVisible(true);// 显示frame

        }

// 初始化

        void init() {

// 蛇头存在就产生身体

            if (snakes.size() > 0) {

                snakebody = new Snake(snakes.get(snakes.size() - 1).x, snakes.get(snakes.size() - 1).y, this);

                snakes.add(snakebody);

            } else {

                snakehead = new Snake(1, 1, this);// 蛇头实例化

                snakes.add(snakehead);

            }

// food随机产生

            food = new Snake((int) (Math.random() * row), (int) (Math.random() * row), this);

        }

// 画蛇,食物,提示

        @Override

        public void paint(Graphics g) {

            super.paint(g);

// 蛇头

            if (snakes != null) {

                snakes.get(0).drawhead(g);

            }

// 蛇身体

            if (snakes != null) {

                for (int i = 1; i < snakes.size(); i++) {

                    snakes.get(i).draw(g);

                }

            }

// food

            if (food != null) {

                food.drawfood(g);

            }

// 游戏失败提示

            if (dead) {

                g.setColor(new Color(255, 255, 255, 255));

                g.setFont(new Font("仿宋", Font.BOLD, 30));

                g.drawString("游戏失败!按“空格键”继续", width / 2 - 180, width / 2);

            }

// 游戏暂停提示

            if (!gameflag) {

                g.setColor(new Color(255, 255, 255, 255));

                g.setFont(new Font("仿宋", Font.BOLD, 30));

                g.drawString("游戏暂停!按“P”键开始", width / 2 - 170, width / 2);

            }

// 分数和速度显示

            g.setFont(new Font("Arial", Font.BOLD, 14));

            g.setColor(new Color(255, 255, 255, 255));

            g.drawString("SCORE", 3, width - 5);

            g.drawString(String.valueOf(score), 60, width - 5);// 显示分数

            g.drawString("SPEED", 100, width - 5);

            g.drawString(String.valueOf(threadspeed), 155, width - 5);// 显示速度

            g.setFont(new Font("仿宋", Font.BOLD, 14));

            g.drawString("按“R”重新开始游戏", width - 150, width - 5);// 重新开始游戏

//画格子

            for(int i=0;i<row;i++) {

                for(int j=0;j<col;j++) {

                    g.setColor(new Color(173,216,230,25));

                    g.drawRect(j*20, i*20, 20, 20);

                }

            }

            repaint();

        }

// 主线程

        class GameThread extends Thread {

            @Override

            public void run() {

                while (true) {

                    try {

                        Thread.sleep(threadspeed);// 间隔150毫秒

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    if (snakehead != null & !dead & gameflag) {

// 蛇头移动坐标录入snakeroad数组

                        snakeroad.add(new Point(snakehead.x, snakehead.y));

                        if (snakeroad.size() == snakes.size()) {

                            snakeroad.remove(0);// 控制snakeroad数组长度

                        }

// 蛇移动

                        snakehead.movebody(dir, step);

                        outofBoard();// 边界穿透

                        dead();// 游戏失败判断

                        hit();// 吃food判断

                    }

                }

            }

        }

// 边界穿透

        void outofBoard() {

            Snake snake = null;

// 四边界限

            for (int i = 0; i < snakes.size(); i++) {

                snake = snakes.get(i);

                if (snake.getY() < 0) {

                    snake.setY(row - 1);

                } else if (snake.getY() > row - 1) {

                    snake.setY(0);

                } else if (snake.getX() < 0) {

                    snake.setX(row - 1);

                } else if (snake.getX() > row - 1) {

                    snake.setX(0);

                }

            }

        }

// 吃food

        void hit() {

            if (food.getX() == snakehead.x & food.getY() == snakehead.y) {

                init();// 新增food和蛇加长

                score++;// 分数增加

            }

        }

// 蛇头碰到蛇身体则失败

        void dead() {

            for (int i = 0; i < snakes.size(); i++) {

                for (int j = 0; j < snakes.size(); j++) {

                    if (i != j) {

                        if (snakes.get(j).getX() == snakes.get(i).getX() && snakes.get(j).getY() == snakes.get(i).getY()) {

                            dead = true;

                        }

                    }

                }

            }

        }

// 重新开始游戏

        void restart() {

            snakehead = null;

            food = null;

            snakes.clear();

            snakeroad.clear();

            threadspeed = 150;

            score = 0;

            dir = false;

            gameflag = false;

            dead = false;

            init();

        }

// 键盘监听

        private void createKeyListener() {

            KeyAdapter l = new KeyAdapter() {

                @Override

                public void keyPressed(KeyEvent e) {

                    int key = e.getKeyCode();

                    switch (key) {

                        case KeyEvent.VK_P:// 按p键控制游戏暂停或开始

                            if (!gameflag) {

                                gameflag = true;

                            } else {

                                gameflag = false;

                            }

                            break;

// 空格

                        case KeyEvent.VK_SPACE:

                            dead = false;

                            break;

// 向上

                        case KeyEvent.VK_UP:

                        case KeyEvent.VK_W:

                            dir = false;

                            step=-1;

                            break;

// 向右

                        case KeyEvent.VK_D:

                        case KeyEvent.VK_RIGHT:

                            dir = true;

                            step=1;

                            break;

// 向下

                        case KeyEvent.VK_S:

                        case KeyEvent.VK_DOWN:

                            dir = false;

                            step=1;

                            break;

// 向左

                        case KeyEvent.VK_A:

                        case KeyEvent.VK_LEFT:

                            dir = true;

                            step=-1;

                            break;

                        case KeyEvent.VK_1:

                            threadspeed += 5;// 按1速度减慢5

                            break;

                        case KeyEvent.VK_2:

                            if (threadspeed > 0) {

                                threadspeed -= 5;// 按2速度加快5

                            }

                            break;

                        case KeyEvent.VK_R:

                            restart();

                            break;

                    }

                }

            };

            mf.addKeyListener(l);// 主窗体增加键盘监听

        }
    }

  

import java.awt.Color;
import java.awt.Graphics;

public class Snake {

        private GamePanel panel = null;

        int x = 0;

        int y = 0;

        public Snake(int x, int y, GamePanel panel) {

            this.x = x;

            this.y = y;

            this.panel = panel;

        }

// 画蛇身

        void draw(Graphics g) {

            g.setColor(new Color(255, 255, 255));

            g.fillRect(x * 20, y * 20, 19, 19);

        }

// 画食物

        void drawfood(Graphics g) {

            g.setColor(new Color(255, 255, 255,255));

            g.fillOval(x * 20+5, y * 20+5, 10, 10);

        }

// 画蛇头

        void drawhead(Graphics g) {

            g.setColor(new Color(255, 0, 0));

            g.fillRect(x * 20, y * 20, 19, 19);

        }

// 蛇头移动

        void move(boolean dir, int step) {

            if (dir) {

                x+=step;

            }else {

                y+=step;

            }

            panel.repaint();

        }

//蛇移动

        public void movebody(Boolean dir, int step) {

// 蛇头移动

            panel.snakehead.move(dir, step);

// 蛇身移动

            for (int i = 1; i < panel.snakes.size(); i++) {

                panel.snakes.get(i).x = panel.snakeroad.get(panel.snakeroad.size()-i).x;

                panel.snakes.get(i).y = panel.snakeroad.get(panel.snakeroad.size()-i).y;

            }

            panel.repaint();

        }

        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;

        }

}