JME课程设计方案报告模板.docx
《JME课程设计方案报告模板.docx》由会员分享,可在线阅读,更多相关《JME课程设计方案报告模板.docx(44页珍藏版)》请在冰豆网上搜索。
JME课程设计方案报告模板
封面
作者:
PanHongliang
仅供个人学习
J2ME课程设计报告
J2ME手机贪吃蛇
专业:
软件工程
班级:
2
组号:
指导教师:
郭俊
二011年9月14日
摘要
1)介绍工程意义背景。
本文给出了一个基于MIDP2.1的贪吃蛇游戏的设计方案,并给出全部实现源代码。
利用J2ME语言编程的思想来完成系统的设计,然后编写出程序设计代码进行界面设计,实现友好的界面交互,具有清晰的程序流程图,最后编程实现了全过程。
2)本文作的主要工作:
(1),贪吃蛇是个老幼皆宜的小游戏。
(2),它实现由3块正方形的方块组成的一条蛇和正方形小块组成的食物,然后有小蛇按方向去吃食物。
(3),计算机使食物随机出现,根据计算机控制它在一定的时间不停的出现,玩家可以让小蛇上、下、左、右的进行吃食物。
3)本文组织
第一章:
首先,主要有主程序GameManager来连接实现全界面功能
第二章:
Navigator.java:
该文件是开始界面。
MainScreen.java:
该文件负责创建主界面。
MessageScreen.java:
该文件是胜利后和最高分文件。
第三章:
NewGame.java:
该文件是整个游戏的核心文件。
目录
(空两行)
1.前言1
2.需求分析1
3.概要设计(特殊功能)1
4.详细设计1
5.源代码及可执行程序1
6.特殊问题解决方法2
6.1.问题12
6.2.问题22
7.使用说明及测试结果2
8.结论2
参考书目3
1.前言
J2ME语言继承了JAVA语言易学易用的特点,特别适合于初学者学系统编程。
随着21世纪信息社会的到来,计算机在人们的工作和生活中的深入,要求我们越来越多地与计算机打交道,为了使用户在繁忙的日程工作中得到放松,于是出现了各种各样的休闲软件,如聊天工具,游戏等等。
通过这学期来J2ME课程的学习,我初步掌握了J2ME语言的最基本的知识,于是老师的指导下动手用J2ME编写俄贪吃蛇游戏。
游戏是用来给大家娱乐的,所以要能在使用的过程中给大家带来快乐,消除大家的疲劳,激发大家的娱乐激情。
从本游戏的基本玩法出发,主要就是贪吃蛇是个老幼皆宜的小游戏。
它实现由3块正方形的方块组成的一条蛇和正方形小块组成的食物,然后有小蛇按方向去吃食物。
计算机使食物随机出现,根据计算机控制它在一定的时间不停的出现,玩家可以让小蛇上、下、左、右的进行吃食物。
2.需求分析
1、开始:
开始游戏
2、继续:
对游戏暂停之后可以继续游戏
3、帮助:
能帮助你更好的过关
4、关于:
关于软件的制作人员
5、退出:
关闭游戏
3.概要设计(特殊功能)
对你要实现的系统的总体设计,包括:
你系统的系统结构和体系框架;工程框图及本工作在工程中的地位;系统中自己完成模块部分的所有对象的概要设计(如对象的主要职责和对象之间的相互关系);主要的控制流程;重要的功能流程设计及方案选择等内容。
首先游戏的功能最主要就是能够实现贪吃蛇的游戏功能。
在游戏的过程中可以暂停返回到主菜单界面,可以返回继续原来的游戏或者开始新游戏。
原来计划使用记录管理系统(RMS)将游戏状态保存下来,这样退出程序后也可以继续原来的游戏,但是实际中发现需要保存的数据量太大,保存时间过长(大约4—5秒),最后还是决定用Boolean变量控制游戏状态。
本游戏的操作流程非常简单,用户启动MIDlet启动后,即进入游戏主画面,屏幕开始显示为欢迎画面。
用户按下[开始]按钮后,就可以开始玩游戏了,当用户想暂停时,再次按一下[开始]按钮,游戏就暂停了,在暂停的情况下再按[开始]按钮,游戏继续运行。
任何时候按[退出]按钮,游戏MIDlet都会终止。
本程序共有5个java源文件:
GameManager.java:
该文件是游戏画布。
Navigator.java:
该文件是开始界面。
MainScreen.java:
该文件负责创建主界面。
MessageScreen.java:
该文件是胜利后和最高分文件。
NewGame.java:
该文件是整个游戏的核心文件。
4.详细设计
游戏包括几个部分,由于数码相机近距离照不清手机上的字,这里只有用模拟
器的截图了:
游戏的起点是GameManage类,继承自MIDlet类,实现游戏的开始和退出。
主菜单界面提供进入其他功能的选项,代码在MainScreen.java文件中,继承
自List类。
选择“帮助”和“关于”菜单显示文字信息,由MessageScreen.java实现,继
承自Form类。
在Navigator.java中实现对游戏流程的控制,处理游戏界面的切换和显示。
游戏界面屏幕大小设置的非常好,所以效果在模拟器上看起来右边已经
出了屏幕:
游戏界面就在NewGame.java中实现。
由于偷懒,这里把算法的处理和游戏的
动画显示都放在这个文件里面,太不了。
游戏界面切换
如图所示,游戏从GameManage开始启动,进入Navigator控制显示主菜单界
面,其他界面都由从菜单界面进入,除了当游戏胜利后可以从游戏界面跳至结束
信息界面。
5.源代码及可执行程序
要求提交主要模块的全部源代码(以小组方式统一提交);源代码应该满足小组规定的源代码规范,包括命名规范,缩进对齐规范,注释规范等等。
源代码的注释应丰富并且有实用。
同时要求编译生成.class文件,以package的方法发布。
使得在检查程序时可以方便的运行。
报告中只对需要说明的极少部分关键代码进行阐述。
1、GameManager
游戏启动后,直接进入主菜单界面,原来设计了一个boolean变量isInitialization
用来在外界原因中断游戏(如来电话)后返回时使用,不过现在没有考虑这种情况,等以后有时间再增加。
publicvoidstartApp(){
if(isInitialization){
Navigator.current=Navigator.MAIN_SCREEN。
Navigator.showScreen(null)。
isInitialization=false。
}
}
2、MainScreen
显示主菜单,通过选择菜单转入其他页面。
这里使用Navigator类的静态boolean型变量isNewGame判断是否产生继续菜
单:
privatevoidgetGameMenu(){
append("开始",null)。
if(!
Navigator.isNewGame){
append("继续",null)。
}
append("帮助",null)。
append("关于",null)。
append("离开",null)。
}
在命令动作方法中通过判断选择菜单的名称,使用Navigator类的
changeScreen()方法转换页面。
Stringcmd=getString(getSelectedIndex())。
Navigator.changeScreen(cmd)。
3、MessageScreen
由于要根据不同情况显示不同信息,需要传入一个参数构造MessageScreen类
的实例,所以构造方法如下:
publicMessageScreen(StringmessageName){
super(Navigator.softTitle)。
back=newCommand("返回",Command.BACK,1)。
message=initStringItem(messageName)。
this.append(message)。
this.addCommand(back)。
this.setCommandListener(this)。
}
在initStringItem()产生不同页面,如果是完成游戏后显示的信息,则将
Navigator类的变量isNewGame置为true:
privateStringIteminitStringItem(Strings){
if(s.equals("胜利")){
Navigator.isNewGame=true。
returnnewStringItem("--胜利宣言--","………………………………")。
}
elseif(s.equals("帮助")){
Stringtemp="…………………………………………"。
returnnewStringItem("--帮助--",temp)。
}
elseif(s.equals("关于")){
Stringtemp="……………………………………"。
returnnewStringItem("--关于游戏--",temp)。
}
else{
returnnewStringItem("error","\nnoinformation!
")。
}
}
4、Navigator
这个类是整个游戏控制的核心,保证了游戏流程进行的正确。
编写完成显示界
面和改变界面功能的两个方法showScreen()和changeScreen()。
changeScreen()根据当前页面变量current做出相应的操作。
即在手机上,即使
不同页面触发相同事件,也会引起不同的操作。
这里一般是根据按下命令键的字
符串区分不同操作。
publicstaticvoidchangeScreen(Stringcmd){
switch(current){
caseMAIN_SCREEN:
if(cmd.equals("开始")){
Navigator.isNewGame=true。
current=GAME_SCREEN。
showScreen(null)。
}
elseif(cmd.equals("继续")){
Navigator.isNewGame=false。
current=GAME_SCREEN。
showScreen(null)。
}
elseif(cmd.equals("帮助")){
current=MESSAGE_SCREEN。
showScreen("帮助")。
}
elseif(cmd.equals("关于")){
current=MESSAGE_SCREEN。
showScreen("关于")。
}
elseif(cmd.equals("离开")){
showScreen("离开")。
}
break。
caseGAME_SCREEN:
if(cmd.equals("返回")){
current=MAIN_SCREEN。
showScreen(null)。
}
elseif(cmd.equals("胜利")){
current=MESSAGE_SCREEN。
showScreen("胜利")。
}
break。
caseMESSAGE_SCREEN:
if(cmd.equals("返回")){
current=MAIN_SCREEN。
showScreen(null)。
}
break。
}
}
showScreen()根据当前页面变量current的不同值显示相应页面。
与
changeScreen()相同的处理方法,在不同current时,根据传入的字符串参数做出不
同处理。
publicstaticvoidshowScreen(Objectobj){
switch(current){
caseMAIN_SCREEN:
if(obj==null){
display.setCurrent(MainScreen.getInstance())。
}
elseif(((String)obj).equals("离开")){
GameManager.instance.isSafeQuit=true。
GameManager.quitApp()。
}
break。
caseGAME_SCREEN:
display.setCurrent(NewGame.getInstance())。
break。
caseMESSAGE_SCREEN:
display.setCurrent(newMessageScreen((String)obj))。
break。
}
}
5、Coordinates
这个类用来产生随机的x、y坐标数,产生的是在一个固定范围内的非零值。
如产生0和行数之间的随机非零整数:
temp=random.nextInt()。
x=java.lang.Math.abs((temp)%row)。
6、Block
游戏界面由多个小方格组成,单独编了一个Block类,每一个小方格都是这个
类的一个实例。
direction保存当前方格的前进方向,isRandom区别当前方块是蛇身的一部分还
是随机产生的方块,status区别当前方块是背景还是蛇身。
7、NewGame
这里实现游戏功能,包括产生新游戏页面、返回旧游戏页面、游戏算法的实现、
屏幕的显示刷新等。
如果更面向对象化一些,应该把算法的部分另外编写一个类
来实现,但是事先没有规划,想一些写一些,等写好后也懒得改了。
正所谓:
偷
懒我所欲也,OO亦我所欲也,两者不可得兼,舍OO而取偷懒者也。
舍弃面向对象的结果就是一个字——繁!
从图上就可以看出明显这个类要复杂
的多。
为了防止程序正在处理绘图的时候无法相应其他事件(如按键盘),这个类
使用线程来解决这个问题。
getInstance()处理显示新游戏还是原来的游戏:
synchronizedpublicstaticDisplayablegetInstance(){
if(instance==null){
Navigator.isNewGame=false。
instance=newNewGame()。
}
elseif(Navigator.isNewGame){Navigator.isNewGame=false。
instance=newNewGame()。
}
returninstance。
}
对键盘事件的处理:
protectedvoidkeyPressed(intkeycode){
if(isRunning){
switch(keycode){
caseKEY_NUM2:
//数字键2
case-1:
//导航键↑
if(headX-1<0){//出界
break。
}
elseif(
blockStatus[headX-1][headY].direction==DIRECTION_DOWN&&bl
ockStatus[headX-1][headY].status==true){//蛇头移动方向是向后,即原
来蛇头的位置
break。
}
else{
blockStatus[headX][headY].direction=DIRECTION_UP。
headDirection=DIRECTION_UP。
break。
}
}
}
}
在paint()中调用paintBlocks()绘制方块,根据方块的status值不同,分别用两
种颜色区分背景和蛇身:
if(!
blockStatus[i][j].status){
g.setColor(COLOR_BACKGROUND)。
g.fillRect(MARGIN_LEFT+(BLOCK_LENGTH+1)*j,
MARGIN_TOP+(BLOCK_LENGTH+1)*i,
BLOCK_LENGTH,BLOCK_LENGTH)。
}
elseif(blockStatus[i][j].status){
g.setColor(COLOR_SNAKE)。
g.fillRect(MARGIN_LEFT+(BLOCK_LENGTH+1)*j,
MARGIN_TOP+(BLOCK_LENGTH+1)*i,
BLOCK_LENGTH,BLOCK_LENGTH)。
}
线程的run()方法中,进行程序各个功能的调度:
while(isRunning){
moveSnakeHead()。
if(snakeLength>=BLOCK_ROW_NUM*BLOCK_COL_NUM){
isRunning=false。
Navigator.changeScreen("胜利")。
break。
}
//出界或蛇头与蛇身交叉
elseif(isOut||isCross){
isRunning=false。
Navigator.isNewGame=true。
initialization()。
Navigator.changeScreen("返回")。
}
else{
moveSnakeTail()。
if(!
isHaveBlock){//产生一个新的随机方格
showRandomBlock()。
isHaveBlock=true。
}
repaint()。
//刷新屏幕
try{
Thread.sleep(sleepTime)。
}
catch(Exceptionex){}
}
}
showRandomBlock()产生随机方格,方格的位置应该避开蛇身的坐标:
while(flag){
Coordinatescod=newCoordinates(BLOCK_ROW_NUM,
BLOCK_COL_NUM)。
x=cod.x。
y=cod.y。
if(!
blockStatus[x][y].status){
blockStatus[x][y].status=true。
blockStatus[x][y].isRandom=true。
flag=false。
}
else{
blockStatus[tailX+1][tailY].direction=DIRECTION_NONE。
}
}
moveSnakeHead()和moveSnakeTail()比较复杂,简单说就是moveSnakeTail()
根据按键的值将相应方向的方格蛇值为蛇头;moveSnakeHead()将前一个蛇身方格设置为蛇尾,同时清除当前蛇尾方格的状态。
这样,动态的现实就好像整个的蛇
向前移动了一格。
这里需要注意的是:
1)根据蛇头坐标计算是否出界;
2)蛇头碰到非背景的方格,需要判断是随机方格还是碰到了蛇身。
如果是随
机方格,就将这个方格设置为蛇头;如果是蛇身则游戏结束;
3)蛇头中保存的始终是上一次按键按下的方向值,新按键按下,设置新的蛇
头,这样,蛇身的每一个方格中的方向都是它前一个蛇身方格的方向,即
移动的前进方向;
4)移动蛇尾时,如果这一次的移动中蛇头碰到随机方格,则蛇尾不移动;移
动蛇尾后将原蛇尾的方块的方向属性设置为无方向。
源代码:
1、
packagegreedsanke。
importjavax.microedition.midlet.*。
importjavax.microedition.lcdui.*。
publicclassGameManagerextendsMIDlet{
publicstaticGameManagerinstance。
privatebooleanisInitialization。
publicstaticbooleanisSafeQuit。
/**Constructor*/
publicGameManager(){
instance=this。
isInitialization=true。
isSafeQuit=true。
Navigator.display=Display.getDisplay(this)。
//Navigator.midlet=instance。
}
/**Mainmethod*/
publicvoidstartApp(){
if(isInitialization){
Navigator.current=Navigator.MAIN_SCREEN。
Navigator.showScreen(null)。
isInitialization=false。
}
}
/**HandlepausingtheMIDlet*/
publicvoidpauseApp(){
}
/**HandledestroyingtheMIDlet*/
publicvoiddestroyApp(booleanunconditional)throwsMIDletStateChangeException{
if(unconditional==false){
thrownewMIDletStateChangeException()。
}
}
/**QuittheMIDlet*/
publicstaticvoidquitApp(){
//J2ME编写贪吃蛇游戏
//17
try{
instance.destroyApp(isSafeQuit)。
instance.notifyDestroyed()。
instance=null。
}
catch(MIDletStateChangeExceptionex){
//doworkofendmidlet
//---------------------------
//---------------------------
isSafeQuit=true。
}
}
}
2、
packagegreedsanke。
importjavax.microedition.lcdui.*。
importjavax.microedition.rms.*。
publicclassMainScreenextendsListimplementsCommandListener{
privatestaticDisplayableinstance。
privateMainScreen(){
super(Navigator.softTitle,IMPLICIT)。
getGameMenu()。
setCommandListener(this)。
}
privatevoidgetGameMenu(){
append("开始",null)。
if(!
Navigator.isNewGame){
append("继续",null)。
}
append("最高分",null)。
append("帮助",null)。
append("关于",null)。
append("离开",null)。
}
synchronizedpublicstaticDisplayablegetInstance(){
instance=newMainScreen()。
returninstance。
}
publicv