戏基于FLEX开发的连连看游戏详细设计说明书[V1.1.0]学院名称:湖南软件职业学院专业名称:软件技术专业组员:虢威、孙庆龙、段志辉、罗奇****:***戏1引言 (3)1.1编写目的 (3)1.2背景 (3)1.3定义 (3)1.4参考资料 (3)2程序系统的结构 (3)3程序(标识符)设计说明 (4)3.1程序描述 (4)3.2功能 (4)3.3性能 (5)3.3.1精度 (5)3.3.2时间特性要求 (5)3.3.3灵活性 (5)3.4算法 (6)3.4.1地图的生成 (6)3.4.1寻路算法 (8)3.5流程逻辑 (13)3.6接口 (13)3.7注释设计 (14)3.9限制条件 (14)3.10尚未解决的问题 (14)戏详细设计说明书1引言1.1编写目的详细设计说明书对连连看游戏的总体设计和各个模块的功能、性能、输入输出、算法、接口、程序逻辑、存储分配及其它给出了详细的设计方案,为软件开发制定详细的计划,同时也提交系统分析员,由其提出意见。
这是程序员开发及未来测试烦人重要文档资料。
1.2背景a.开发软件名称:基于FLEX开发的连连看b.项目开发小组成员:虢威、孙庆龙、段志辉、罗奇c.用户:所有喜欢玩这个游戏的玩家d.项目开发环境:Windows XP + Flash Builder4 + ActionScript 3.0。
1.3定义连连看项目详细设计方案。
1.4参考资料(1)《软件工程案列开发与实践》,刘竹林等,清华大学出版社(2)《IT项目管理》,曾鸿、毛志雄等,中国铁道出版社(3)《ActionScript 3.0编程精髓》,Colinn Moock(美),机械工业出版社(4)《Flex 3 Cookbook》,(美)诺布尔(美)安德森,电子工业出版社2程序系统的结构本次所设计连连看游戏的程序主结构如图2-1所示。
戏3程序(标识符)设计说明从本章开始,逐个地给出各个层次中的每个程序的设计考虑。
以下给出的提纲是针对一般情况的。
对于一个具体的模块,尤其是层次比较低的模块或子程序,其很多条目的内容往往与它所隶属的上一层 模块的对应条目的内容相同,在这种情况下,只要简单地说明这一点即可。
3.1程序描述主要功能:连连看是一款图案配对的益智游戏,与“找出两幅图片中的不同”类戏同为比眼力的游戏。
游戏速度节奏快,画面清晰可爱,适合细心的玩家。
可扩展性:能够适应应用要求的变化和修改,具有灵活的可扩充性。
3.2功能游戏界面主框架主要包括游戏图形区域界面、游戏开始按钮、游戏关闭按钮。
游戏画布区主要应该包括游戏画布中图片随机出现的位置。
初始化进入事件等待状态 初始化失败不正常退出开始请求 相关事件返回暂停请求 退出 正常退出图2-1 连连看程序主结构戏3.3性能3.3.1精度1、在执行游戏页面首次加载的时候,不允许出现因为程序的原因导致增加加载失败;2、在执行物件删除操作的时候,不允许因为程序的原因发生多删除物件、删除失败的情况3.3.2时间特性要求把用户进入游戏界面的时间要求在3秒内,对鼠标点击两个相同物件后,物件消失的响应时间规定在2秒内。
3.3.3灵活性A、操作方式程序在通常的应用环境下使用鼠标和键盘进行输入和输出操作,对于执行按钮,通常使用鼠标的点击完成。
B、运行环境WINDOWS XP操作系统。
戏3.4算法3.4.1地图的生成本游戏地图设计是由一个由M*N(M=N)个的正方形图案组成的.因此我们设定按钮在X 轴上的数目为x_num,在Y轴上的数目为y_num。
然后用一个地图数组来存储地图元素。
其中每个数字代表一种图案,而0则为同路,代表无图。
所以,我们的地图数组可能是以下这样的一组数据。
这个地图为(行数+ 2) * (列数+ 2) 的距阵。
[[0,0,0,0,0,0],[0,1,4,3,1,0],[0,2,3,1,2,0],[0,4,2,3,4,0],[0,3,1,4,2,0],[0,0,0,0,0,0]]为何要在周围加上一圈0,待会在算法中解释。
这样的地图有以下特点:1.地图中的每一个数字的个数都是偶数,也即都是成对的出现2.地图的排列必须是随机排列的.3.地图中的每一个数字的种类不能大于已有的图案的个数。
以下是产生按钮数组的代码:public function genBtns():void{this._btns.length = 0;//清除以前保存的按钮数组var x_num:uint = Game.NUM_X + 2;//按钮数组 X轴大小var y_num:uint = Game.NUM_Y + 2;//按钮数组 y轴大小var vals:Array = this.genVals();var v:int = 0;for(var p_x:uint = 0;p_x<x_num;p_x++){var x_btns:Array = [];for(var p_y:uint = 0;p_y<y_num;p_y++){if(p_x == 0 || p_x == (x_num - 1) || p_y == 0 || p_y == (y_num - 1)){x_btns.push(null);}else{var l_x:uint = (p_x-1) * MyButton.SIZE + Game.MARGIN;var l_y:uint = (p_y-1) * MyButton.SIZE + Game.MARGIN;var val:uint = vals[v++];var btn:MyButton = newMyButton("btn_"+p_x+"_"+p_y,val,val+"",l_x,l_y,new Point(p_x,p_y));x_btns.push(btn);}戏}this._btns.push(x_btns);}}以下是把按钮添加到画布的代码:private function addBtns(e:TimerEvent):void{var tmpCount:uint = this._dfFlag?Game.NUM_X+2:Game.NUM_Y+2;var btns:Array = [];if(btnsIdx < tmpCount){if(this._dfFlag){btns = this._btns[btnsIdx] as Array;for(var j:uint=0;j<btns.length;j++){var btn:MyButton = btns[j] as MyButton;if(btn){this._btn_content.addElement(btn);this._lab_Count.text = (++tCount) +"";}}}else{for(var i:uint=0;i<Game.NUM_X+2;i++){var btn2:MyButton = this._btns[i][btnsIdx] as MyButton;if(btn2){this._btn_content.addElement(btn2);this._lab_Count.text = (++tCount) +"";}}}btnsIdx++;}else{t.stop();t.removeEventListener(TimerEvent.TIMER,addBtns);t = null;this._lab_level.text = this.getLevel() + "";startTime();//开始计时}}戏3.4.1寻路算法为了方便,我们假设地图大小为4*4,国旗有4种。
参考以下图片,图中用4中颜色表示4种不同国旗。
实际上程序内部是不需要认识国旗的图象的,只需要用一个ID 来表示,界面上画出来的国旗图形是根据ID 取资源里的图片画的。
比如上图中用 4 种颜色表示 4 种国旗,我们可以定义红色棋子的ID 为1,绿色为2,蓝色为3,黄色为4。
另外,如果棋子被消除ID 可以定义为0。
把ID 放在一个二维矩阵,画到界面上时,根据距阵里元素的位置和值(ID)决定在什么位置画什么颜色棋子。
我见过两种风格的连连看,有一种是和我正在写的连连看一样,连线可以伸到图形矩行外面,比如图中的第一行有两个红色棋子,这两个是可以连的;另外一种和QQGame 里的连连看一样,连线不能伸到棋子矩行外面,也就是说图中的第一行的两个红色棋子是不能连的。
程序内部棋子都是数字,这两种风格的差别在于ID 距阵的大小,第一种是:(行数+ 2) * (列数+ 2);第二种是:行数* 列数。
第一种更简单,所以下面只说第一种。
连通算法:1、两次点击同一张图片:return null2、两次点击不同图片:return null3、两次点击同一种图片:连连看所要求的是:A:两个目标是相同的B:两个目标之间连接线的折点不超过两个。
(连接线由x轴和y轴的平行线组成)那么分析一下连接的情况可以看到,一般分三种情况a:直线相连b:一个折点c:两个折点如下图:戏具体实现代码如下:public static function testLX(frBtn:MyButton,toBtn:MyButton):Array{ if(frBtn == toBtn){//同一个对象return null;}if(frBtn.getVal() != toBtn.getVal()){//值不符合return null;}var fr_point:Point = frBtn.getPoint();var to_point:Point = toBtn.getPoint();var points:Array = [fr_point];//目标点只有两个//测试 0个转折点(水平或者垂直方向) 是否能通过if(isPass(fr_point,to_point,frBtn,toBtn)){points.push(to_point);return points;}//测试 1个转折点是否能通过var p1:Point = new Point(fr_point.x,to_point.y);//转折点 1var p2:Point = new Point(to_point.x,fr_point.y);//转折点 2if(isPass(fr_point,p1,frBtn,toBtn) &&isPass(p1,to_point,frBtn,toBtn)){// 转折点 1 可以无障碍的连接两点points.push(p1);points.push(to_point);return points;}if(isPass(fr_point,p2,frBtn,toBtn) &&isPass(p2,to_point,frBtn,toBtn)){// 转折点 2 可以无障碍的连接两点戏points.push(p2);points.push(to_point);return points;}//测试 2个转折点是否能通过//两个 x轴相等或两个 y轴相等var i:int;var j:int;var first_p:Point;//第1个连接点var second_p:Point;//第2个连接点var btns:Array = getGameInstant().getBtns();// →for(i = fr_point.x+1;i < Game.NUM_X + 2;i++){if(btns[i][fr_point.y] == null){//无障碍first_p = new Point(i,fr_point.y);//第1个连接点second_p = new Point(i,to_point.y);//第2个连接点if(isPass(to_point,second_p,frBtn,toBtn) && isPass(first_p,second_p,frBtn,toBtn)){points.push(first_p);points.push(second_p);points.push(to_point);return points;}}else{break;}}// ←for(i = fr_point.x-1;i >= 0;i--){if(btns[i][fr_point.y] == null){//无障碍first_p = new Point(i,fr_point.y);//第1个连接点second_p = new Point(i,to_point.y);//第2个连接点if(isPass(to_point,second_p,frBtn,toBtn) && isPass(first_p,second_p,frBtn,toBtn)){points.push(first_p);points.push(second_p);points.push(to_point);return points;}}else{break;}戏}// ↓for(i = fr_point.y+1;i < Game.NUM_Y + 2;i++){if(btns[fr_point.x][i] == null){//无障碍first_p = new Point(fr_point.x,i);//第1个连接点second_p = new Point(to_point.x,i);//第2个连接点if(isPass(to_point,second_p,frBtn,toBtn) &&isPass(first_p,second_p,frBtn,toBtn)){points.push(first_p);points.push(second_p);points.push(to_point);return points;}}else{break;}}// ↑for(i = fr_point.y-1;i >= 0;i--){if(btns[fr_point.x][i] == null){//无障碍first_p = new Point(fr_point.x,i);//第1个连接点second_p = new Point(to_point.x,i);//第2个连接点if(isPass(to_point,second_p,frBtn,toBtn) &&isPass(first_p,second_p,frBtn,toBtn)){points.push(first_p);points.push(second_p);points.push(to_point);return points;}}else{break;}}return null;}//判断两点之间在水平或者垂直方向是否能通过private static functionisPass(fr_point:Point,to_point:Point,fr_btn:MyButton,to_btn:MyButton) :Boolean{var btns:Array = getGameInstant().getBtns();var i:int;戏//直线—if(fr_point.y == to_point.y){// →for(i = fr_point.x;i <= to_point.x;i++){if(btns[i][fr_point.y] == fr_btn || btns[i][fr_point.y] == to_btn){continue;}if(btns[i][fr_point.y]){//有障碍return false;}}// ←for(i = fr_point.x;i >= to_point.x;i--){if(btns[i][fr_point.y] == fr_btn || btns[i][fr_point.y] == to_btn){continue;}if(btns[i][fr_point.y]){//有障碍return false;}}return true;}//竖线 |if(fr_point.x == to_point.x){// ↓for(i = fr_point.y;i <= to_point.y;i++){if(btns[fr_point.x][i] == fr_btn || btns[fr_point.x][i] == to_btn){continue;}if(btns[fr_point.x][i]){//有障碍return false;}}// ↑for(i = fr_point.y;i >= to_point.y;i--){if(btns[fr_point.x][i] == fr_btn || btns[fr_point.x][i] == to_btn){continue;}戏if(btns[fr_point.x][i]){//有障碍return false;}}return true;}return false;}3.5流程逻辑本次游戏设计的处理流程如下图所示3.6接口3.6.1外部接口戏A、用户界面本软件的屏幕格式,按钮格式,输入输出方式等都是完全按照人性化的设计,方便用户执行各种操作。