贪吃蛇-JavaGUI实现

开发的大体思路
1.定义数据
2.画上面板(将数据进行初始化赋值)
3.监听事件
   键盘监听
   事件监听

游戏主界面代码

<details>
<summary>点击查看代码</summary>

```
package com.Tang.gui.snake;

import javax.swing.*;

//游戏主界面
public class StartGame {
    public static void main(String[] args) {
        JFrame frame = new JFrame();

        //正常的游戏界面都在面板上
        frame.add(new GamePanel());


        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setBounds(10,10,900,720);
        frame.setResizable(false);//窗口大小不可变
        frame.setVisible(true);
    }
}

蛇头蛇身图片数据代码

package com.Tang.gui.snake;

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

public class Data {
    //相对路径 tx.jpj
    //绝对路径 / 相对于当前项目
    //广告栏
    public static URL headerURL = Data.class.getResource("statics/header.png");
    public static ImageIcon header = new ImageIcon(headerURL);

    //身体
    public static URL bodyURL = Data.class.getResource("statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);
    //蛇头
    public static URL upURL = Data.class.getResource("statics/up.png");
    public static URL downURL = Data.class.getResource("statics/down.png");
    public static URL leftURL = Data.class.getResource("statics/left.png");
    public static URL rightURL = Data.class.getResource("statics/right.png");
    public static ImageIcon up = new ImageIcon(upURL);
    public static ImageIcon down = new ImageIcon(downURL);
    public static ImageIcon left = new ImageIcon(leftURL);
    public static ImageIcon right = new ImageIcon(rightURL);
    //食物
    public static URL foodURL = Data.class.getResource("statics/food.png");
    public static ImageIcon food = new ImageIcon(foodURL);

}

游戏面板代码

package com.Tang.gui.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;

//游戏的面板
//ActionListener接口主要用于计时器的监听
public class GamePanel extends JPanel implements KeyListener, ActionListener {
    //绘制面板,游戏中的所有东西都是用画笔来画
    //定义蛇的数据结构
    int length;
    int[] snakeX = new int[600];
    int[] snakeY = new int[500];
    String fx;//蛇头的方向
    //定义积分
    int score;
    //定义食物的坐标
    int foodx;
    int foody;
    Random random = new Random();
    //定时器以毫秒为单位1s = 1000ms
    Timer timer = new Timer(100,this);//100毫秒执行一次,为小蛇移动的速度
    //初始游戏状态
    boolean isStart = false;//游戏初始默认为停止
    //失败状态
    boolean isFail = false;//初始默认不是失败的
    public GamePanel() {
        init();
        //获取焦点和键盘监听事件
        this.setFocusable(true);//获得焦点事件,就是当前运行进程为游戏窗口
        foodx = 25 + 25*random.nextInt(34);//游戏界面宽度为850,蛇一节身体宽度为25(左边界的起始位置也为25),所以在横向上可以有850/25=34个位置可以产生食物
        foody = 75 + 25*random.nextInt(24);//75为上边界的起始位置,游戏界面高度为600,蛇一节身体宽度为25,所以在纵向上可以有600/25=24个位置可以产生食物

        this.addKeyListener(this);//获得键盘监听事件
        timer.start();//游戏一开始定时器就启动

    }

    //初始化方法
    public void init(){
        length = 3;//初始化蛇长(加上蛇头)一共三节
        snakeX[0] = 100; snakeY[0] = 100;//初始蛇脑袋的位置
        snakeX[1] = 75; snakeY[1] = 100;//初始蛇第一节身体的位置
        snakeX[2] = 50; snakeY[2] = 100;//初始蛇第二节身体的位置
        fx = "R";//初始方法向右
        score = 0;//初始成绩为零
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);//清屏
        //绘制静态面板
        //面板背景颜色为白色
        this.setBackground(Color.white);
        //将游戏头部广告栏画上去
        Data.header.paintIcon(this,g,25,11);
        //默认的游戏界面
        g.fillRect(25,75,850,600);
        //将成绩给画上去
        g.setColor(Color.white);//画笔颜色
        g.setFont(new Font("微软雅黑",Font.BOLD,18));//设置字体
        g.drawString("长度:"+ length ,750,35);
        g.drawString("分数:"+ score ,750,60);
        //将食物画入游戏界面中
        Data.food.paintIcon(this,g,foodx,foody);

        //将小蛇的初始状态放入游戏界面中
        if(fx.equals("R")){
            Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//需要通过方向指定蛇头的方向
        }else if(fx.equals("L")){
            Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);//将蛇头画入游戏界面指定位置
        }else if(fx.equals("U")){
            Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);//将蛇头画入游戏界面指定位置
        }else if(fx.equals("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]);
        }
        //若果游戏没有开始这显示按下空格开始游戏字体
        if(isStart == false){
            g.setColor(Color.white);//设置画笔颜色
            g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体
            g.drawString("按下空格键开始游戏",300,400);//设置画笔画下的文字,以及文字画入游戏界面的位置
        }
        //如果游戏失败则显示游戏结束,按下空格重新开始游戏字体
        if(isFail){
            g.setColor(Color.RED);//设置画笔颜色
            g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体
            g.drawString("游戏结束,按下空格重新开始",300,400);//设置画笔画下的文字,以及文字画入游戏界面的位置
        }
    }

    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();//获得键盘按下的是哪一个键
        if(keyCode == KeyEvent.VK_SPACE){//如果按下的是空格键
            if(isFail){//如果游戏失败
                //重新开始
                isFail = false;
                init();
            }else {
                isStart = !isStart;//取反,通过修改此值让画笔决定画与不画
            }
            repaint();//刷新,画笔重画
        }
        //小蛇移动
        if(keyCode == KeyEvent.VK_UP){//当按下上键小蛇的头转向上
            fx = "U";
        }else if(keyCode == KeyEvent.VK_DOWN){//当按下下键小蛇的头转向下
            fx = "D";
        }else if(keyCode == KeyEvent.VK_LEFT){//当按下左键小蛇的头转向左
            fx = "L";
        }else if(keyCode == KeyEvent.VK_RIGHT){//当按下右键小蛇的头转向右
            fx = "R";
        }
    }
    //事件的监听,需要通过固定事件来刷新,1s=10次
    @Override
    public void actionPerformed(ActionEvent e) {
        if(isStart && isFail == false){//如果游戏是开始状态并且没有失败,就让小蛇动起来
            if(snakeX[0] == foodx && snakeY[0] == foody){//蛇头碰到食物后
                length ++;//蛇身长度加一
                //没吃到一个食物分数加一
                score ++;
                //再次随机生成食物
                foodx = 25 + 25*random.nextInt(34);//游戏界面宽度为850,蛇一节身体宽度为25(左边界的起始位置也为25),所以在横向上可以有850/25=34个位置可以产生食物
                foody = 75 + 25*random.nextInt(24);//75为上边界的起始位置,游戏界面高度为600,蛇一节身体宽度为25,所以在纵向上可以有600/25=24个位置可以产生食物
            }
            for (int i = length-1; i >0 ; i--) {//让蛇的后一节移动到前一节位置
                snakeX[i] = snakeX[i-1];
                snakeY[i] = snakeY[i-1];
            }
            if(fx.equals("R")){//如果此时蛇头向右
                snakeX[0] += 25;//蛇头向右引领方向,蛇身大小为25
                //边界判断
                if(snakeX[0] > 850){//碰到游戏界面的右边界时
                    snakeX[0] = 25;//回到最左侧边界
                }
            }else if(fx.equals("L")){//如果此时蛇头向左
                snakeX[0] -= 25;
                //边界判断
                if(snakeX[0] < 25){//碰到游戏界面的左边界时
                    snakeX[0] = 850;//回到最右侧边界
                }
            }else if(fx.equals("U")){//如果此时蛇头向上
                snakeY[0] -= 25;
                //边界判断
                if(snakeY[0] < 75){//碰到游戏界面的上边界时
                    snakeY[0] = 650;//回到最下侧边界
                }
            }else if(fx.equals("D")){//如果此时蛇头向下
                snakeY[0] += 25;
                //边界判断
                if(snakeY[0] > 650){//碰到游戏界面的下边界时
                    snakeY[0] = 75;//回到最上侧边界
                }
            }
            //蛇头撞到自己则游戏失败
            for (int i = 1; i < length; i++) {
                if(snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]){//如果蛇身与蛇头相遇则游戏失败
                    isFail = true;//游戏失败
                }
            }

            repaint();//重画页面
        }
        timer.start();
    }




    @Override
    public void keyReleased(KeyEvent e) {

    }
    @Override
    public void keyTyped(KeyEvent e) {

    }

}

运行结果图
起初界面

运行中界面


失败界面

posted @ 2022-07-12 19:55  剑断青丝ii  阅读(70)  评论(0编辑  收藏  举报