实验内容

一、实现贪吃蛇游戏的基本功能,屏幕上随机出现一个豆子,上下左右控制蛇的移动,吃到豆子以后蛇的身体加长一节。
二、蛇碰到边界,蛇死亡,游戏结束。
三、对蛇吃到豆子进行分值计算,并显示。

实验平台

通过高级程序设计语言(JAVA)实现贪吃蛇。

相关知识

①JAVA图形用户界面设计GUI
使用AWT组件库设计图形界面,如窗口Frame、面板Panel等。

引入

import java.awt.Frame;
import java.awt.Panel;

②链表LinkedList
一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

引入 LinkedList 类

import java.util.LinkedList;

普通创建方法

LinkedList<Node> Body = new LinkedList<>();

java贪吃蛇课程设计 java课程设计贪吃蛇游戏_java贪吃蛇课程设计


③键盘事件,如KeyEvent,KeyListener等

引入

//按键事件
import java.awt.event.KeyEvent;
//键盘监听
import java.awt.event.KeyListener;

按键常量

java贪吃蛇课程设计 java课程设计贪吃蛇游戏_sed_02


当按下一个键时会调用KeyPressed处理器,当松开一个键时会调用KeyReleased处理器,当输入一个统一编码时会调用KeyTyped处理器。

java贪吃蛇课程设计 java课程设计贪吃蛇游戏_java贪吃蛇课程设计_03

每个按键事件有一个相关的按键字符和按键代码,分别由KeyEvent中的getKeyChar()和getKeyCode()方法返回。

java贪吃蛇课程设计 java课程设计贪吃蛇游戏_java_04

④线程thread

创建线程

Thread thread = new Thread();

实现Runnable接口

public class GameRunThread implements Runnable {
    public void run() {
        System.out.println("...");
    }
}

调用run()方法

如果直接调用Thread类的run方法即thread.run(),那么相当于普通对象调用自身方法一样,是同步的,并不是一个新的线程。

调用start()方法

调用了start方法thread.start(),即通知线程规划器,当前线程已经初始化好了,准备就绪。线程规划器则会去以一个新的线程去执行run方法。
调用了start方法知识通知了线程规划器,并不代表先通知,就一定会被先执行的。

⑤双缓冲技术

双缓冲技术的工作原理
先在内存中分配一个和我们动画窗口一样大的空间(在内存中的空间我们是看不到的),然后利用getGraphics()方法去获得双缓冲画笔,接着利用双缓冲画笔给空间我们想画的东西,最后将它全部一次性的显示到我门的屏幕上.这样在我门的动画窗口上面是显示出来就非常的流畅了.避免了上面的闪烁效果。

执行过程
repaint() 到update()再到paint(),而我们的双缓冲代码就写在update()里。
(1)定义一个Graphics对象gBuffer和一个Image对象iBuffer。按屏幕大小建立一个缓冲对象给iBuffer。然后取得iBuffer的Graphics赋给gBuffer。此处可以把gBuffer理解为逻辑上的缓冲屏幕,而把iBuffer理解为缓冲屏幕上的图象。
(2)在gBuffer(逻辑上的屏幕)上用paint(Graphics g)函数绘制图象。
(3)将后台图象iBuffer全部一次性的绘制到我们的动画窗口,然后把我们内存中分配的空间窗口关闭调用dispose()方法.

代码

import java.awt.Image;
 import java.awt.Graphics;
 private Image iBuffer;
 private Graphics gBuffer;
 public void update(Graphics g) {
     if(iBuffer == null)  {  
        //创建用于双缓冲的屏幕外可绘制图像
        iBuffer = createImage(DrawView.WIDTH * DrawView.SIZE + 1, DrawView.HEIGHT * DrawView.SIZE + 1);  
        gBuffer = iBuffer.getGraphics();  
     }  
     gBuffer.setColor(getBackground());  
     gBuffer.fillRect(0,0,DrawView.WIDTH * DrawView.SIZE + 1, DrawView.HEIGHT * DrawView.SIZE + 1);  
     //调用paint(),将缓冲图象的画传入
     paint(gBuffer);  
     //再将此缓冲图像一次性绘到代表屏幕的Graphics对象,即该方法传入的“g”上
     g.drawImage(iBuffer,0,0,this); 
 }

具体步骤

java贪吃蛇课程设计 java课程设计贪吃蛇游戏_java_05

Node类:蛇是由一个一个节点组成,所以首先将节点抽象为一个类,获取或者访问的方法,set()和get()方法。

Snake类:此类是一条蛇抽象出来的一个类。一种包含了存储节点的 LinkedList 类型的集合,作为蛇的Body。

(1)getDirection()方法:获取蛇的方向;

(2)setDirection()方法:设置蛇的方向;

(3)getSnakeHead()方法:获取蛇的头部节点;

(4)getSnakeBody()方法:获取蛇的Body;

(5)snakeMove()方法:蛇的移动是在头部加一个节点,尾部减去一个节点,0,1,2,3分别代表上右下左四个方向;

(6)eatEgg()方法:如果蛇的头节点与egg的节点相等,随机生成一个egg,Body增加一个节点,此时score加1;

(7)snakeRunInterface()方法:蛇越界的方法,如果蛇的头节点不在定义的范围内,则静态逻辑变量gameState为false。

SnakeGameView类:该类继承了Frame类,是一个游戏界面的类,用于布局游戏的界面。创建一个线程thread。

(1)setEgg()方法:设置egg节点;

(2)getScore()方法:获得分数;

(3)showView()方法:图形界面,包括主界面,分数,操作提示等;

(4)在主方法中启动线程。

DrawView类:此类继承了Panel类,从而拥有了paint()方法的使用权,其中存在一个问题,就是游戏在不断的重画过程中,会出现游戏的闪烁问题,就引出了双缓冲的技术。

(1)paint(Graphics g)方法:用于游戏面板的重画,像网格、蛇、蛋的重画;

(2)update(Graphics g)方法:更新画面,利用双缓冲的技术解决界面闪烁的问题;

(3)drawGridding(Graphics g)方法:画网格,用for循环分别画横线和竖线;

(4)drawSnake(Graphics g)方法:画蛇;

(5)drawEgg(Graphics g)方法:画蛋。

GameControl类:此类装配了KeyListener接口,用于监听键盘,从而实现按键对游戏的操作。

keyReleased(KeyEvent ke)方法:分四种情况,调用Snake中的setDirection()方法,给定实参0或1或2或3,分别代表上右下左四个方向。

GameRunThread类:此类装配了Runnable接口,是一个线程类,用于不断重画界面。

run()方法:如果SnakeGameView类里面的静态逻辑变量gameState为true,重新绘制界面。