贪吃蛇游戏.docx
- 文档编号:24235985
- 上传时间:2023-05-25
- 格式:DOCX
- 页数:87
- 大小:164.12KB
贪吃蛇游戏.docx
《贪吃蛇游戏.docx》由会员分享,可在线阅读,更多相关《贪吃蛇游戏.docx(87页珍藏版)》请在冰豆网上搜索。
贪吃蛇游戏
简介
小到一个游戏,大到复杂的企业级应用,都可以称之为一个项目,所有项目的开发,都可以遵循相同的基本开发过程:
需求->分析->设计->实现
需求
请看演示
总结如下:
功能1:
开始游戏
功能2:
暂停游戏
功能3:
重新开始游戏
功能4:
控制方向
分析(OOA)
分析,即对游戏进行面向对象的建模,要正确的分析问题,必须对你要完成的需求有深刻的认识和理解。
思考的主要问题是:
本游戏存在哪些对象?
对象有哪些特性?
哪些对象与哪些对象有关?
其关系是什么?
设计(OOD)
设计是为实现服务的,你必须清楚如何实现,才能进行正确的设计,设计阶段思考的主要问题是:
1、细化各个对象的属性,为了实现的便利,为了更好的复用等等各种目标,充分利用面向对象中的相关概念
2、在完成各种功能的过程中,每个对象应该负责什么(职责分配)?
3、每个对象的职责如何完成?
a)一般需要思考对象需要与哪些其它的对象进行什么样的交互以便完成某个职责
对分析模型进行细化之一
比如,对上述分析类图进行思考,可以看到“节点”与“蛋”,有相同的地方,都具有:
所在行、所在列、大小这样的特性,所以,我们可以对它们进行归纳,抽象为“某种具有位置属性的对象”,即某种“块”。
对分析模型进行细化之二
对贪吃蛇的结构做进一步思考,很显然,这是一种链表数据结构,当贪吃蛇移动的时候,我们可以在贪吃蛇(链表)所指向的链表头节点插入一个前驱节点,同时删除其尾部节点,即可完成贪吃蛇的移动!
我们可以得到如下结论:
1、贪吃蛇对象应该有一个引用指向头节点,当需要往头节点之前插入一个节点的时候,我们需要:
a)改变贪吃蛇对象原来指向的头节点的引用,改为指向新的节点
b)新插入节点的后继节点是原来的头节点
2、因为贪吃蛇的移动过程中,需要不断删除其尾部节点,因此,我们需要的是一个双端链表结构
a)所谓双端链表,即链表对象中既有指向头节点的引用,也有指向尾部节点的引用
b)为什么需要双端链表?
因为如果不是双端的,我们需要从头节点一直往后找才能找到最后一个节点,速度比较慢!
3、如何删除尾部节点?
a)我们需要把尾部节点的前驱节点的后继设置为null,因此,这意味着,任何一个节点既需要能访问其后继节点,也需要能够访问其前驱节点,所以我们需要的是一个双向链表!
b)我们需要改变贪吃蛇对象对尾部节点的引用
由此,我们也可以获得贪吃蛇对象本身,应该具备“移动”的职责!
在“移动”的过程中,需要“插入新的头节点”和“删除尾部节点”这样的功能(在继续实现的过程中,你可能还会发现在移动过程中,还需要判断头部节点是否与蛇中间的任何一个节点产生了碰撞,即形成了闭合,如果形成了闭合,意味着游戏的结束)。
“移动”这种职责(实际上就是一个方法:
method),应该有游戏对象负责调用它!
因此这个方法应该定义为public(公有的可见性)
而“插入新的头节点”和“删除尾部节点”这样的方法,与外部环境无关,应该将其实现细节进行隐藏,所以将其定义为private(私有可见性)
根据此类图,我们可以初步得到如下代码:
●Game.java
packageorg.leadfar.snake;
publicclassGame{
//行数,默认为30行
privateintrows=30;
//列数,默认为30列
privateintcols=30;
//每个单元格的边长,默认为15个像素
privateintsize=15;
//游戏得分,默认取值为0
privateintscore=0;
//游戏当前所处的状态,默认让其处于暂停状态
privateintstatus=STATUS_PAUSE;
publicstaticfinalintSTATUS_RUNING=0;//运行状态
publicstaticfinalintSTATUS_PAUSE=1;//暂停状态
publicstaticfinalintSTATUS_STOP=2;//游戏结束状态
//游戏所包含的贪吃蛇对象
privateSnakesnake;
//游戏所包含的随机出现的蛋
privateEggegg;
}
●Snake.java
packageorg.leadfar.snake;
publicclassSnake{
publicstaticfinalintLEFT=1;//左
publicstaticfinalintRIGHT=2;//右
publicstaticfinalintUP=3;//上
publicstaticfinalintDOWN=4;//下
//运动方向,默认为上移
privateintdirection=UP;
//头节点
privateNodehead;
//尾节点
privateNodetail;
//移动贪吃蛇
publicvoidmove(){
//TODO待实现
}
//插入新的头节点
privatevoidaddToHead(){
//TODO待实现
}
//删除尾部节点
privatevoiddelFromTail(){
//TODO待实现
}
}
●Block.java
packageorg.leadfar.snake;
publicclassBlock{
//所在行
privateintrow;
//所在列
privateintcol;
//大小
privateintsize;
publicintgetRow(){
returnrow;
}
publicvoidsetRow(introw){
this.row=row;
}
publicintgetCol(){
returncol;
}
publicvoidsetCol(intcol){
this.col=col;
}
publicintgetSize(){
returnsize;
}
publicvoidsetSize(intsize){
this.size=size;
}
}
●Node.java
packageorg.leadfar.snake;
publicclassNodeextendsBlock{
//后继节点
privateNodenext;
//前驱节点
privateNodeprevious;
publicNodegetNext(){
returnnext;
}
publicvoidsetNext(Nodenext){
this.next=next;
}
publicNodegetPrevious(){
returnprevious;
}
publicvoidsetPrevious(Nodeprevious){
this.previous=previous;
}
}
●Egg.java
packageorg.leadfar.snake;
publicclassEggextendsBlock{
}
对游戏要实现的各种功能进行设计之一
我们的游戏要实现如下功能:
功能1:
开始游戏
功能2:
暂停游戏
功能3:
重新开始游戏
功能4:
控制方向
这些基本的功能,就是游戏(Game)这个对象,应该提供的基本职责!
因此,我们可以在Game这个类中,增加以下几个方法:
具体代码如下:
//开始游戏
publicvoidstart(){
}
//暂停游戏
publicvoidpause(){
}
//重新开始游戏
publicvoidreStart(){
}
//向左
publicvoidleft(){
}
//向右
publicvoidright(){
}
//向上
publicvoidup(){
}
//向下
publicvoiddown(){
}
对游戏要实现的各种功能进行设计之二:
每个对象的职责如何完成?
下面针对每个对象的职责,逐个思考其实现的思路
一般我们需要思考如下问题:
●我们需要改变哪些对象的什么状态值(属性值)?
●我们需要与哪些对象进行交互(调用哪些对象的哪些方法)?
Game中每个方法的基本思路如下:
●当游戏开始的时候,我们需要做什么?
-实现start方法的思路
我们当初设想一开始游戏处于暂停状态,所以start的时候,需要把游戏状态改为运行状态
●实现pause方法的思路
改变游戏的状态为暂停
●实现reStart方法的思路
重新开始,意味着需要将游戏的所有状态进行初始化,主要是游戏得分应该归0、重新创建一个snake对象、重新生成egg对象!
而且,重新开始之后,应该直接将游戏状态设置为运行状态(即马上重新开始)
●控制方向相关方法的实现思路
在这些方法的实现中,实际上,我们是要改变snake对象的方向值!
Snake中各个方法的实现思路,则主要是链表数据结构的实现思路!
各种对象总体的职责及交互思路
游戏状态转换图
实现(OOP)
但是,到目前为止,我们的程序依然不可以运行!
在哪里开始运行?
这将涉及到一系列具体的跟实现有关的问题:
●如何显示我们的游戏界面?
●如何在游戏界面上画出我们需要的线条、方块和文字?
●我们敲击键盘上的按键,如何才能调用到Game中的各种方法?
●如何让贪吃蛇自动往前移动?
●如何随机生成一个蛋对象?
●等等等等
在实现阶段,我们需要考虑在哪个平台上用哪种技术来实现?
我们需要熟悉具体的API。
很显然,你在一个Android这样的手机操作系统上开发这个游戏,与在电脑上开发这样的游戏,在具体实现的时候,会有很大的不同,显示游戏界面、接收键盘或触摸屏的输入等方式也各不相同,因此,我们在实现之前,必须选定一种具体的实现技术和平台。
我们将:
●用Java来实现
●用Java中的AWT技术来显示界面、画出线条、方块、文字和接收键盘输入
●用一个线程来控制界面的刷新,并控制贪吃蛇的自动移动
●用JDK类库中的相关类来随机在某个位置生成一个蛋对象
创建一个窗口
如下代码演示了如何用Java显示一个窗口
packagedemo;
importjava.awt.Frame;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
//Game继承Frame类,表示一个窗口
publicclassGameextendsFrame{
//行数,默认为30行
privateintrows=30;
//列数,默认为30列
privateintcols=30;
//每个单元格的边长,默认为15个像素
privateintsize=15;
privatevoidlaunch(){
//在屏幕上x=200,y=200这个位置上显示窗口
this.setLocation(200,200);
//设置宽度是:
rows*size(像素)
//设置高度是:
cols*size(像素)
this.setSize(rows*size,cols*size);
//设置窗口事件监听器
this.addWindowListener(newWindowAdapter(){
//当点击关闭按钮的时候,退出整个应用程序
publicvoidwindowClosing(WindowEvente){
System.exit(0);//退出整个应用程序
}
});
//将窗口设置为可见
this.setVisible(true);
}
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
//创建一个游戏窗口,并运行显示出来
newGame().launch();
}
}
将窗口背景设置为灰色,并用深灰色画出横线和竖线
packagedemo;
importjava.awt.Color;
importjava.awt.Frame;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
//Game继承Frame类,表示一个窗口
publicclassGameextendsFrame{
//行数,默认为30行
privateintrows=30;
//列数,默认为30列
privateintcols=30;
//每个单元格的边长,默认为15个像素
privateintsize=15;
//游戏得分,默认取值为0
privateintscore=0;
//AWT中的双缓冲技术
privateImageoffScreenImage=null;
privatevoidlaunch(){
//在屏幕上x=200,y=200这个位置上显示窗口
this.setLocation(200,200);
//设置宽度是:
rows*size(像素)
//设置高度是:
cols*size(像素)
this.setSize(rows*size,cols*size);
//设置窗口事件监听器
this.addWindowListener(newWindowAdapter(){
//当点击关闭按钮的时候,退出整个应用程序
publicvoidwindowClosing(WindowEvente){
System.exit(0);//退出整个应用程序
}
});
//将窗口设置为可见
this.setVisible(true);
//设置窗口的标题
this.setTitle("贪吃蛇游戏");
}
@Override
publicvoidpaint(Graphicsg){
//Graphics相当于画笔,这是取出画笔的颜色
Colorc=g.getColor();
//设置为灰色
g.setColor(Color.GRAY);
//将整个背景填充为灰色
//x,y,width,height
g.fillRect(0,0,cols*size,rows*size);
//设置为深灰色
g.setColor(Color.DARK_GRAY);
//画所有的横线
for(inti=1;i //从起点向终点画线: x1,y1,x2,y2 g.drawLine(0,size*i,cols*size,size*i); } //画所有的竖线 for(inti=1;i //从起点向终点画线: x1,y1,x2,y2 g.drawLine(size*i,0,size*i,size*rows); } g.setColor(Color.YELLOW); g.drawString("现在得分是: "+score,10,60); g.setColor(c); } @Override //AWT中为了处理直接画到Frame上时有闪烁,双缓冲技术 publicvoidupdate(Graphicsg){ if(offScreenImage==null){ //创建一张图片,宽度和高度与当前窗口相同 offScreenImage=this.createImage(cols*size,rows*size); } GraphicsgOff=offScreenImage.getGraphics(); paint(gOff); //一次性将图片画到屏幕上,避免闪烁 g.drawImage(offScreenImage,0,0,null); } /** *@paramargs */ publicstaticvoidmain(String[]args){ //创建一个游戏窗口,并运行显示出来 newGame().launch(); } } 如何接收键盘的输入? 我们可以在窗口运行的时候,加入键盘的事件监听器 packagedemo; importjava.awt.Color; importjava.awt.Frame; importjava.awt.Graphics; importjava.awt.Image; importjava.awt.event.KeyAdapter; importjava.awt.event.KeyEvent; importjava.awt.event.WindowAdapter; importjava.awt.event.WindowEvent; //Game继承Frame类,表示一个窗口 publicclassGameextendsFrame{ //行数,默认为30行 privateintrows=30; //列数,默认为30列 privateintcols=30; //每个单元格的边长,默认为15个像素 privateintsize=15; //游戏得分,默认取值为0 privateintscore=0; //AWT中的双缓冲技术 privateImageoffScreenImage=null; privatevoidlaunch(){ //在屏幕上x=200,y=200这个位置上显示窗口 this.setLocation(200,200); //设置宽度是: rows*size(像素) //设置高度是: cols*size(像素) this.setSize(rows*size,cols*size); //设置窗口事件监听器 this.addWindowListener(newWindowAdapter(){ //当点击关闭按钮的时候,退出整个应用程序 publicvoidwindowClosing(WindowEvente){ System.exit(0);//退出整个应用程序 } }); //设置键盘事件监听器 this.addKeyListener(newKeyAdapter(){ //某个键被按下的时候,触发本事件的执行! @Override publicvoidkeyPressed(KeyEvente){ intkeyCode=e.getKeyCode(); switch(keyCode){ caseKeyEvent.VK_F5: {//按下F5,游戏开始 System.out.println("游戏开始"); }break; caseKeyEvent.VK_F6: {//按下F6,游戏暂停 System.out.println("游戏暂停"); }break; caseKeyEvent.VK_F7: {//按下F7,游戏重新开始 System.out.println("游戏即将重新开始"); }break; caseKeyEvent.VK_LEFT: {//按下left,游戏重新开始 System.out.println("贪吃蛇向左移动"); }break; caseKeyEvent.VK_RIGHT: {//按下right,游戏重新开始 System.out.println("贪吃蛇向右移动"); }break; caseKeyEvent.VK_UP: {//按下up,游戏重新开始 System.out.println("贪吃蛇向上移动"); }break; caseKeyEvent.VK_DOWN: {//按下down,游戏重新开始 System.out.println("贪吃蛇向下移动"); }break; } } }); //将窗口设置为可见 this.setVisible(true); //设置窗口的标题 this.setTitle("贪吃蛇游戏"); } @Override publicvoidpaint(Graphicsg){ //Graphics相当于画笔,这是取出画笔的颜色 Colorc=g.getColor(); //设置为灰色 g.setColor(Color.GRAY); //将整个背景填充为灰色 //x,y,width,height g.fillRect(0,0,cols*size,rows*size); //设置为深灰色 g.setColor(Color.DARK_GRAY); //画所有的横线 for(inti=1;i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 贪吃 游戏