绊夏微凉

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

贪吃蛇实现步骤

1.游戏窗口

package snake;

import javax.swing.*;

public class StartGame {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        // 设置窗口大小
        frame.setBounds(10, 10, 900, 700);
        // 设置窗口大小固定
        frame.setResizable(false);
        // 设置窗口可关闭
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        // 设置窗口可见
        frame.setVisible(true);
    }
}

注意:每个图片的大小为25,所以窗口大小的长和宽是25的倍数

2.获取图片

package snake;

import javax.swing.*;
import java.net.URL;

public class Data {

    // 获取头部图片
    public static URL headUrl = Data.class.getResource("statics/head.jpg");
    public static ImageIcon head = new ImageIcon(headUrl);

    // 获取向右的蛇头图片
    public static URL rightUrl = Data.class.getResource("statics/right.png");
    public static ImageIcon right = new ImageIcon(rightUrl);

    // 获取向左的蛇头图片
    public static URL leftUrl = Data.class.getResource("statics/left.png");
    public static ImageIcon left = new ImageIcon(leftUrl);

    // 获取向上的蛇头图片
    public static URL upUrl = Data.class.getResource("statics/up.png");
    public static ImageIcon up = new ImageIcon(upUrl);

    // 获取向下的蛇头图片
    public static URL downUrl = Data.class.getResource("statics/down.png");
    public static ImageIcon down = new ImageIcon(downUrl);

    // 获取身体图片
    public static URL bodyUrl = Data.class.getResource("statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyUrl);

    // 获取食物图片
    public static URL foodUrl = Data.class.getResource("statics/food.png");
    public static ImageIcon food = new ImageIcon(foodUrl);
}

3.设置游戏界面

package snake;

import javax.swing.*;
import java.awt.*;

public class GamePanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
    }
}

将游戏页面添加至游戏窗口

package snake;

import javax.swing.*;

public class StartGame {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        // 设置窗口大小
        frame.setBounds(10, 10, 900, 700);
        // 游戏面板放到游戏窗口
        frame.add(new GamePanel());
        // 设置窗口大小固定
        frame.setResizable(false);
        // 设置窗口可关闭
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        // 设置窗口可见
        frame.setVisible(true);
    }
}

4.设置蛇

4.1设置蛇头和蛇身

package snake;

import javax.swing.*;
import java.awt.*;

public class GamePanel extends JPanel {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);

        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 设置蛇头和蛇身
        Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
    }
}

4.2提取初始化

package snake;

import javax.swing.*;
import java.awt.*;

public class GamePanel extends JPanel {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];

    public GamePanel() {
        init();
    }
    
    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);

        // 设置蛇头和蛇身
        Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
    }
}

4.3根据方向设置蛇头

package snake;

import javax.swing.*;
import java.awt.*;

public class GamePanel extends JPanel {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;

    public GamePanel() {
        init();
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
    }
}

5.设置食物

package snake;

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

public class GamePanel extends JPanel {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;
    // 食物坐标
    private int foodX;
    private int fondY;
    private Random random = new Random();

    public GamePanel() {
        init();
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
        // 初始化食物坐标
        foodX = 25 + random.nextInt(34) * 25;
        fondY = 25 + random.nextInt(25) * 25;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 设置食物
        Data.food.paintIcon(this, g, foodX, fondY);
    }
}

注意:食物的坐标是随机的,所以用到随机函数,但是不超过总的坐标范围。

34 = 850 / 25

25 = 625 / 25

6.设置游戏状态

按下空格键游戏开始/暂停,游戏暂停显示文字“按下空格,开始游戏”。

监听空格键,按下空格键,游戏从暂停变成开始/开始变暂停。

package snake;

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

public class GamePanel extends JPanel implements KeyListener {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;
    // 食物坐标
    private int foodX;
    private int fondY;
    private Random random = new Random();
    // 游戏状态
    private boolean isStart = false;

    public GamePanel() {
        init();
        // 设置焦点
        this.setFocusable(true);
        // 添加键盘监听
        this.addKeyListener(this);
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
        // 初始化食物坐标
        foodX = 25 + random.nextInt(34) * 25;
        fondY = 25 + random.nextInt(25) * 25;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 设置食物
        Data.food.paintIcon(this, g, foodX, fondY);
        // 游戏暂停,显示按下空格,游戏开始
        if (!isStart) {
            // 设置字体颜色
            g.setColor(Color.white);
            // 设置字体
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            // 设置文字
            g.drawString("按下空格,游戏开始", 300, 300);
        }
    }


    @Override
    public void keyPressed(KeyEvent e) {
        // 获取按键编码
        int keyCode = e.getKeyCode();
        // 按下空格键
        if (keyCode == KeyEvent.VK_SPACE) {
            isStart = !isStart;
        }
        // 重画
        repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }
}

注意:

该游戏页面获取焦点以及添加键盘监听,如果不加无法键盘监听无效。

空格监听后得重画,不然也无法正常显示。

7.蛇移动

用定时器实现蛇的移动

package snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GamePanel extends JPanel implements KeyListener, ActionListener {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;
    // 食物坐标
    private int foodX;
    private int fondY;
    private Random random = new Random();
    // 游戏状态
    private boolean isStart = false;
    // 设置定时器
    private Timer timer = new Timer(100, this);

    public GamePanel() {
        init();
        // 设置焦点
        this.setFocusable(true);
        // 添加键盘监听
        this.addKeyListener(this);
        // 启动定时器
        timer.start();
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
        // 初始化食物坐标
        foodX = 25 + random.nextInt(34) * 25;
        fondY = 25 + random.nextInt(25) * 25;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 设置食物
        Data.food.paintIcon(this, g, foodX, fondY);
        // 游戏暂停,显示按下空格,游戏开始
        if (!isStart) {
            // 设置字体颜色
            g.setColor(Color.white);
            // 设置字体
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            // 设置文字
            g.drawString("按下空格,游戏开始", 300, 300);
        }
    }


    @Override
    public void keyPressed(KeyEvent e) {
        // 获取按键编码
        int keyCode = e.getKeyCode();
        // 按下空格键
        if (keyCode == KeyEvent.VK_SPACE) {
            isStart = !isStart;
        }
        // 重画
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart) {
            // 后一个坐标等于前面一个坐标
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            if (fx == "R") { // 向右头坐标横坐标+25
                snakeX[0] += 25;
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if (fx == "L") { // 向左头横坐标-25
                snakeX[0] -= 25;
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if (fx == "U") { // 向上头纵坐标-25
                snakeY[0] -= 25;
                if (snakeY[0] < 75) {
                    snakeY[0] = 625;
                }
            } else if (fx == "D") { // 向下头纵坐标+25
                snakeY[0] += 25;
                if (snakeY[0] > 625) {
                    snakeY[0] = 75;
                }
            }
            // 重画
            repaint();
            // 启动定时器
            timer.start();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }

}

8.通过方向键来控制蛇的移动

package snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GamePanel extends JPanel implements KeyListener, ActionListener {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;
    // 食物坐标
    private int foodX;
    private int fondY;
    private Random random = new Random();
    // 游戏状态
    private boolean isStart = false;
    // 设置定时器
    private Timer timer = new Timer(100, this);

    public GamePanel() {
        init();
        // 设置焦点
        this.setFocusable(true);
        // 添加键盘监听
        this.addKeyListener(this);
        // 启动定时器
        timer.start();
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
        // 初始化食物坐标
        foodX = 25 + random.nextInt(34) * 25;
        fondY = 25 + random.nextInt(25) * 25;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 设置食物
        Data.food.paintIcon(this, g, foodX, fondY);
        // 游戏暂停,显示按下空格,游戏开始
        if (!isStart) {
            // 设置字体颜色
            g.setColor(Color.white);
            // 设置字体
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            // 设置文字
            g.drawString("按下空格,游戏开始", 300, 300);
        }
    }


    @Override
    public void keyPressed(KeyEvent e) {
        // 获取按键编码
        int keyCode = e.getKeyCode();
        // 按下空格键
        if (keyCode == KeyEvent.VK_SPACE) {
            isStart = !isStart;
        }
        // 监听方向键
        if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        } else if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        }
        // 重画
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart) {
            // 后一个坐标等于前面一个坐标
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            if (fx == "R") { // 向右头坐标横坐标+25
                snakeX[0] += 25;
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if (fx == "L") { // 向左头横坐标-25
                snakeX[0] -= 25;
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if (fx == "U") { // 向上头纵坐标-25
                snakeY[0] -= 25;
                if (snakeY[0] < 75) {
                    snakeY[0] = 625;
                }
            } else if (fx == "D") { // 向下头纵坐标+25
                snakeY[0] += 25;
                if (snakeY[0] > 625) {
                    snakeY[0] = 75;
                }
            }
            // 重画
            repaint();
            // 启动定时器
            timer.start();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }

}

9.动态食物坐标和吃到食物长度+1

蛇头的坐标和食物的坐标重合为吃到食物。

package snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GamePanel extends JPanel implements KeyListener, ActionListener {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;
    // 食物坐标
    private int foodX;
    private int fondY;
    private Random random = new Random();
    // 游戏状态
    private boolean isStart = false;
    // 设置定时器
    private Timer timer = new Timer(100, this);

    public GamePanel() {
        init();
        // 设置焦点
        this.setFocusable(true);
        // 添加键盘监听
        this.addKeyListener(this);
        // 启动定时器
        timer.start();
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
        // 初始化食物坐标
        foodX = 25 + random.nextInt(34) * 25;
        fondY = 25 + random.nextInt(25) * 25;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 设置食物
        Data.food.paintIcon(this, g, foodX, fondY);
        // 游戏暂停,显示按下空格,游戏开始
        if (!isStart) {
            // 设置字体颜色
            g.setColor(Color.white);
            // 设置字体
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            // 设置文字
            g.drawString("按下空格,游戏开始", 300, 300);
        }
    }


    @Override
    public void keyPressed(KeyEvent e) {
        // 获取按键编码
        int keyCode = e.getKeyCode();
        // 按下空格键
        if (keyCode == KeyEvent.VK_SPACE) {
            isStart = !isStart;
        }
        // 监听方向键
        if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        } else if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        }
        // 重画
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart) {
            // 后一个坐标等于前面一个坐标
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            if (fx == "R") { // 向右头坐标横坐标+25
                snakeX[0] += 25;
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if (fx == "L") { // 向左头横坐标-25
                snakeX[0] -= 25;
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if (fx == "U") { // 向上头纵坐标-25
                snakeY[0] -= 25;
                if (snakeY[0] < 75) {
                    snakeY[0] = 625;
                }
            } else if (fx == "D") { // 向下头纵坐标+25
                snakeY[0] += 25;
                if (snakeY[0] > 625) {
                    snakeY[0] = 75;
                }
            }
            if (foodX == snakeX[0] && fondY == snakeY[0]) {
                // 重置食物坐标
                foodX = 25 + random.nextInt(34) * 25;
                fondY = 25 + random.nextInt(25) * 25;
                // 长度+1
                length++;
            }
            // 重画
            repaint();
            // 启动定时器
            timer.start();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }
}

10.游戏失败

头的坐标和身体坐标重合,游戏即为失败。

游戏正常开始条件为失败状态为false以及游戏状态为开始。

空格监听,得先判断是否失败,否则在判断游戏是否开始

package snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GamePanel extends JPanel implements KeyListener, ActionListener {

    // 蛇长度
    private int length;
    // 蛇头和身体的左边
    private int[] snakeX = new int[34];
    private int[] snakeY = new int[25];
    // 蛇头方向
    private String fx;
    // 食物坐标
    private int foodX;
    private int fondY;
    private Random random = new Random();
    // 游戏状态
    private boolean isStart = false;
    // 设置定时器
    private Timer timer = new Timer(100, this);
    // 失败状态
    private boolean isFalse = false;

    public GamePanel() {
        init();
        // 设置焦点
        this.setFocusable(true);
        // 添加键盘监听
        this.addKeyListener(this);
        // 启动定时器
        timer.start();
    }

    // 初始化
    private void init() {
        // 初始化蛇
        // 初始化蛇的长度为3
        length = 3;
        // 初始化蛇的头和身体坐标
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化蛇头方向
        fx = "R";
        // 初始化食物坐标
        foodX = 25 + random.nextInt(34) * 25;
        fondY = 25 + random.nextInt(25) * 25;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 清屏
        super.paintComponent(g);
        // 设置背景色
        this.setBackground(Color.white);
        // 设置头部位置
        Data.head.paintIcon(this, g, 25, 25);
        // 设置游戏界面位置及大小
        g.fillRect(25, 75, 850, 625);
        // 设置蛇头
        if (fx == "R") {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "L") {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "U") {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx == "D") {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 设置蛇身
        for(int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 设置食物
        Data.food.paintIcon(this, g, foodX, fondY);
        // 游戏暂停,显示按下空格,游戏开始
        if (isFalse) {
            // 设置字体颜色
            g.setColor(Color.white);
            // 设置字体
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            // 设置文字
            g.drawString("游戏失败,按下空格,游戏开始", 300, 300);
        } else {
            if (!isStart) {
                // 设置字体颜色
                g.setColor(Color.white);
                // 设置字体
                g.setFont(new Font("微软雅黑", Font.BOLD, 40));
                // 设置文字
                g.drawString("按下空格,游戏开始", 300, 300);
            }
        }

    }


    @Override
    public void keyPressed(KeyEvent e) {
        // 获取按键编码
        int keyCode = e.getKeyCode();
        // 按下空格键
        if (keyCode == KeyEvent.VK_SPACE) {
            if (isFalse) {
                isFalse = false;
            } else {
                isStart = !isStart;
            }
        }
        // 监听方向键
        if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        } else if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        }
        // 重画
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart && !isFalse) {
            for (int i = 1; i < length; i++) {
                // 判断身体是否与蛇头重合
                if (snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0]) {
                    // 设为失败
                    isFalse = true;
                    // 重置游戏页面
                    init();
                    // 重画
                    repaint();
                    return;
                }
            }
            // 后一个坐标等于前面一个坐标
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            if (fx == "R") { // 向右头坐标横坐标+25
                snakeX[0] += 25;
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if (fx == "L") { // 向左头横坐标-25
                snakeX[0] -= 25;
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if (fx == "U") { // 向上头纵坐标-25
                snakeY[0] -= 25;
                if (snakeY[0] < 75) {
                    snakeY[0] = 625;
                }
            } else if (fx == "D") { // 向下头纵坐标+25
                snakeY[0] += 25;
                if (snakeY[0] > 625) {
                    snakeY[0] = 75;
                }
            }
            if (foodX == snakeX[0] && fondY == snakeY[0]) {
                // 重置食物坐标
                foodX = 25 + random.nextInt(34) * 25;
                fondY = 25 + random.nextInt(25) * 25;
                // 长度+1
                length++;
            }
            // 重画
            repaint();
            // 启动定时器
            timer.start();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }

}

posted on 2021-06-07 17:20  绊夏微凉  阅读(106)  评论(0)    收藏  举报