java版的贪吃蛇毕业论文.docx
《java版的贪吃蛇毕业论文.docx》由会员分享,可在线阅读,更多相关《java版的贪吃蛇毕业论文.docx(20页珍藏版)》请在冰豆网上搜索。
![java版的贪吃蛇毕业论文.docx](https://file1.bdocx.com/fileroot1/2023-1/21/dcfd6475-748a-4b2d-899d-ad3d8546cf18/dcfd6475-748a-4b2d-899d-ad3d8546cf181.gif)
java版的贪吃蛇毕业论文
贪吃蛇【1】
姓名:
摘要:
本文用J2SE实现大家耳熟能详的一个贪吃蛇游戏来综合运用所学知识,本游戏运用软件工程思想(螺旋模型),打好游戏主体框架,JAVA的面向对象思想,封装类,接口等概念,来完成本游戏,打到综合运用知识的目的。
⑴.本游戏开发平台:
WINXP;
⑵.JAVA开发环境:
JDK1.6+Eclipse;
⑶.开发语言:
J2SE
关键词:
中央控制器;游戏面板;食物;蛇;石头
TheGreedSnake
Abstract:
Inthispaper,J2SEimplementationofaSnakegamefamiliartotheintegrateduseofwhattheyhavelearned,thisgameistheuseofsoftwareengineeringthinking(spiralmodel),themainframeworkofthefightgame,JAVAobject-orientedthinking,wrapperclasses,interfaceconceptstocompletethisgame,hittingtheintegrateduseofknowledgeandpurpose.
⑴.Thegamedevelopmentplatform:
WINXP;
⑵.JAVADevelopmentEnvironment:
JDK1.6+Eclipse;
⑶.DevelopmentLanguages:
J2SE
Keywords:
Controller;GamePanel;Food;Snake;Ground
前言
贪吃蛇游戏背景:
蛇引诱夏娃吃了苹果之后,就被贬为毒虫,阴险的象征。
而蛇吃东西是整只动物吞进去的,大概在文艺复兴的时候(好象是那个时候但是不确定)就有人发明的一种游戏,是现在贪吃蛇的前身。
后来慢慢的发展就变成了今天的贪吃蛇了、现在贪吃蛇主要应用于手机游戏。
本文运用软件工程思想、JAVA面向对象编程、类的封装、抽象类的使用(接口),游戏编码规范遵循MVC模式,循序渐进实现贪吃蛇的相关功能。
一:
游戏中的面向对象分析与设计
㈠●涉及到几个对象(类)
㈡●每个类有什么方法
1.首先得有个游戏显示面板(GamePanel)类
该类有一个方法voiddisplay();//用来显示游戏面板
2.得有个蛇(Snake)类
该类有以下几个方法:
voidmove();//移动(走一步)
voidchangeDirection();//改变方向
voideatFood();//吃食物(身体变长)
vooleanisEatBody();//蛇是否吃到了自己的身体
voiddrawMe();//显示
3.一个食物类(Food)类
该类有以下方法:
booleanisSnakeEatFood(Snake);//判断蛇是否吃到了食物
voiddrawMe();//显示
4.一个背景石头(Ground)类
该类有以下方法:
BooleanisSnakeEatRock(Snake);//蛇是否吃到了石头
voiddrawMe();//显示
此时类之间的关系如下图所示:
图1各个类之间的关系
二:
编写贪吃蛇游戏中的各个类的主体框架性代码
本有序遵循MVC(Model-View-Controller)所以首先建立以上几个实体类并定义相应的包名:
liang.snake.entities包下定义Food、Ground、Snake三个类,再在liang.snake.view包下定义GamePanel类,再在,按照以上说明的各个类具有的方法,写上如下代码:
packageliang.snake.entities;
publicclassFood{
publicbooleanisSnakeEatFood(Snakesnake)
{
System.out.println("Snake'seatfood");
returnfalse;
}
publicvoiddrawme()
{
System.out.println("Food'sdrawme");
}
}
packageliang.snake.entities;
publicclassGround{
publicbooleanisSnakeEatRock()
{
returnfalse;
}
publicvoiddrawme()
{
System.out.println("Ground'sdrawme");
}
}
packageliang.snake.entities;
publicclassSnake{
publicvoidmove()
{
System.out.println("Snake'smove");
}
publicvoidchangeDirection(intdirection)
{
System.out.println("Snake'schangeDirection");
}
publicvoideatFood()
{
System.out.println("Snake'seatfood");
}
publicbooleanisEatBody()
{
System.out.println("Snake'seatbody");
returnfalse;
}
publicvoiddrawMe(){
System.out.println("Snake'sdrawMe");
}
packageliang.snake.view;
importjava.awt.Graphics;
importjavax.swing.JPanel;
importliang.snake.entities.Food;
importliang.snake.entities.Ground;
importliang.snake.entities.Snake;
publicclassGamePanelextendsJPanel{
privateSnakesnake;
privateGroundground;
privateFoodfood;
publicvoidpaintComponent(Graphicsg){
snake.drawMe();
ground.drawme();
food.drawme();
}
publicvoiddisplay(Snakesnake,Groundground,Foodfood)
{
this.snake=snake;
this.ground=ground;
this.food=food;
System.out.println("GamePanel'sdisplay");
this.repaint();
}
三:
编写Controler类与实现蛇移动的事件监听
由于蛇不能直接操作显示面板(GamePanel)所以这里定义一个监听器SnakeListener:
里面定义一个方法:
voidsnakeMove(Snake);每当蛇移动一步就触发监听器,调用snakeMoved()由Controller去实现监听器的接口,然后由控制器去触发显示面板的事件源,让显示面板完成相应操作。
逻辑图如下:
图2事件监听建立联系
在Snake中增加蛇的方向常量:
publicstaticfinalintUP=1;
publicstaticfinalintDOWN=-1;
publicstaticfinalintLEFT=2;
publicstaticfinalintRIGHT=-2;
并添加一个接口:
packageliang.snake.Listener;
importliang.snake.entities.Snake;
publicinterfaceSnakeListener{
publicvoidSnakeMove(Snakesnake);
}
Controler实现SnakeListener接口并处理案件消息:
代码如下:
packageliang.snake.Controller;
importjava.awt.event.KeyAdapter;
importjava.awt.event.KeyEvent;
importliang.snake.Listener.SnakeListener;
importliang.snake.entities.Food;
importliang.snake.entities.Ground;
importliang.snake.entities.Snake;
importliang.snake.view.GamePanel;
publicclassControllerextendsKeyAdapterimplementsSnakeListener{
Snakesnake=newSnake();
Groundground=newGround();
Foodfood=newFood();
GamePanelgamepanel=newGamePanel();
publicController(Snakesnake,Groundground,Foodfood,GamePanelgamepanel){
this.snake=snake;
this.ground=ground;
this.food=food;
this.gamepanel=gamepanel;
}
publicvoidkeyReleased(KeyEvente){
switch(e.getKeyCode())
{
caseKeyEvent.VK_UP:
snake.changeDirection(Snake.UP);
break;
caseKeyEvent.VK_DOWN:
snake.changeDirection(Snake.DOWN);
break;
caseKeyEvent.VK_LEFT:
snake.changeDirection(Snake.LEFT);
break;
caseKeyEvent.VK_RIGHT:
snake.changeDirection(Snake.RIGHT);
break;
}
}
publicvoidnewgame()
{
snake.start();
}
publicvoidSnakeMove(Snakesnake){
gamepanel.display(snake,ground,food);
}
}
开发到此时,Snake中应该增加监听器,并另启动一个线程来不断调用蛇的move();在Snake中提供一个启动线程的方法,在Snake中增加如下代码:
privateSetlistener=new
HashSet();
publicvoidaddSnakeListener(SnakeListenerl)
{
if(l!
=null)
this.listener.add(l);
}
}
publicvoidstart()
{
newThread(newSnakeDriver()).run();
}
并在Run方法中增加
for(SnakeListenerl:
listener)
{
l.SnakeMove(Snake.this);}
try
{
Thread.sleep(1000);
}
catch(InterruptedExceptione)
{
e.printStackTrace();
}
四:
编写对各个类进行测试的程序代码
构建一个新类Game来测试程序代码:
packageliang.snake.Game;
importjava.applet.AudioClip;
importjava.awt.BorderLayout;
importjava.io.File;
import.MalformedURLException;
import.URL;
importjavax.swing.JFrame;
importliang.snake.Controller.Controller;
importliang.snake.entities.Food;
importliang.snake.entities.Ground;
importliang.snake.entities.Snake;
importliang.snake.view.GamePanel;
publicclassGame{
publicstaticvoidmain(String[]args){
JFramejf=newJFrame("我的论文");
Snakesnake=newSnake();
Groundground=newGround();
Foodfood=newFood();
GamePanelgamepanel=newGamePanel();
Controllercontroller=newController(snake,ground,food,gamepanel);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation(400,0);
jf.setSize(800,600);
jf.add(gamepanel);
jf.addKeyListener(controller);
snake.addSnakeListener(controller);
jf.setVisible(true);
controller.newgame();
}
}
运行这个带有main()的类,在Eclipse的Console窗口中可以看到如下信息:
Snake'smove
GamePanel'sdisplay
Snake'sdrawMe
Ground'sdrawme
Food'sdrawme
Snake'sdrawMe
Ground'sdrawme
Food'sdrawme
Snake'smove
GamePanel'sdisplay
Snake'sdrawMe
Ground'sdrawme
Food'sdrawme
这就意味着,当蛇移动一次,就触发监听器,有控制器(controller)给GamePanel发送指令,让它重画,GamePanel中的
publicvoiddisplay(Snakesnake,Groundground,Foodfood)
{
System.out.println("GamePanel'sdisplay");
this.snake=snake;
this.ground=ground;
this.food=food;
this.repaint();
}
这个方法依次画出几个实体,所以打印出上述信息。
到了这一步我们的基本框架打好了,下面开始第5步
五:
蛇的数据结构设计与移动显示
分析:
要区分蛇头和蛇尾巴,这就要求这个数据结构是有序的,
还要经常访问第一个和最后一个节点,所以LinkedList最合适,因为它有getFirst(),getLast()方法和removeLast()方法
蛇下一步移动到哪是由方向控制的,前面已经定义过,蛇透坐标如下图:
图3蛇头方向计算新蛇头坐标
在Snake的move()中增加
body.removeLast();
intx=body.getFirst().x;
inty=body.getFirst().y;
switch(direction)
{
caseUP:
y--;
break;
caseDOWN:
y++;
break;
caseLEFT:
x--;
break;
caseRIGHT:
x++;
break;
}
Pointnewhead=newPoint(x,y);
//加头
body.addFirst(newhead);
并定义privateintdirection;
为了能更方便的维护游戏,这里定义Global类来定义常量如下:
packageliang.snake.Global;
publicclassGlobal{
publicstaticfinalintCELL_SIZE=20;
publicstaticintHIGHT=30;
publicstaticintWIDTH=30;
}
并修改游戏中窗口大小为:
jf.setSize(Global.CELL_SIZE*Global.WIDTH,Global.CELL_SIZE*Global.HIGHT);
再加上如下代码,对蛇初始化:
publicSnake()
{
init();
}
publicvoidinit()
{
intx=Global.WIDTH/2;
inty=Global.HIGHT/2;
intnodenum=3;
for(inti=0;i{
body.addFirst(newPoint(x++,y));
}
this.direction=RIGHT;
}
在蛇的drawMe(Graphicsg)中些上如下让蛇显示的代码:
这里的画图采用填充3D矩形来实现:
for(Pointp:
body)
{
g.fill3DRect(p.x*Global.CELL_SIZE,p.y*Global.CELL_SIZE,Global.CELL_SIZE,Global.CELL_SIZE,true);
}
画图的规则如下图:
图4计算格子坐标和像素坐标
此时运行Game类就可以看到蛇显示在面板中了,如图:
图5显示面板显示的蛇
但是蛇越走越长,是因为没有擦除以前的图像,在GamePanel的paintComponent(Graphicsg)中添加如下代码:
g.setColor(newColor(0xcfcfcf));
g.fill3DRect(0,0,Global.CELL_SIZE*Global.WIDTH,Global.CELL_SIZE*Global.HIGHT,true);
此时蛇就可以正常移动了如图:
图6移动中的蛇
通过按键改变移动方向,此时的蛇身体节点显示为白色,我们再在蛇的绘制方法中位器指定颜色:
代码如下:
图7指定颜色后的蛇
六:
试与修正蛇的移动与显示问题
此时的蛇当移动到窗口边界的时候就能走出窗口还有蛇可以穿过自己的身体,这些游戏规则中式不允许的,下面来修正这些问题,修改Snake中的move()方法如下:
首先定义publicintolddirection,newdirection;
防止蛇穿过自己身体:
publicvoidmove()
{
//去尾
if(olddirection+newdirection!
=0)
{
olddirection=newdirection;
}
body.removeLast();
intx=body.getFirst().x;
inty=body.getFirst().y;
switch(olddirection)
{
caseUP:
y--;
if(y<0)
{
y=Global.HIGHT-1;
}
break;
caseDOWN:
y++;
if(y>=Global.HIGHT)
{
y=0;
}
break;
caseLEFT:
x--;
if(x<0)
{
x=Global.WIDTH-1;
}
break;
caseRIGHT:
x++;
if(x>=Global.WIDTH)
{
x=0;
}
break;
}
Pointnewhead=newPoint(x,y);
//加头
body.addFirst(newhead);
System.out.println("Snake'smove");
}
publicvoidchangeDirection(intdirection)
{
System.out.println("Snake'schangeDirection");
newdirection=direction;
并修改蛇的初始化方法如下:
olddirection=newdirection=RIGHT;
此时就修正了上面的问题,可以运行Game类来测试下
七:
编写与测试表示食物的类并实现吃食物
首先在Snake类中添加publicPointgetHead()
{
returnbody.getFirst();
}
用来获取头结点,然后再Food类中写上如下代码:
packageliang.snake.entities;
importjava.awt.Color;
importjava.awt.Graphics;
importjava.awt.Point;
importliang.snake.Global.Global;
publicclassFoodextendsPoint{
publicvoidnewfood(Pointp)
{
this.setLocation(p);
}
publicbooleanisSnakeEatFood(Snakesnake)
{
System.out.println("Snake'seatfood");
returnthis.equals(snake.getHead());
}
publicvoiddrawme(Graphicsg)
{
System.out.println("Food'sdrawme");
g.fill3DRect(this.x*Global.CELL_SIZE,this.y*Global.CELL_SIZE,Global.CELL_SIZE,Global.CELL_SIZE,true);
}
}
此时就可以画出食物并判断蛇是否吃到了食物,接下来就可以在Controller中处理吃食物的代码,吃了食物我们只要把先前移动去除的尾巴再给加上就实现了蛇吃食物身体变长的效果了,如下:
定义PointoldTail;
在蛇move()中保存去除的尾巴:
oldTail=body.removeLast();
在Controller