五子棋游戏总体设计与实现.docx
《五子棋游戏总体设计与实现.docx》由会员分享,可在线阅读,更多相关《五子棋游戏总体设计与实现.docx(17页珍藏版)》请在冰豆网上搜索。
五子棋游戏总体设计与实现
4。
系统总体设计与实现
4.1总体设计分析
总体设计是软件开发过程中的另一个重要阶段,在这一阶段中将根据需求分析中提出的逻辑模型,科学合理地进行物理模型的设计。
这个阶段的主要目标是将反映用户信息需求的逻辑方案转换成物理方案,并为下一阶段提供必要的技术资料。
4。
1。
1总体设计原则
(1)整体性:
软件是作为统一整体而存在的。
因此,在总体设计中要从整个软件的角度进行考虑.
(2)灵活性:
为保持软件长久的生命力,要求该手机游戏软件具有很强的环境适应性。
为此,游戏软件应具有较好的开放性和结构的可变性。
(3)可靠性:
可靠性是指软件抵御外界干扰的能力及受外界干扰时的恢复能力。
(4)经济性:
经济性是指在满足游戏软件需求的前提下,尽可能地减小游戏软件的开销。
4。
1.2软件模块总体设计
软件中各模块之间的关系通常利用层次图来表示。
它是一种一系列多层次的用树形结构的矩形框描绘数据的层次结构框图。
一个单独的矩形框作为树形结构的顶层,各个数据的子集由下面的各层矩形框代表,最底层的各个矩形框代表组成这个数据的实际数据元素(不能再分割的元素),它代表完整的数据结构。
这模式非常适合于需求分析阶段的需要,层次方框图对数据结构描绘随着结构精细化也越来越详细。
反复细化沿着图中每条路径,从对顶层信息的分类开始,直到确定了数据结构的全部细节为止.
图4—1游戏功能结构
本研究中将游戏软件分为三大模块,如图4—1所示,包括:
游戏选项、游戏设置和帮助。
按照在调研中搜集的资料对每个模块的功能进行编排制作。
依据上述功能的分析,本研究中,将游戏软件在三大模块的基础上又对每一大模块又分为几个子模块:
游戏选项包括六个模块:
开始游戏、重新游戏、悔棋、认输、背景音乐和退出游戏。
游戏设置包括三个模块:
先后手设置、棋盘底纹颜色设置和棋盘大小设置。
帮助包括两个模块:
游戏帮助和关于.
4。
2游戏设计
4.2。
1游戏前的准备
本游戏在开发之前需要做一些前期准备工作,尤其是对于精通五子棋游戏的Java游戏开发者来说.通常情况下,一款运用起来比较熟练地J2ME开发工具是必不可少的。
本游戏使用的是J2ME的简化开发工具SunJava(TM) WirelessToolkit2.5.2for CLDC,他需先将Java虚拟机安装调试好之后才能使用。
WTK2.5.2不带有文本编辑功能,所以需要另寻搭配使用.本游戏采用UltraEdit进行编辑。
本游戏需要几张后缀名为.png格式的卡通图,除了一张用作五子棋游戏的Logo 外,其余的都将在游戏中使用。
4.2.2游戏界面和事件驱动设计
游戏的界面设计采取传统游戏界面风格,如图4-2所示.游戏设计中采用传统界面游戏风格,首先启动游戏,然后进入游戏开始界面,界面中放置“设置”、“开局”、“帮助”、“关于”四个选项供玩家选择。
其中“设置"选项主要是对游戏的相关功能进行设置,如游戏难度设置。
另外还有“悔棋”、“重玩”等项目的设置。
除此之外还包括查看游戏帮助、游戏介绍等。
图4—2游戏界面设计
所谓事件驱动,简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数)。
当然事件不仅限于用户的操作.我们知道,事件是事件驱动的核心自然是.从事件角度说,一个事件收集器、一个事件发送器和一个事件处理器组成了事件驱动程序的基本结构。
事件收集器专门负责收集包括来自硬件的(如时钟事件等)、来自用户的(如键盘、鼠标事件等)及来自软件的(如应用程序本身、操作系统等)的所有事件。
将收集器收集到的事件分发到目标对象中则由事件发送器负责完成.具体的事件响应工作则由事件处理器完成,它需要运用虚函数机制(函数名取为类似于Handle Msg 的一个名字),它往往要到实现阶段才完全确定.事件处理器对于框架的使用者来说是他们唯一能够看到的。
棋类游戏通常具备两个重要特性,首先是对战双方轮流落子,其次是落子间隔通常是不确定的,尤其是对战后期,可能每一步棋都要经过深思熟虑,无论是人还是计算机,都无法对时间间隔有事先的预期.基于以上两个特性,本游戏摒弃了大多数游戏采用的线程或定时器驱动游戏的方法,而采用了事件驱动的方法,即玩家的键盘或触摸笔触发游戏的下一个动作。
事件驱动大大减少了不必要的工作量,只有玩家发出消息时,计算机才启动运算,而在玩家思考期间,计算机不做任何运算和重绘操作.
4.2。
3游戏的类设计
五子棋游戏属于二维棋类游戏,因此可以定义一个Chesses类来表示棋子,用一个 Chess 类型的二维数组来包含棋盘上的所有棋子,对于该棋子玩家的区分使用Chesses的boolean型的变量 isPlayer1来区分.可以考虑直接生成数组的每一个对象而不是在数组建立后,而是把每一个棋子对象(Chesses)放在游戏的进行中生成,这主要是考虑到移动设备的资源有限,尽可能减少系统资源占用。
这样在游戏进行时,可以避免还没有下的棋子在一开始就占用了系统内存,玩家每下一步棋,在数组相应位置生成该棋子的对象。
对于游戏中的每一类的设计,首先就是一个MIDlet类,Gobang 类继承自MIDlet类,通过方法startApp,pauseApp,destroyApp 来通知游戏的开始,暂停和销毁结束,用于连接设备的应用程序管理器(ApplicationManager)。
本游戏共由7个类组成,它们各自的功能如下:
(1) GobangMIDlet类
负责程序的启动和屏幕之间的切换;
(2)GobangCanvas类
玩家的对战平台,他继承于 Canvas 类;
(3) Setting类
用于创建游戏的各项设置参数表单;
(4)GobangLogic类
游戏的逻辑类,负责胜负判断和计算机落子;
(5)Dot类
棋子类,包含了棋子的位置信息;
(6) Help 类
游戏的帮助类,包含五子棋的一些常识信息和五子棋教学内容;
(7)About类
游戏的关于类,包含游戏的版本、版权等信息。
各个类之间的关系如图4-3所示:
图4-3游戏类设计
4.2.4游戏的流程设计
对于棋盘界面的更新,游戏进行绘制棋子时是按照棋子的二维数组来完成的,玩家下棋后,设置isPlayer1 值,程序修改数组相应位置,然后重新绘制(repaint)。
为了使游戏的操作尽可能的简便,本文设计上不在游戏进入时设计菜单,玩家可以直接开始对战,而是在开始游戏的过程中设置重新开始和退出的按钮。
即一键开始,运行即玩,重来或退出都使用一键操作.游戏流程的设计依据主要是游戏的界面设计和游戏的类的设计。
游戏启动时,Gobang MIDlet对象先显示游戏的主屏幕,在屏幕下方一侧是出软键(软键指描述抽象客户端设备如何显示),另一侧是用软件构成的菜单,菜单元素主要有“开局”、“游戏设置"、“游戏帮助”、“关于”选项.当玩家选择“游戏设置"软键时,则显示游戏参数设置表单;当玩家选择“开局”软键时,则显示游戏对战主界面;当玩家选择“游戏帮助”软键时,则显示游戏帮助表单;当玩家选择“关于”软键时,则显示游戏关于表单。
玩家进入游戏参数设置表单,当玩家按下“确定”软键时,则确认当前游戏参数,返回游戏主屏幕;当玩家按下“取消"软键时,则放弃此次对游戏的修改,直接返回游戏主屏幕。
玩家进入游戏对战画布,对战中画布有两个软键,当玩家按下“返回主菜单”软键时,则退出游戏到达游戏主菜单;当玩家按下“悔棋"软键时,则进行悔棋操作;当游戏结束时,“悔棋”软键被换成了“重玩”软键.玩家进入游戏介绍表单,当玩家按下“确定”软键时,返回游戏主屏幕。
4.2。
5游戏算法的设计
1、五子棋的获胜组合
有哪些获胜组合是在一场五子棋的游戏中计算机必须要知道的,因此,获胜组合的总数必须要求得.在本文中我们假定当前的棋盘为15*15:
(1)每一列的获胜组合是11,共15列,计算水平方向的获胜组合数,所以水平方向的获胜组合数为:
11*15=165。
(2)每一行的获胜组合是11,共15列,则可计算垂直方向的获胜组合总数,垂直方向的获胜组合数为:
11*15=165。
(3)同理,可计算正对角线方向的获胜组合总数,正对角线上的获胜组合总数为11+(10+9+8+7+6+5+4+3+2+1)*2=121.
(4)计算反对角线上的获胜组合总数。
计算反对角线方向的获胜组合总数可计算为11+(10+9+8+7+6+5+4+3+2+1)*2=121.这样可计算得所有的获胜组合数为:
165+165+121+121=572。
2、设计获胜棋型
通过上面的计算,一个15*15的屋子棋盘在此已经计算出了会有572中获胜方式,因此,我们就可以利用数组建立一些常规棋型,棋型的主要作用是:
(1)判断是否有任何一方获胜;
(2)根据当前格局判断最可能的落子方式。
然而在现实中,高手留给我们的经验就是把握前奏,如“冲四”、“活三”,除了“连五”以外,这些也是同向胜利的捷径。
3、攻击与防守
获胜棋型的算法是中性的,不区分计算机和玩家,这就涉及到攻击和防守何者优先的问题。
而许多高手都认为五子棋的根本是“防守”,“攻击”是灵魂。
进攻是取胜的手段,是防守的延续和发展。
许多经验和研究表明,一个棋手只要掌握了全面的、基本的防守原理和技巧,就能和比自己棋力高一个等级的进攻型选手对抗,起码能立于不败之地。
对手进过越偏激,则防守的效果越好.没有进攻的防守就像只开花不结果,没有实际意义,顽强的防守是反攻的前奏,没有进攻的延续,防守也失去了价值.而这缺一不可。
根据以上原理,计算机在接受最佳的攻击位置之前,还要计算当前玩家的最佳攻击位置.如果玩家存在最佳攻击位置,那么计算机就将下一步的棋子摆在玩家的最佳攻击位置上以阻止玩家的进攻,否则计算机便将棋子下在自己的最佳攻击位置上进行攻击。
4、用到的典型算法
(1)坐标变换算法
游戏的实质其实是对所下棋子的位置进行操作和判断,因此将己方、对方以及棋盘上空点的位置坐标存储在相应的List中。
我对所下棋子的坐标进行了处理,因为我所采用的棋盘为15*15,所以棋子横坐标为0到14的整数,纵坐标也为0到14的整数。
因此,每次在棋盘上下子之后,计算机在存储该点的坐标时,便要对坐标进行加工。
假设左上角点为firstPoint,它的实际坐标为(x1,y1),而我是将它作为(0,0)存储的,其它的坐标,其它点都是以该点为标准进行变换的,假设棋盘上每个格子的宽度为w,某实际点为(x2,y2),变换后的坐标为(x,y),x=(x2—x1)/w,y=(y2-y1)/w。
(2)胜负判断算法
胜负判断的规则很简单,就是判断游戏双方的棋子在同一条水平线、同一条竖线或是同一条斜线上谁先出现5个连续的棋子,谁先达到这样的目标,谁就获得胜利.在本设计中,是在每次下完一个子后进行判断,看己方是否达到了胜利的标准,若胜利游戏便结束;否则,游戏继续。
(3)人工智能算法
人工智能算法的主体思想分为以下三个步骤:
第一步:
根据双方的当前的形势循环地假设性的分别给自己和对方下一子(在某个范围内下子),并判断此棋子能带来的形势上的变化,如能不能冲4,能不能形成我方或敌方双3等.
第二步:
根据上一步结果,组合每一步棋子所带来的所有结果(如某一步棋子可能形成我方1个活3,1个冲4(我叫它半活4)等),包括敌方和我方的.
第三步:
根据用户给的规则对上一步结果进行排序,并选子(有进攻形、防守形规则)。
5、典型类的具体设计
(1)应用程序类
Gobang类用于连接设备的应用程序管理器(ApplicationManager),Gobang类继承自 MIDlet类,通过Gobang类的方法start App,pauseApp,destroyApp来通知游戏的开始,暂停和销毁结束。
源代码如下:
packagecom.occo。
j2me。
game.gobang;
import javax。
microedition.lcdui。
Display;
importjavax。
microedition.midlet.MIDlet;public classGobangextends MIDlet
//定义游戏界面的Canvas 类GobangCanvas的对象Gobangpublic
{Gobang Canvas gobang;
Gobang(){
super();
gobang=new GobangCanvas(this);//生成 GobangCanvas类的对象gobang
}protected voidstart App(){
Display。
getDisplay(this)。
set Current(gobang);
} protected voidpause App(){
}protectedvoiddestroyApp(boolean arg0){
}}//在屏幕上绘出游戏见面gobang
(2)游戏界面类
GobangCanvas 类继承自Canvas,游戏的核心类是GobangCanvas类,此类将完成游戏的绘图、互动、控制、逻辑、等所有功能,此类的框架代码如下:
Packagecom.occo。
j2me.game。
gobang;
importjavax.microedition。
lcdui.Displayable;
importjavax.microedition.lcdui。
Command;
importjavax。
microedition。
lcdui.Canvas;
importjavax。
microedition.lcdui。
CommandListener;
public GobangCanvas(Gobanggobang){
this.gobang=gobang;}
protected voidpaint(Graphicsg){
}
import javax.microedition.lcdui。
Graphics;public class GobangCanvas extends Canvasimplements Command Listener{protected Gobanggobang; publicGobangCanvas(){}
}
(3)棋子类
整个棋盘是一个 Chesses 类型的二维数组,棋盘上的每一个棋子都对应着一个Chesses的对象,此类定义了一个棋子,源代码如下:
package com.occo.j2me.game.gobang;
publicChesses() {}
publicclassChesses{boolean isPlayer1;
publicChesses(booleanisPlayer1){
this。
isPlayer1=is Player1;
}}
4。
3游戏实现
4.3.1主类的实现
YpkWuZiQiActivity类是五子棋游戏的主类,同时也是五子棋游戏的入口,它继承自Activity类。
进入程序后,首先调用init()方法,init()方法通过调用setContentView(R。
layout。
welcomeview)显示登录该游戏的第一个界面。
welcomeview。
xml是一个布局文件,里面存储了界面信息.该界面中有四个Button,分别为welButton1、welButton12、welButton3、welButton4,点击每个Button都会触发一个事件,其中点击welButton1和welButton2还会给它的成员变量FIGHTINGMODE赋值,因为在人人对战和人机对战是写在同一个ChessBoard类中的,所以需要通过FIGHTINGMODE的值来区分是人人对战还是人机对战。
点击welButton1时,FIGHTINGMODE=1,然后会调用initTwo()方法,该方法通过调用setContentView(R.layout.chess)方法,来显示对战的界面。
chess.xml文件存储了对战界面的信息。
在chess.xml文件中调用了ChessBoard类,该类中主要定义了棋盘的信息,下文会对该类做具体的介绍的.在对战界面中也有四个Button,分别是b1、b2、b3、b4.
首先来介绍一下b2,该Button的功能是返回主页,调用init()方法就可以实现。
b3的功能是重新开始,这个也只需要调用initTwo()方法。
b3的功能是退出,调用了系统方法:
System.exit
(1).下面重点介绍一下b1,该Button的功能是悔棋。
该Button设定的点击事件详细内容如下:
b1.setOnClickListener(newOnClickListener(){
publicvoidonClick(Viewv){
ChessBoardchess=(ChessBoard)findViewById(R.id.chess);
Point temp=null;
if(chess。
whoRun ==1){
ﻩﻩif(chess。
firstPlayer.getMyPoints()。
size()>=1&&chess。
secondPlayer!
=null){
temp=chess.secondPlayer.getMyPoints().get(chess。
secondPlayer.getMyPoints().size()-1);
chess。
secondPlayer.getMyPoints().remove(temp);
chess.freePoints.add(temp);
temp=chess。
firstPlayer.getMyPoints()。
get(chess。
firstPlayer.getMyPoints().size()-1);
chess.firstPlayer.getMyPoints()。
remove(temp);
chess.freePoints.add(temp);
chess.freshCanvas();
ﻩﻩﻩﻩ}
ﻩﻩﻩ}
if(chess.whoRun==2){
if(chess。
firstPlayer.getMyPoints()。
size()>=1&&chess。
secondPlayer!
=null){
temp=chess.firstPlayer.getMyPoints().get(chess.firstPlayer.getMyPoints()。
size()-1);
chess。
firstPlayer。
getMyPoints().remove(temp);
chess.freePoints.add(temp);
temp=chess。
secondPlayer.getMyPoints().get(chess.secondPlayer.getMyPoints().size()—1);
chess.secondPlayer。
getMyPoints().remove(temp);
chess。
freePoints.add(temp);
chess.freshCanvas();
ﻩ}
ﻩﻩ }
}
})
首先获取ChessBoard对象,该对象继承自View,详细的定义了棋盘信息,主要负责显示棋盘的内容。
接下来判断一下触发悔棋事件的是哪一个玩家,再判断是否符合悔棋的条件,这个条件很简单,就是棋盘上至少要有两个棋子.之后便进行悔棋操作,分别将两个玩家最后下的棋子取出,程序实现就是将两个ArrayList的最后一个元素remove出来,再分别放到记录棋盘中没有棋子的点的集合中,最后更新一下画布,主要是调用ChessBoard的invalidate()方法.通过以上步骤之后,呈现在我们面前的便是悔完棋的画面了.
点击welButton2时,FIGHTINGMODE=2,之后的步骤便会点击welButton1是相同的了,不同的是,由于对战模式的改变,从人人对战变成了人机对战。
点击welButton3时,通过initThree()方法调用setContentView(R.layout.netchess)方法实现网络对战。
详细的对战实现细节将会在下文一一介绍。
在这个界面中只保留了两个Button:
b2和b4.这两个Button所实现的功能和上面的b2和b4是相同的。
最后,welButton4比较简单。
它所实现的功能为退出应用程序,调用System.exit
(1)方法。
4。
3.2游戏设置类的实现
游戏设置表单用来对游戏参数进行设置,包括棋盘大小、先手选择、智能级别.表单中使用了Gauge和Choice Group 两种高级用户界面组件.
1、棋盘尺寸选择
标准的五子棋棋盘为15*15,但为了满足不同玩家的需求,这里提供了大小为10*10到 20*20的棋盘,用户可以通过Gauge 组件改变.棋盘的最小值为10,而Gauge 组件的最小值为 0,所以当前的 Gauge值需要角上10 才是当前棋盘大小.创建 Gauge组件的代码如下:
form =new Form(”游戏设置");//创建参数设置表单并添加标签
gauge Size = new Gauge("棋盘规格:
"+board Size +"X" + board Size,true,10,boardSize-10); //棋盘规格
form。
append(gaugeSize);
图4—4棋盘尺寸的设计
在Gauge交互模式下可以为Gauge对象所在的表单对象绑定一个ItemStateListener事件监听器,并在监听器上捕捉 Gauge对象的事件,当 Gauge的值发生变化时就会触发事件。
这里将根据Gauge的当前值改变标签,显示当前的棋盘大小。
其代码如下:
publicvoiditem StateChanged(Itemitem)
{
if(item==gaugeSize)//当Gauge组件发生变化时
{
int bs=gaugeSize。
getValue() +10;//获取当前的Gauge值并计算棋盘大小(加10)
gauge Size。
setLabel(”棋盘规格:
” + bs+”X” + bs);//改变Gauge组件的标签
}
}
2、难度选择
游戏的难易程度根据计算机的智能级别来控制,创建及添加选项的方法和复选框一样,所不同的是在创建Choice Group 对象时,类型设置为 1(单选)。
对于单选框,setSelectedIndex只能用来指定某个选项被选中,因此,布尔值selected 的值必然为true,否则便没有意义.
游戏共有 3个难度级别,分别是:
拜师学艺、棋行天下、谁与争锋(此游戏中并未作出区分),初始情况下为拜师学艺,该选项的索引值为 0。
创建难度选择单选框的代码如下:
level = 1;//默认情况下的难度级别
choicelevel= newChoiceGroup("电脑智能级别:
”,1);