javaSE||贪吃蛇

目录

一:贪吃蛇游戏的实现步骤

1. 画出窗口

2. 在窗口上添加画布

3. 在画布上添加一个黑色游戏区

4. 放静态蛇、

5. 定义蛇的数据结构

6. 控制蛇头方向

7. 放上开始提示信息

8. 按空格键开始游戏

9. 让蛇动起来

10. 实现暂停

11. 实现转向功能

12. 添加食物

13. 吃掉食物

二:核心源码

1.  MySnake类

2. MyPanel类

3. Direction类


本文用于自己参考,不参与商业用途,学习于来自动力节点课程,如有侵权联系删除。

成品

一:贪吃蛇游戏的实现步骤

1. 画出窗口

窗口大小

实现700*900

①宽度值为700像素,每个格子为25像素,共计有28个格子。

②高度值为800像素,每个格子为25像素,共计有36 个格子。

package demo;
 
import javax.swing.*;
 
 
public class MySnake {
    public static void main(String[] args) {
        // 创建一个窗口
        JFrame frame = new JFrame();
        // 指定窗口x和y的相对位置及窗口的宽度和高度值
        frame.setBounds(500,25,700,800);
        // 不允许拖拽改变大小
        frame.setResizable(false);
        // 当点击窗口关闭按钮,执行操作是退出
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        // 当前窗口显示出来
        frame.setVisible(true);
 
    }
}
2. 在窗口上添加画布
package demo;
 
import javax.swing.*;
import java.awt.*;
 
public class MyPanel extends JPanel {
    public MyPanel() {
    }
    // 重写画组件的方法
    @Override
    protected void paintComponent(Graphics g) {
        // 调用父类值的方法做一些基本工作
        super.paintComponent(g);
        // 设置背景颜色
        this.setBackground(Color.red);
    }
}
3. 在画布上添加一个黑色游戏区
package demo;
 
import javax.swing.*;
import java.awt.*;
 
public class MyPanel extends JPanel {
    public MyPanel() {
    }
    // 重写画组件的方法
    @Override
    protected void paintComponent(Graphics g) {
        // 调用父类值的方法做一些基本工作
        super.paintComponent(g);
        // 设置背景颜色
        this.setBackground(Color.red);
        // 在画布中添加游戏区域(这里就和框一样大小)
        g.fillRect(0,0,700,900);
    }
}
4. 放静态蛇、
package demo;
 
import javax.swing.*;
import java.awt.*;
import java.lang.invoke.VarHandle;
 
public class MyPanel extends JPanel {
    // 声明右侧蛇头和身体
    ImageIcon right = new ImageIcon("images/right.png");
    ImageIcon body = new ImageIcon("images/body.png");
 
    public MyPanel() {
    }
 
    // 重写画组件的方法
    @Override
    protected void paintComponent(Graphics g) {
        // 调用父类值的方法做一些基本工作
        super.paintComponent(g);
        // 设置背景颜色
        this.setBackground(Color.red);
        // 在画布中添加游戏区域
        g.fillRect(0,0,700,800);
 
        // 在画布中添加右侧蛇头和身体
        right.paintIcon(this,g,100,100);
        body.paintIcon(this,g,75,100);
        body.paintIcon(this,g,50,100);
    }
}
5. 定义蛇的数据结构
  //声明右侧蛇头和身体
    ImageIcon right = new ImageIcon("D:\\破解工具\\images\\right.png");
    ImageIcon body =new ImageIcon("D:\\破解工具\\images\\body.png");
 //设定蛇头和身体的初始位置
        snakeX[0]=100;
        snakeY[0]=100;
        snakeX[1]=75;
        snakeY[1]=100;
        snakeX[2]=50;
        snakeY[2]=100;
//添加的身体
        body.paintIcon(this,g,75,100);
        body.paintIcon(this,g,50,100)
//两个数组分别存放X和Y坐标
    int[] snakeX = new int[1008];//数组最大值是宽乘高
    int[] snakeY = new int[1008];//数组最大值是宽乘高
