基于android平台的 “贪吃蛇”技术报告
第五组
组员:许菲 侯怡婷 何俊涛
全巍 雷永普
目 录
?1 系统描述 .............................. 1 1.1 本
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
的目的和意义 .............................................................. 1 1.2 设计的主要内容 ..................................................................... 1 1.4 设计实现功能和目标 .............................................................. 2 1.5游戏设计环境 .......................................................................... 3 ?2 游戏需求分析 ............................ 3 2.1 游戏处理流程 ......................................................................... 3 2.2 需求分析 ................................................................................ 4 2.3 功能模块设计 ......................................................................... 6 2.4 类模块设计 ............................................................................. 7 2.5 游戏图形界面的图形显示更新功能 ........................................ 8 ?3 游戏的基本实现 ........................ 8 3.1 游戏界面的实现 ..................................................................... 8 3.2 游戏整个框架的构建 ............................................................ 10 3.3 实现键盘响应事件: .......................................................... 14 3.4 刷新 .................................................................................... 15 3.5 实现页面的切换 ................................................................. 15 3.6 加载游戏 ............................................................................ 16 ?4 对游戏界面以及其他方面的改进 .......... 16 4.1游戏背景界面的改进 ............................................................. 16 4.2 添加音效 .............................................................................. 16
- 1 -
4.3 游戏本身的完善 ................................................................... 16 ?5 类模块具体设计 ........................ 19 5.1 TitleView.java.................................................................... 19 5.2 SnakeView.java.................................................................... 19 ?6 系统测试 ............................. 21 ?7
心得体会
决胜全面小康心得体会学党史心得下载党史学习心得下载军训心得免费下载党史学习心得下载
............................. 24 附录 “贪吃蛇游戏”程序部分源代码 .......... 27
- 2 -
基于手机android平台的 “贪吃蛇”的设计和实现 内容提要:
“贪吃蛇”游戏是一个经典的游戏~它因操作简单、娱乐性强而广受欢迎。本文基于Java技术和android开发环境~开发了一个操作简单、界面美观、功能较齐全的“贪吃蛇”游戏。整个游戏程序分为三个功能模块~五个类模块~实现了游戏的开始、暂停、结束。通过本游戏的开发~达到学习android平台操作技术和熟悉软件开发流程的目的。
?1 系统描述
1.1 本设计的目的和意义
贪吃蛇游戏是一款非常经典的手机游戏~贪吃蛇游戏的设计比较复杂~它涉及面广、牵涉方面多~如果不好好考虑和设计~将难以成功开发出这个游戏。在这个游戏的设计中~牵涉到图形界面的显示与更新、数据的收集与更新~并且在这个游戏的开发中~还要应用类的继承机制以及一些设计模式。因此~在设计开发过程中~需要处理好各个类之间间的逻辑依赖关系和数据通信关系。
正是因为如此~本次设计的目的在于学习Java程序设计基本技术~学习用android开发Java程序的相关技术~熟悉游戏“贪吃蛇”的需求~熟悉项目开发的完整过程。学会怎样进行一个项目的需求分析、概要设计、详细设计等软件开发过程~熟练地掌握Java程序设计的基本技术和方法~熟练地掌握android环境的使用方法~培养初步的项目分析能力和程序设计能力。
1.2 设计的主要内容
- 1 -
贪吃蛇游戏设计与实现~主要分为以下三个模块:游戏主界面模块、游戏控制模块和游戏菜单模块。在此只实现游戏的游戏主界面模块、游戏控制模块和游戏菜单模块~并且只是实现开始、暂停、退出等最基本简单的功能。
本次设计要达到的目标分别从以下模块进行阐述:
,1,游戏菜单模块:
这个模块主要是为进入游戏做准备~是进入游戏的第一步~提供“开始游戏”“游戏帮助”“退出游戏”等按钮~通过帮助按钮简单介绍游戏规则。
,2,游戏主界面模块:
游戏的主界面是进入游戏后~能够给玩家第一感官的部分~主要包括游戏图形区域界面、游戏分数以及关卡的显示更新界面、提示退出游戏的快捷方式~游戏开始按钮、暂停游戏按钮以及退出游戏按钮。从很大程度上决定了玩家对游戏的兴趣问题~因此~游戏的主界面应该力求美观~爽心悦目。
,3,游戏控制模块:
这个模块是游戏的中心环节~主要完成控制游戏的开始、暂停、退出~移动~加速等功能。为了能够给玩家一个很好的游戏环境~这部分应该做到易懂、易操作。
1.4 设计实现功能和目标
本设计所开发的是基于android手机平台的一个贪吃蛇游戏软件~主要实现游戏的开始、暂停、退出等功能~分为: 游戏主界面模块、游
- 2 -
戏控制模块和游戏菜单三个模块。
性能:
本软件在设计方面本着方便、实用及娱乐性高的宗旨~在对界面进行设计的过程中~始终坚持清晰明了~在性能方面能够实现效率高~不易出错等优点。
,1,游戏主界面模块:
主要包括游戏图形区域界面、游戏开始按钮、暂停游戏按钮、关闭按钮。游戏的主界面应该力求美观~爽心悦目。
,2,游戏控制模块:
主要完成控制游戏的开始、暂停、退出等功能~这部分应该做到易懂、易操作而且准确率高~不易出错。
,3,游戏菜单模块:
是进入游戏主界面的第一步~提供“游戏帮助”等功能。这部分使贪吃蛇游戏软件更加完善。
1.5游戏设计环境
android模拟器~模拟实现手机上的贪吃蛇游戏开发。软件包括:
? android-sdk
? eclipse
? jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008
?2 游戏需求分析
2.1 游戏处理流程
- 3 -
本次游戏设计的处理流程图如下所示。
开始
初始化界面和蛇身
游戏者按键选
择
放置食物
蛇开始运动
蛇吃到食? N
Y
蛇长大
N
蛇死
亡? Y Y
继续
续
? N
退出界面
2.2 需求分析
2.2.1 用户的特点
游戏开发成功后~最终用户为各个年龄段的人群~用户范围相当
- 4 -
广泛。本游戏友好的用户界面~简单易学的按钮操作以及简单通俗的游戏规则~使广大的用户不需要专门进行培训~就可以立即学会如何使用。 2.2.2 功能需求
贪吃蛇是一款经典的手机游戏~一条蛇在封闭围墙里~通过按键盘上下左右四个键控制蛇向上下左右四个方向移动~如果蛇头撞倒食物~则食物被吃掉~蛇身体长一节~同时记1分,若吃到奖励苹果~加两分,若吃到毒苹果~则减3分。在游戏过程中~如果长按住方向键不放~则蛇的移动速度加快~松开方向键~恢复原速。如果蛇在移动中撞到墙或障碍物或者蛇头撞倒自己身体~则游戏结束:
,1, 游戏主界面模块需求
游戏界面主框架主要包括游戏图形区域界面、游戏开始按钮、游戏暂停按钮、关闭按钮。
,2, 游戏图形区域界面的需求
游戏画布区主要应该包括游戏画布中贪吃蛇随机出现的位置~贪吃蛇重新出现的位置~事物随机出现的位置。
,3, 游戏菜单模块的需求
游戏菜单模块主要是为进入游戏主界面做准备~提供“游戏帮助”介绍游戏规则。同时提供进入游戏和退出游戏等功能。
2.2.3 属性需求
在可使用性方面~要求各个功能实现简单~操作方便~系统处理正确,整个系统恢复性能好~连接速度快~以确保系统可使用性好。 另外~还要求系统的可扩展性、可维护性、可移植性良好。
- 5 -
2.3 功能模块设计
软件开发过程中的功能模块设计~主要解决实现该游戏需求的程序模块设计问题。包括如何把该游戏划分成若干个模块、决定各个模块之间的接口、模块之间传递的信息~以及模块结构的设计等。 2.3.1 游戏功能
本系统主要完成以下几方面的功能:
游戏控制功能——包括游戏的开始、暂停、退出
界面布局
其他辅助功能,如游戏帮助~游戏积分~游戏过关等, 2.3.2 总设计模块的划分
游戏总设计模块划分为游戏主要界面模块、游戏控制模块和游戏菜单模块。
2.3.3 游戏主界面模块
游戏主界面模块主要是指游戏的框图~其包括一下内容: 1、游戏界面的边界~即游戏中的墙,
2、游戏中蛇的构成~以及苹果的构成,
3、游戏中障碍物的构成,
4、游戏中分数显示以及关卡显示。
2.3.4 游戏控制模块
,1,游戏开始控制:
我们的程序是使用上键开始游戏~启动游戏后会有一个初始菜单界
- 6 -
面~我们点击“开始游戏”~弹出一句话“请按上键开始游戏”。游戏开始后蛇向下移动~然后由控制上下左右键来控制蛇的移动。 在程序中我们重新建了一个activity来控制游戏的开始~使游戏的开始界面更美观。
,2,游戏暂停控制:
我们是使用center键来控制游戏的暂停的~这是一项人性化的设计~当玩家在游戏过程中突遇紧急情况时可以按center键暂停游戏~等玩家空闲后按center键可以继续游戏。
,3,游戏退出控制:
在游戏的退出上我们的程序使用了多种方式来应对不同的情况~当玩家正在游戏中时~如想退出可以按“1”键~程序会自动跳转到初始菜单界面~在初始菜单界面点击“退出游戏”即可退出游戏。如果玩家在游戏中由于碰到墙或者咬到自己或者碰到障碍物而导致游戏结束的~游戏或自动弹出一个界面~里面有提示是继续游戏还是退出游戏~当点击“取消”时~游戏就会自动跳转到初始菜单~再点击“退出游戏”即可。
2.4 类模块设计
src源码目录:
- 7 -
Snake.java为主界面类,
SnakeView 为贪吃蛇类的视图主要逻辑控制和绘制类, TitleView 为界面的整体视图,
MenuActivity为菜单类~可以跳转到Help类和Snake类, Help为游戏帮助类。
2.5 游戏图形界面的图形显示更新功能
在初始菜单界面~我们的程序设置了三个功能键:“开始游戏”“游戏帮助”“退出游戏”~“开始游戏”是进入游戏的入口~“游戏帮助”是告诉玩家如何玩这个游戏~“退出游戏”是玩家退出游戏的出口。
?3 游戏的基本实现 3.1 游戏界面的实现
1、先声明用来存放绘画图像的X~Y轴的位置的数组: private int[][] mTileGrid;
2、编写存放图片索引用图片的X~Y轴位置,
public void setTile(int tileindex, int x, int y)
- 8 -
{ mTileGrid[x][y] = tileindex; } 3. 把图片素材加入到bitmap中
public void loadTile(int key, Drawable tile)
{
Bitmap bitmap =
Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
tile.setBounds(0, 0, mTileSize, mTileSize);
tile.draw(canvas);
mTileArray[key] = bitmap;
}
4、调用以上的方法以循环的方式位置数组赋值以及图片的索引~
private void updateWalls() {
for (int x = 0; x < mXTileCount; x++) {
setTile(GREEN_STAR, x, 0);
setTile(GREEN_STAR, x, mYTileCount - 1); }
for (int y = 1; y < mYTileCount - 1; y++) {
setTile(GREEN_STAR, 0, y);/设置左边的界线的位置
setTile(GREEN_STAR, mXTileCount - 1, y);/设置右边的界线的位置
}}
5、重写VIEW 类里面的方法。 把界线画出。
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
for (int x = 0; x < mXTileCount; x += 1) {
for (int y = 0; y < mYTileCount; y += 1) {
if (mTileGrid[x][y] > 0) {
- 9 -
canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
mXOffset + x * mTileSize,
mYOffset + y * mTileSize, mPaint);}
同上可见: 整个界面其实就是由图片数组拼直面成的。
到此~则可以实现游戏背景墙。
3.2 游戏整个框架的构建
3.2.1 实现
方案
气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载
游戏的整个框架的构建包括基本的蛇身~苹果的实现~有两种方案: 方案一:使用常用的数组来存储蛇身和苹果的点集的信息。此方案的优点是对数组的操作较为熟悉~实现简单~但是部分操作较为麻烦~有可能出现数组越界~或者浪费太多存储空间。
方案二:使用动态数组ArrayList来存储蛇身和苹果点集的信息。ArrayList可以用来定义为各种不同类型的数组~不仅仅局限于int整型,而且ArrayList为用户编程提供了各种借口~比如插入~删除元素~统计元素个数等~实现较为简单~不会出现数组越界的问题。 结合各种因素的考虑~我们在设计中采用第二种方案。
3.2.2 定义Position方法~用于存储蛇身和苹果的点集坐标 private class Position { //存储每个点的 坐标
public int x;
public int y;
public Position(int xposition, int yposition) {
x = xposition;
y = yposition;
- 10 -
}
public boolean equals(int newx,int newy) {
if (x == newx && y == newy )
{ return true; }
return false;
} }
3.2.3 定义setMode方法~用于表示游戏所处的几种状态:进行~暂停~
public void setMode(int newMode)
{
int oldMode = mMode;
mMode = newMode;
if(newMode == RUNNING && oldMode != RUNNING)
{}
if(newMode == PAUSE){}
if(newMode == LOSE) {}
if(newMode == READY) {}
}
3.2.4 苹果的实现
3.2.4.1 声明:
private ArrayList
mAppleTrail = new ArrayList();
用于存储苹果的坐标位置
3.2.4.2 根据游戏的需要~苹果的位置应该是随机产生的~使用
java.util.Random类中提供的随机数实现苹果坐标的随机。
int newapplex = 2+random.nextInt((mYTileCount-2)-4);
int newappley = 2+random.nextInt((mXTileCount-2)-4);
newapple = new Position(newapplex,newappley);
- 11 -
3.2.4.3 检测苹果坐标是否与蛇的坐标以及墙的左边冲突
设置冲突标志位:boolean flag = false;
int snakelength = mSnakeTrail.size();
for (int index = 0; index < snakelength; index++)
{
if (mSnakeTrail.get(index).equals(newapple.x,newapple.y))
{ flag = true; }
}
墙的冲突检测方法与上同,当产生的新坐标没有问题时~则把新
坐标加入到mAppleTrail中。
3.2.5 蛇的实现
3.2.5.1 声明:
private ArrayList mAppleTrail = new ArrayList();
用于存储苹果的坐标位置
3.2.5.2 蛇的初始化
蛇身的初始化在ininNewGame中实现~直接把最初要呈现给玩家的
蛇的情况定义出来~即添加一定数量的坐标点进入mSnakeTrail中~使得
在最初开始游戏时~有蛇可以进行自由移动。
3.2.5.3 蛇的移动
游戏中是通过触发来改变坐标,+1~-1,的方式来改蛇头的方向~
包括后面的蛇的碰撞检测都要用到蛇头。
获取蛇的头部: Position head = mSnakeTrail.get(0);
- 12 -
蛇的新头部: Position newHead = new Position(2,2);
通过设置整型变量mDirection以及mNextDirection来判断蛇下一步移动方向~然后改变蛇头的坐标~使蛇移动
switch (mDirection) {
case EAST:
{
newHead = new Position(head.x,head.y-1);
break;
}
. ……
}
3.2.5.4 蛇的碰撞检测
蛇在移动时~若碰撞到墙壁或者自己身体~则游戏结束。
蛇的碰壁检测:
if((head.x < 1) || (head.y < 1) || (head.x > mYTileCount-2)
|| (head.y > mXTileCount-2))
{
setMode(LOSE);
return;
}
蛇的自身碰撞的检测:
int wallength = mWallTrail.size();
for ( int wallindex = 0 ; wallindex < wallength; wallindex++)
{
Position c = mWallTrail.get(wallindex);
- 13 -
if (c.equals(newHead.x,newHead.y))
{
setMode(LOSE);
return;
} }
3.2.5.5 蛇吃苹果的实现
蛇所经过的每一个坐标~ 他们都要在苹果所在的
ArrayList mAppleList = new ArrayList(),坐标
集里面集依次判断~若是坐标相同~那个这个苹果就被蛇吃了 。
找苹果的方法:
int applecount = mAppleTrail.size();
int appleindex;
for ( appleindex = 0; appleindex < applecount; appleindex++)
{
Position c = mAppleTrail.get(appleindex);
if (c.equals(newHead.x,newHead.y)) {}
}
3.3 实现键盘响应事件:
键盘主要起操作作用~ 可以控制蛇的行走方向:
public boolean onKeyDown(int keyCode,KeyEvent event)//键盘响应
{
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
if (mDirection != SOUTH)
{
mNextDirection = NORTH;
}
return (true);
- 14 -
}
……..
}
3.4 刷新
只要继承Handler类就可以对消息进行控制~或者处理
class RefreshHandler extends Handler { //响应消息
public void handleMessage(Message msg) {
SnakeView.this.update();// 重要页面
页面 SnakeView.this.invalidate();刷新
}
// 向外提供人工的调用消息的接口,
public void sleep(long delayMillis) {
this.removeMessages(0);//注消消息
// 添加消息,
sendMessageDelayed(obtainMessage(0), delayMillis);
}
3.5 实现页面的切换
程序中从主菜单界面到游戏界面的切换以及从主菜单界面到游戏帮助界面都采用的是活动的切换方法,
使用startActivity(new
Intent(MenuActivity.this,Snake.class)); 实现不同活动之间的切换~即从一个页面跳转到另一个上。
另一种方案也能实现页面的切换就是~通过控制页面上的控件如按
- 15 -
钮的显示~隐藏来达到切换的目的~但是这种方式较为复杂。 3.6 加载游戏
通过ininNewGame方法来初始化新游戏~通过Update方法更新游戏设置。
?4 对游戏界面以及其他方面的改进 4.1游戏背景界面的改进
为贪吃蛇游戏设计了背景~使其更具有观赏新~使玩家赏心悦目。 4.2 添加音效
为游戏添加了音效~使游戏在听觉上给人以耳目一新的感觉,具体实现方法:
通过调用android.media.MediaPlayer类函数~声明对象: MediaPlayer mp=MediaPlayer.create(this.getContext(),R.raw.background);
通过mp.start();
mp.pause();
mp.stop();
来控制游戏不同状态时的音乐状态。
4.3 游戏本身的完善
4.3.1 为游戏设置关卡
根据玩家的得分为游戏设置了关卡~难度逐渐加强~蛇的移动速度逐渐加快。
每一关卡中的障碍物是固定不变的~为简单起见~只设置了五个关卡
- 16 -
通过Obstacle函数来设置关卡的障碍物~其中函数中以当前处于的关卡数作为判断依据。
public void Obstacle()
{
switch(stage){
case 5:
case 4:
case 3:
case 2:
} }
4.3.2 游戏中设置的有三种不同的苹果:普通~加分~和毒苹果,
吃掉普通的苹果加一分;吃掉加分的苹果加两分;吃掉毒苹果减三分并加速
每一种苹果的实现方法都一样~使用ArrayList动态数组
每种苹果都采用随机的方法实现~实现方式基本与蛇找到苹果相同~只是在细节上略有区别
private void Poisonapple(); private void Loveapple(); 4.3.3 设置退出快捷键
在游戏进行中~设置了退出快捷键~可以直接退出游戏~更加方便玩家操作。
具体实现还是依靠键盘响应函数:游戏中是数字“1”键作为退出快捷键
public boolean onKeyDown(int keyCode,KeyEvent event)
- 17 -
if(keyCode == KeyEvent.KEYCODE_1) {
mUpdateFlag = false;
mp.stop();
Intent intent = new Intent(this.getContext(),MenuActivity.class);
this.getContext().startActivity(intent);
}
4.3.4 设置加速
根据实际操作需要~当操控蛇的移动时~若按下方向键不放~则
蛇在该方向上的运行速度就会加快,若松开方向键则恢复原速度。
通过设置整型变量mSpeed和mNSpeed~其中mNSpeed用来保存蛇
在该关卡的移动速度。
通过键盘响应函数public boolean onKeyDown(int keyCode,KeyEvent event) 和public boolean onKeyUp(int keyCode, KeyEvent event)一起来实现加速功能。
4.3.5 提示对话框
在游戏结束后弹出对话框询问玩家的下一步动作~按确定按钮继续
开始新的游戏~按取消退出游戏。
这项功能需要android.content.DialogInterface类的支持~
声明对象:private AlertDialog.Builder showRightorNot ,
弹出对话框的界面:
showRightorNot = new AlertDialog.Builder(this.getContext());
showRightorNot.setIcon(R.drawable.icon); showRightorNot.setTitle("贪吃蛇");
showRightorNot.setPositiveButton("确定", this);
- 18 -
showRightorNot.setNegativeButton("取消", this);
showRightorNot.setMessage("按确定继续,按取消退出游戏").show();
?5 类模块具体设计
5.1 TitleView.java
5.1.1 TitleView.java中的成员变量表
变量 类型 意义 赋值
声明四种类型的小块~mTileArray[] private Bitmap
黄绿红黑
12 protected static final
mTileSize 小块边长 int
mXTileCount protected static int x方向小块个数 mYTileCount; protected static int y方向小块个数 mTileGrid private int[][] 每个小块的数值 mXOffset protected int 横向偏移量 mYOffset; protected int 纵向偏移量
new
paint private Paint
Paint();
5.1.2 TitleView.java成员方法
5.2 SnakeView.java
5.2.1 SnakeView.java中的成员变量表
- 19 -
变量 类型 作用 赋值 TAG public static final String "Snakeview"
Private 游戏继续提示
showRightorNot
AlertDialog.Builder
mDirection private int 控制蛇的移动方向 SOUTH
控制蛇的下一个移动方
mNextDirection private int SOUTH
向
NORTH private static final int 控制蛇向上移动 1 SOUTH private static final int 控制蛇向下移动 2 EAST private static final int 控制蛇向右移动 3 WEST private static final int 控制蛇向左移动 4 READY public static final int 1 RUNNING public static final int 控制游戏开始 2 PAUSE public static final int 控制游戏暂停 3 LOSE public static final int 控制游戏结束 4 textView1; private TextView textView2; private TextView textView3; private TextView mCenterPressed private boolean false mUpdateFlag private boolean false mMode public int READY stage private int
记录
混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载
通关等级 1 mScore private int 计分 0 mSpeed private int 刷新界面时间变量 600 mNSpeed private int 刷新界面时间变量 mSpeed
刷新界面处理变量 new
re private RefreshHandler
RefreshHandler(); random private static final Random new Random(); mRecord private int [] =new int[10]
- 20 -
5.2.2 SnakeView.java成员方法
5.3 MenuActivity.Java
5.3.1 MenuActivity.Java成员变量
public static final String TAG TAG
private AlertDialog.Builder showRightorNot showRightorNot
5.4 Help.Java
5.4.1 Help.Java成员变量
onCreate protected void onCreate
?6 系统测试
保存原程序~启动模拟机~选择java application~运行结果如下:
- 21 -
- 22 -
- 23 -
进行游戏测试~在可使用性方面~操作方便~系统处理正确,整个系统恢复性能好~连接速度快~系统可使用性好。
?7
心得
信息技术培训心得 下载关于七一讲话心得体会关于国企改革心得体会关于使用希沃白板的心得体会国培计划培训心得体会
体会
雷永普——总的来说~这次参与设计贪吃蛇游戏收获很大~达到了实习锻炼的目的。本次实习培养了团队合作精神~自己的Java语言设计能力得到了提高~体验了软件开发过程~培养了项目开发的分析能力和程序设计能力。
首先~从玩游戏到设计游戏的角色转化~体验软件开发过程~培养
- 24 -
了项目开发的分析能力。
其次~培养了团队合作精神。整个程序开发过程中~小组成员团结合作~努力思考~认真讨论。可以说我们的程序开发小组~凝聚了友情~感受了温情~创造了激情。
最后~最直接的收获就是在Android平台上用JAVA语言开发程序的能力。这是毕业找工作的一大资本~为从学校的理论学习过渡到工作中的实际操作奠定了基础。
全巍——这3个星期的嵌入式系统的实习对我收获很大。在对Android平台下的程序开发有了很深刻的了解。我们主要完成“贪吃蛇”游戏的开发工作。在起初对所要完成的工作很没有信心~因为之前并没有做过类似的项目。这个游戏看似简单~实际操作起来却不是想象的那么简单。慢慢的在老师的耐心指导和同学的帮助下一步步地熟悉Android平台下的开发工作~“贪吃蛇”也开始成熟起来。最后经过小组成员的共同努力~完整的游戏成形。总体来说这次实习完成了既定的目标~对于今后的工作打下了牢固的基础~积累了丰富的经验。对工作有了初步的认识~相信我今后会在这个领域有所发展。
何俊涛——总的来说~在这次实习过程中让我认识到了android系统的简便之处~在当今社会编程人才随处可见的形势下~什么样的系统才能更受欢迎~android恰好做到了这点。
在这次实习中~我们通过做贪吃蛇这个游戏体会到了编程的快乐~也体会到了那种做成功的喜悦~当我们越到问题时~能够互相合作去解决问题~不仅将程序问题成功解除~也加深了印象~同时在自己解决不了的
- 25 -
问题时~通过咨询老师也能让我们把问题解除~同时也加强了我们思考
的深度。
总之~这次实习让我学到了很多有用的东西~也相信在我今后的学习生
活中会发挥很大的作用。
参考文献
- 26 -
附录 “贪吃蛇游戏”程序部分源代码
package com.Snake.android; showRightorNot ;
private int mDirection = SOUTH; import java.util.ArrayList; private int mNextDirection = SOUTH; import java.util.Random;
import android.app.AlertDialog; //设置方向
import android.content.Context; private static final int NORTH = 1; import android.content.DialogInterface; private static final int SOUTH = 2; import android.content.Intent; private static final int EAST = 3; import android.content.res.Resources; private static final int WEST = 4; import android.media.MediaPlayer;
import android.os.Handler; public static final int READY = 1; import android.os.Message; public static final int RUNNING = 2; import android.util.AttributeSet; public static final int PAUSE = 3; import android.view.KeyEvent; public static final int LOSE = 4; import android.view.View;
import android.widget.TextView; private TextView textView1;
private TextView textView2;
/** private TextView textView3;
* @author Administrator
* private boolean mCenterPressed = false;
*/ private boolean mUpdateFlag =false;//是否
public class SnakeView extends TileView 更新的标志量
implements
android.content.DialogInterface.OnClickListener public int mMode = READY; {
public static final String TAG = private int mScore = 0; "Snakeview"; private int mSpeed = 600;
private AlertDialog.Builder private int stage = 1;
- 27 -
private int mNSpeed = mSpeed; * @param context
* @param attrs
//刷新界面处理器 */
private RefreshHandler re = new class RefreshHandler extends Handler RefreshHandler(); { //每600ms刷新一次
/**
//为创建苹果坐标使用随机对象 * 响应消息
private static final Random random = new */
Random(); @Override
public void
//用于存储贪吃蛇中,苹果和蛇的点阵handleMessage(Message msg) { 的坐标的信息的集合 update();
private ArrayList mSnakeTrail = invalidate();//消失 重新调
new ArrayList(); 用on draw
private ArrayList mAppleTrail = }
new ArrayList(); /**
private ArrayList mWallTrail = * 向外提供人工的调用消息的
new ArrayList(); 接口
private ArrayList mPoisonApple * @param delayMillis = new ArrayList(); */
private ArrayList mLoveApple = public void sleep(long delayMillis)
new ArrayList(); { //隔600ms重新调用这个函数
this.removeMessages(0);
MediaPlayer sendMessageDelayed(obtainMessage(0), mp=MediaPlayer.create(this.getContext(),R.raw.bdelayMillis);
ackground); }
}
//相当于数组 大小可变
/** public SnakeView(Context context,
- 28 -
AttributeSet attrs) { yposition) {
x = xposition; super(context, attrs);
setFocusable(true); y = yposition;
ininSnakeView(); }
}
public boolean equals(int newx,int
public void ininSnakeView()//初始化界面 newy) {
{ if (x == newx && y == newy )
{
Resources return true;
r = this.getContext().getResources(); }
resetTiles(6); return false;
} }
loadTile(1, r.getDrawable(R.drawable.redstar));
loadTile(2, r.getDrawable(R.drawable.yellowstar)); public void ininNewGame() loadTile(3, r.getDrawable(R.drawable.greenstar)); {
mSnakeTrail.clear();
loadTile(4,r.getDrawable(R.drawable.purplewstar) mAppleTrail.clear(); ); mScore=0;
stage=1;
loadTile(5,r.getDrawable(R.drawable.favourite)); mSpeed=600;
}
//初始化蛇的位置
private class Position { //存储每个点 mSnakeTrail.add(0,new Position(20,20)); 的 坐标 mSnakeTrail.add(1,new Position(19,20));
public int x; mSnakeTrail.add(2,new Position(18,20));
public int y;
//初始化苹果的位置
public Position(int xposition, int Apple();
- 29 -
Poisonapple(); return (true);
Loveapple();
}
mDirection = NORTH; if(mDirection != NORTH)
mNextDirection = NORTH; {
mNextDirection = SOUTH;
} }
return (true);
public boolean onKeyDown(int }
if (keyCode == keyCode,KeyEvent event)//键盘响应
{ KeyEvent.KEYCODE_DPAD_DOWN) {
mSpeed = 200; if (mDirection != SOUTH) {
if(keyCode == mNextDirection = NORTH; KeyEvent.KEYCODE_DPAD_UP) }
{ return (true);
if(mMode == READY || }
mMode == LOSE)
{ if (keyCode ==
ininNewGame(); KeyEvent.KEYCODE_DPAD_LEFT) {
if (mDirection != WEST) {
setMode(RUNNING); mNextDirection = EAST;
update(); }
mp.start(); return (true);
return (true); }
}
if(mMode == PAUSE) if (keyCode ==
{ KeyEvent.KEYCODE_DPAD_RIGHT) {
setMode(RUNNING); if (mDirection != EAST) {
mp.start(); mNextDirection = WEST;
- 30 -
} return
return (true); super.onKeyDown(keyCode, event);
}
}
if(keyCode ==
KeyEvent.KEYCODE_DPAD_CENTER) @Override
{ public boolean onKeyUp(int keyCode,
if(mCenterPressed == false) KeyEvent event)
{ {
setMode(PAUSE); mSpeed = mNSpeed;
mp.pause(); if(keyCode ==
} KeyEvent.KEYCODE_DPAD_UP)
else {
{ if(mDirection != NORTH)
setMode(RUNNING); {
mp.start(); mNextDirection = SOUTH;
} }
mCenterPressed = !mCenterPressed; return (true);
} }
if (keyCode ==
KeyEvent.KEYCODE_DPAD_DOWN) { if(keyCode == KeyEvent.KEYCODE_1)
if (mDirection != SOUTH) { {
mUpdateFlag = false; mNextDirection = NORTH;
mp.stop(); }
Intent intent = new return (true); Intent(this.getContext(),MenuActivity.class); }
this.getContext().startActivity(intent); if (keyCode ==
} KeyEvent.KEYCODE_DPAD_LEFT) {
- 31 -
if (mDirection != WEST) { textView1.setVisibility(View.INVISIBLE);
update(); mNextDirection = EAST;
} return;
return (true); }
} if(newMode == PAUSE)
{
if (keyCode == str = "按暂停键继续开始"; KeyEvent.KEYCODE_DPAD_RIGHT) { mUpdateFlag = false;
if (mDirection != EAST) { }
mNextDirection = WEST; if(newMode == LOSE)
} {
return (true); str = "游戏结束,按上键重新开始";
} mUpdateFlag = false;
// TODO Auto-generated method
stub showRightorNot = new
return super.onKeyUp(keyCode, event); AlertDialog.Builder(this.getContext());
}
showRightorNot.setIcon(R.drawable.icon);
public void setMode(int newMode) showRightorNot.setTitle("贪吃蛇");
{
int oldMode = mMode; showRightorNot.setPositiveButton("确定",
mMode = newMode; this);
String str = "";
if(newMode == RUNNING && showRightorNot.setNegativeButton("取消", oldMode != RUNNING) this);
{
invalidate(); showRightorNot.setMessage("按确定继续,
mUpdateFlag =true; 按取消退出游戏").show();
mp.stop();
- 32 -
mp.prepareAsync(); 置底部界
} }
if(newMode == READY) for (int y = 1; y < mXTileCount - 1;
{ y++)
mp.start(); {
str = "按上键开始游戏"; setTile(3, 0,y);
} setTile(3,mYTileCount-1,y);
textView1.setText(str); }
}
textView1.setVisibility(View.VISIBLE);
} public void updateSnake()
{
public void update() boolean Snakegrow = false;
{ //获取蛇的头部
if(mUpdateFlag) Position head = mSnakeTrail.get(0);
{ //蛇的新头部
clearTiles(); Position newHead = new Position(2,2);
updateWalls(); //根据当前的为方向设置坐标的信息
updateSnake(); mDirection = mNextDirection;
updateApple();
re.sleep(mSpeed); switch (mDirection) {
} case EAST:
} {
public void updateWalls() newHead = new Position(head.x,head.y-1);
{ break;
for (int x = 0; x < mYTileCount; x++) }
{ case WEST:
setTile(3, x,0);//设置顶部界限 {
setTile(3, x,mXTileCount-1);//设 newHead = new Position(head.x,head.y+1);
- 33 -
break; if (c.equals(newHead.x,newHead.y))
} {
case NORTH: setMode(LOSE);
{ return;
newHead = new Position(head.x+1,head.y); }
break; }
} //蛇与障碍物的冲撞检测
case SOUTH: int wallength = mWallTrail.size();
{ for ( int wallindex = 0 ; wallindex < newHead = new Position(head.x-1,head.y); wallength; wallindex++)、
break; {
} } Position c = mWallTrail.get(wallindex);
if (c.equals(newHead.x,newHead.y)) //蛇碰壁检测 {
if((newHead.x < 1) || setMode(LOSE);
(newHead.y < 1) || return;
(newHead.x > mYTileCount-2) || }}
(newHead.y > mXTileCount-2))
{
setMode(LOSE); //找苹果
return; int applecount = mAppleTrail.size();
} String str1 = " 分数:";
int appleindex;
//蛇自身冲撞检测 for ( appleindex = 0; appleindex < int snakelength = mSnakeTrail.size(); applecount; appleindex++)
for (int snakeindex = 0; snakeindex < snakelength; {
snakeindex++) Position c = mAppleTrail.get(appleindex);
{ if (c.equals(newHead.x,newHead.y)) //找
Position c = mSnakeTrail.get(snakeindex); 到苹果
- 34 -
{ 苹果
mAppleTrail.remove(c); {
Apple(); mPoisonApple.remove(c);
mScore++; mScore = mScore - 3;
if(mScore%3==0) mSpeed *= 0.8;
{ } }
mSpeed *=0.95; int lovecount = mLoveApple.size();
mNSpeed = mSpeed; for (int index = 0; index < lovecount; index++)
stage++; {
Apple(); Position c = mLoveApple.get(index);
Poisonapple(); if (c.equals(newHead.x,newHead.y)) //
Loveapple(); 找到苹果
} {
Snakegrow = true; mLoveApple.remove(c);
} mScore = mScore + 5;
textView2.setText(str1+ mScore mSpeed /= 0.8;
+ " 按数字键“1”退出游戏"); } }
String str2="第 " + stage + " 关";
textView3.setText(str2); Obstacle();
} //将蛇头的位置信息放在第一个的对象
中方取值
//毒苹果处理方法 mSnakeTrail.add(0, newHead);
int posioncount = mPoisonApple.size();
if(!Snakegrow)
for (int index = 0; index < posioncount; {
index++) mSnakeTrail.remove(mSnakeTrail.size() - 1); } {
Position c = mPoisonApple.get(index); for (Position c : mSnakeTrail)
if (c.equals(newHead.x,newHead.y)) //找到 {
- 35 -
setTile(2, c.x, c.y); {
flag = true; } }
} }
//随即产生苹果
private void Apple() int wallength = mWallTrail.size();
{ for (int index = 0; index < wallength;
Position newapple = null; index++)
boolean collision =false; {
if
while( !collision ) (mWallTrail.get(index).equals(newapple.x,newappl
{ e.y))
//为随即苹果添加一个随即位置 {
int newapplex = flag = true; 2+random.nextInt((mYTileCount-2)-4); } }
int newappley = collision = !flag; 2+random.nextInt((mXTileCount-2)-4); }
//把apple的坐标添加到appleTrail中
newapple = new mAppleTrail.add(newapple); Position(newapplex,newappley); }
//检查苹果的坐标是否与蛇的冲突 private void Poisonapple()
boolean flag = false;//冲突标志位 {
int snakelength = mSnakeTrail.size(); mPoisonApple.clear();
for (int index = 0; index < snakelength;
index++) Position newapoison = null;
{ boolean collision1 =false;
if boolean collision2 =false; (mSnakeTrail.get(index).equals(newapple.x,newap
ple.y)) while(!collision1 && !collision2 )
- 36 -
{ (mWallTrail.get(index).equals(newapoison.x,newa
poison.y)) //为随即苹果添加一个随即位置
int newapoisonx = {
2+random.nextInt((mYTileCount-2)-4); flagw = true;
int newapoisony = }}
2+random.nextInt((mXTileCount-2)-4); collision2 = !flagw;
}
//把apple的坐标添加到appleTrail中 newapoison = new
Position(newapoisonx,newapoisony); mPoisonApple.add(newapoison);
}
//检查苹果的坐标是否与蛇的冲突
private void Loveapple()
boolean flags = false;//冲突标志位 {
boolean flagw = false; mLoveApple.clear();
int snakelength = mSnakeTrail.size();
for (int index = 0; index < Position newalove = null; snakelength; index++) boolean collision1 =false;
{ boolean collision2 =false;
if
(mSnakeTrail.get(index).equals(newapoison.x,new while(!collision1 && !collision2 )
{ apoison.y))
{ //为随即苹果添加一个随即位置
flags = true; int newalovex =
} } 2+random.nextInt((mYTileCount-2)-4);
collision1 = !flags; int newalovey =
int wallength = mWallTrail.size(); 2+random.nextInt((mXTileCount-2)-4);
for (int index = 0; index < wallength; index++)
{ newalove = new
if Position(newalovex,newalovey);
- 37 -
//检查苹果的坐标是否与蛇的冲突 }
//把apple的坐标添加到appleTrail
boolean flags = false;//冲突标志位 中
boolean flagw = false; mLoveApple.add(newalove);
int snakelength = mSnakeTrail.size();
for (int index = 0; index < }
snakelength; index++)
public void updateApple() {
if {
for(Position c: mAppleTrail) (mSnakeTrail.get(index).equals(newalove.x,newalo
ve.y)) {
{ setTile(1,c.x,c.y);
flags = true; }
} }
}
public void Obstacle() collision1 = !flags;
int wallength = mWallTrail.size(); {
for (int index = 0; index < wallength; switch(stage){
index++) case 5:
{ {
if mWallTrail.add(0,new Position(32,7)); (mWallTrail.get(index).equals(newalove.x,newalov mWallTrail.add(1,new Position(31,7)); e.y)) mWallTrail.add(2,new Position(30,7));
{ mWallTrail.add(3,new Position(29,7));
flagw = true; mWallTrail.add(4,new Position(28,7));
} mWallTrail.add(5,new Position(27,7));
} mWallTrail.add(6,new Position(26,7));
collision2 = !flagw; mWallTrail.add(7,new Position(25,7));
- 38 -
for(Position c:mWallTrail) mWallTrail.add(0,new Position(21,22));
mWallTrail.add(1,new Position(21,21)); setTile(3,c.x,c.y);
mWallTrail.add(2,new Position(21,20));
for(Position c:mPoisonApple) mWallTrail.add(3,new Position(21,19));
setTile(4,c.x,c.y); mWallTrail.add(4,new Position(21,18));
mWallTrail.add(5,new Position(21,17));
for(Position c:mLoveApple)
setTile(5,c.x,c.y); for(Position c:mWallTrail)
} setTile(3,c.x,c.y);
case 4:
{ for(Position c:mPoisonApple)
//mWallTrail.clear(); setTile(4,c.x,c.y);
mWallTrail.add(0,new Position(1,18));
mWallTrail.add(1,new Position(2,18)); for(Position c:mLoveApple)
mWallTrail.add(2,new Position(3,18)); setTile(5,c.x,c.y);
mWallTrail.add(3,new Position(4,18)); }
mWallTrail.add(4,new Position(5,18)); case 2:
mWallTrail.add(5,new Position(6,18)); {
mWallTrail.add(0,new Position(7,1));
for(Position c:mWallTrail) mWallTrail.add(1,new Position(7,2));
setTile(3,c.x,c.y); mWallTrail.add(2,new Position(7,3));
mWallTrail.add(3,new Position(7,4));
for(Position c:mPoisonApple) mWallTrail.add(4,new Position(7,5));
setTile(4,c.x,c.y); mWallTrail.add(5,new Position(7,6));
}
case 3: for(Position c:mWallTrail)
{ setTile(3,c.x,c.y);
//mWallTrail.clear();
- 39 -
for(Position c:mPoisonApple) }
setTile(4,c.x,c.y);
for(Position c:mLoveApple) @Override
setTile(5,c.x,c.y); public void onClick(DialogInterface dialog,
}} } int which) {
// TODO Auto-generated method
public void Text(int n,TextView textView1) stub
{ if(which
switch (n) { == DialogInterface.BUTTON_POSITIVE)
case 1: {
{ //dialog.cancel();
this.textView1 = textView1; //ininNewGame();
break; setMode(READY);
} mp.start();
case 2: mUpdateFlag = false;
{
this.textView2= textView1; }
break; if(which
} == DialogInterface.BUTTON_NEGATIVE)
case 3: {
{ ((Snake)(this.getContext())).finish();
this.textView3= textView1; mp.stop();
break; }
} }
}
}
- 40 -