6. 控制蛇头方向

//定义枚举来实现,创建枚举类Direction

package Demo;

public enum Direction {//定义枚举方向,四个取值,向上,向下,向左,向右
    top,bottom,Left,right;
}
7. 放上开始提示信息

使用提供的画笔g

g.setColor(Color.white);
                g.setFont(new Font("宋体",Font.BOLD,50));
                g.drawString("请按空格键表示游戏开始!",50,500);
8. 按空格键开始游戏

创建Boolean类isStart判断是否开始游戏,isStart若是为false显示开始文字,然后再构造方法中,设置焦点,通过获得键盘事件来控制,重写keyTyped()、keyPressed()、keyReleased(),在keyPressed()方法中判断是否为空格所对应的ASCII码

 

//Boolean的标记   
 boolean isStart = false; 

//获取键盘事件
        this.setFocusable(true);
        //添加键盘监听
        this.addKeyListener(this);
        timer.start();
        foodX=25+25*random.nextInt(20);
        foodY=25+25*random.nextInt(20);
//重写的方法中可以多次按下空格进行开始或者暂停,!isStart是精髓
 public void keyPressed(KeyEvent e) {
        int keyCode=e.getKeyCode();
        if(keyCode==32){
            //标记游戏状态值取反
            isStart=!isStart;
            //重新画组件
            repaint();
9. 让蛇动起来

创建定时器Timer来进行移动,第一个参数表示多长时间运行一次,第二个参数当时间到了以后找谁-this,this需要实现ActionListener接口,重写actionPerformed()方法,也就是当时间到了调用actionPerformed()方法。

在构造方法中启动定时器,当到100毫秒就调用重写actionPerformed()方法。

在重写actionPerformed()方法体中,实现蛇移动;移动蛇的思路:

假如蛇水平向右移动,最后一个身体移动到前面一个身体的位置,也就是x坐标更改,y坐标不动;假如蛇的头部也水平向右移动,蛇的头部x坐标应该在当前位置+25。

Timer timer=new Timer(100,this);

//下面是重写的actionPerformed()方法
 if(isStart){//如果开始则移动
            // 移动身体
            for(int i =len-1;i>0;i--){
                snakeX[i]=snakeX[i-1];
                snakeY[i]=snakeY[i-1];
            }
           //通过方向值direction进行判断
            switch (direction){
                case top:
                    snakeY[0]-=25;
                    if(snakeY[0]<=0){
                        num++;

                        isStart=!isStart;
                        //System.exit(0);
                       // snakeY[0]=900;
                    }
                    break;
                case bottom:
                    snakeY[0]+=25;
                    if(snakeY[0]>=900){

                        num++;
                        isStart=!isStart;
                       // System.exit(0);
                       // snakeY[0]=0;
                    }
                    break;
                case right:
                    //假如蛇向右,蛇头加25
                    snakeX[0]+=25;
                    if(snakeX[0]>=700){

                        num++;
                        isStart=!isStart;
                        //System.exit(0);
                       // snakeX[0]=0;
                    }
                    break;
                case Left:

                    //假如蛇向左,蛇头减25
                    snakeX[0]-=25;
                    if(snakeX[0]<=0){

                        num++;
                        isStart=!isStart;
                        //System.exit(0);
                        //snakeX[0]=700;
                    }
                    break;
            }

 其中我添加了个num来进行死亡代码的判断标记,当蛇头碰到“墙壁”isStart里面的if判断在下面代码。注释中的第一个System,exit相当于碰到墙壁,程序就死去,第二个snakeX[0]和snakeY[0]是设置蛇头碰到坐标0,0时从另一头出来。

10. 实现暂停
 if(!isStart){
            if(num%2==0){
                g.setColor(Color.white);
                g.setFont(new Font("宋体",Font.BOLD,50));
                g.drawString("请按空格键表示游戏开始!",50,500);
            }else {
                g.setColor(Color.white);
                g.setFont(new Font("宋体",Font.BOLD,40));
                g.drawString("你死了游戏分数是"+fenshu,50,450);
            }

        }
11. 实现转向功能
}else if (keyCode==KeyEvent.VK_UP){
                direction=Direction.top;
        } else if (keyCode==KeyEvent.VK_DOWN) {
                direction=Direction.bottom;
        } else if (keyCode==KeyEvent.VK_LEFT) {
                direction=Direction.Left;
        } else if (keyCode==KeyEvent.VK_RIGHT) {
                direction=Direction.right;
        }

 //通过方向值direction进行判断
            switch (direction){
                case top:
                    snakeY[0]-=25;
                    if(snakeY[0]<=0){
                        num++;

                        isStart=!isStart;
                        //System.exit(0);
                       // snakeY[0]=900;
                    }
                    break;
                case bottom:
                    snakeY[0]+=25;
                    if(snakeY[0]>=900){

                        num++;
                        isStart=!isStart;
                       // System.exit(0);
                       // snakeY[0]=0;
                    }
                    break;
                case right:
                    //假如蛇向右,蛇头加25
                    snakeX[0]+=25;
                    if(snakeX[0]>=700){

                        num++;
                        isStart=!isStart;
                        //System.exit(0);
                       // snakeX[0]=0;
                    }
                    break;
                case Left:

                    //假如蛇向左,蛇头减25
                    snakeX[0]-=25;
                    if(snakeX[0]<=0){

                        num++;
                        isStart=!isStart;
                        //System.exit(0);
                        //snakeX[0]=700;
                    }
                    break;
            }
12. 添加食物
//声明两个食物变量   
    int foodX;
    int foodY;
//随机生成食物
    Random random=new Random();
  //食物重新生成
                foodX=25+25*random.nextInt(20);
                foodY=25+25*random.nextInt(20);
13. 吃掉食物

声明分数变量吃到食物身体长度加1,分数加10.

int fenshu=0;
if(snakeX[0]==foodX&&snakeY[0]==foodY){
                //蛇长度加1
  len++;
  fenshu+=10;

二:核心源码

1.  MySnake类
package Demo;

import javax.swing.*;

public class MySnake {
    public static void main(String[] args) {
        //创建一个窗口
        JFrame frame = new JFrame();
        //给窗口设置长宽高
        frame.setBounds(600,100,700,900);
        //不允许拖拽改变大小
        frame.setResizable(false);
        //点击关闭按钮,是退出
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new MyPanel());
        //显示出来
        frame.setVisible(true);





    }


}
2. MyPanel类
package Demo;

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 MyPanel extends JPanel implements KeyListener, ActionListener {
    //声明右侧蛇头和身体
    ImageIcon right = new ImageIcon("D:\\破解工具\\images\\right.png");
    ImageIcon body =new ImageIcon("D:\\破解工具\\images\\body.png");
    //声明上下左的图片
    ImageIcon top=new ImageIcon("D:\\破解工具\\images\\top.png");
    ImageIcon bottom=new ImageIcon("D:\\破解工具\\images\\bottom.png");
    ImageIcon left=new ImageIcon("D:\\破解工具\\images\\left.png");
    //声明蛇的长度
    int len = 3;
int num=2;
int fenshu=0;
    //两个数组分别存放X和Y坐标
    int[] snakeX = new int[1008];//数组最大值是宽乘高
    int[] snakeY = new int[1008];//数组最大值是宽乘高
    //声明一个枚举型变量,标识蛇头方向
    //声明1个变量标记游戏开始True 表示游戏开始,否则没有开始游戏
    boolean isStart = false;
Timer timer=new Timer(100,this);

Direction direction = Direction.right;

//声明两个食物变量
    int foodX;
    int foodY;
    Random random=new Random();
    ImageIcon food=new ImageIcon("D:\\破解工具\\images\\food.png");



    public MyPanel() {
        //设定蛇头和身体的初始位置
        snakeX[0]=100;
        snakeY[0]=100;
        snakeX[1]=75;
        snakeY[1]=100;
        snakeX[2]=50;
        snakeY[2]=100;
        //获取键盘事件
        this.setFocusable(true);
        //添加键盘监听
        this.addKeyListener(this);
        timer.start();
        foodX=25+25*random.nextInt(20);
        foodY=25+25*random.nextInt(20);
    }
//重写画组件方法
    @Override
    protected void paintComponent(Graphics g) {
            //调用父类方法做一些基本工作
        super.paintComponent(g);
        this.setBackground(Color.green);
        g.fillRect(0,0,700,900);
        //添加头
       /* right.paintIcon(this,g,snakeX[0],snakeY[0]);*/
        //根据枚举型变量判断,显示蛇头位置
        switch (direction){
            case top:
                top.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            case bottom:
               bottom.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            case Left:
               left.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            case right:
                right.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
        }

        //添加两个身体
       /* body.paintIcon(this,g,75,100);
        body.paintIcon(this,g,50,100);*/
        for(int i = 1;i<len;i++){
            body.paintIcon(this,g,snakeX[i],snakeY[i]);
        }
        //放上开始提示信息,设置字体和颜色


        if(!isStart){
            if(num%2==0){
                g.setColor(Color.white);
                g.setFont(new Font("宋体",Font.BOLD,50));
                g.drawString("请按空格键表示游戏开始!",50,500);
            }else {
                g.setColor(Color.white);
                g.setFont(new Font("宋体",Font.BOLD,40));
                g.drawString("你死了游戏分数是"+fenshu,50,450);
            }

        }
        food.paintIcon(this,g,foodX,foodY);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode=e.getKeyCode();
        if(keyCode==32){
            //标记游戏状态值取反
            isStart=!isStart;
            //重新画组件
            repaint();
        }else if (keyCode==KeyEvent.VK_UP){
                direction=Direction.top;
        } else if (keyCode==KeyEvent.VK_DOWN) {
                direction=Direction.bottom;
        } else if (keyCode==KeyEvent.VK_LEFT) {
                direction=Direction.Left;
        } else if (keyCode==KeyEvent.VK_RIGHT) {
                direction=Direction.right;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(isStart){//如果开始则移动
            // 移动身体
            for(int i =len-1;i>0;i--){
                snakeX[i]=snakeX[i-1];
                snakeY[i]=snakeY[i-1];
            }
           //通过方向值direction进行判断
            switch (direction){
                case top:
                    snakeY[0]-=25;
                    if(snakeY[0]<=0){
                        num++;

                        isStart=!isStart;
                        //System.exit(0);
                       // snakeY[0]=900;
                    }
                    break;
                case bottom:
                    snakeY[0]+=25;
                    if(snakeY[0]>=900){

                        num++;
                        isStart=!isStart;
                       // System.exit(0);
                       // snakeY[0]=0;
                    }
                    break;
                case right:
                    //假如蛇向右,蛇头加25
                    snakeX[0]+=25;
                    if(snakeX[0]>=700){

                        num++;
                        isStart=!isStart;
                        //System.exit(0);
                       // snakeX[0]=0;
                    }
                    break;
                case Left:

                    //假如蛇向左,蛇头减25
                    snakeX[0]-=25;
                    if(snakeX[0]<=0){

                        num++;
                        isStart=!isStart;
                        //System.exit(0);
                        //snakeX[0]=700;
                    }
                    break;
            }
            if(snakeX[0]==foodX&&snakeY[0]==foodY){
                //蛇长度加1
                len++;
                fenshu+=10;
                //食物重新生成
                foodX=25+25*random.nextInt(20);
                foodY=25+25*random.nextInt(20);
                }
            //重写画组件方法

            repaint();
            //重启定时器
            timer.start();
        }

    }
}
3. Direction类
package Demo;

public enum Direction {//定义枚举方向,四个取值,向上,向下,向左,向右
    top,bottom,Left,right;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值