实验三 详细设计

 

软件工程实验报告 三

一、实验名称

系统详细设计

二、实验目的

根据需求分析、概要设计,完成系统的详细设计

三、实验主要内容

详细设计的主要任务是设计每个模块的实现算法、所需的局部数据结构。详细设计的目标有两个:实现模块功能的算法要逻辑上正确和算法描述要简明易懂。

四、实验原理

1、模块说明。说明该模块需要实现什么功能,还有设计要点。
2、流程逻辑。用流程图说明该模块的处理过程。
3、算法。不一定有,如果涉及一些比较特殊的算法或关键模块,就写一下算法的伪代码或用流程图说明。
4、限制条件。该模块的功能有哪些限制,比如用户ID不能重复,只能查询自己权限范围内的用户。
5、输入项。每个子模块可以看做一个”方法“,我传给你什么,你给我输出什么。比如删除用户,输入项就是用户ID。
6、输出项。删除用户的输出项,就是不能在查询模块里查询到已删除的用户
7、界面设计。用visio或者其他工具画一些界面图
8、需要操作的数据表。

五、实验结果

详细设计

目录

一、用户界面设计

二、系统实现.

2.1通用功能类的实现

2.2申报开票模块的实现

三、总结和展望

3.1总结

3.2展望

11主要成员变量说明:

没有棋子为0,黑子为1,白子为2

              private const NOTHING:uint = 0;

              private const BLACK:uint = 1;

              private const WHITE:uint = 2;

盘面状态数组 canPlay

盘面上的旗子数组aGridState

棋子的几种状态  public const STWO:int = 2;//眠二

              public const FTWO:int = 4;//假活二

              public const STHREE:int = 5;//眠三

              public const TWO:int = 8;//活二

              public const SFOUR:int = 12;//冲四

              public const FTHREE:int = 15;//假活三

              public const THREE:int = 40;//活三

              public const FOUR:int = 90;//活四

              public const FIVE:int = 200;//五连

棋盘中的八个方向private var dir:Array = [[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1],[-1,0]]

(从左上角开始顺时针)。

 

1.2 主要成员函数说明:

 

先是初始化盘面数组for (var i:uint=0; i<gridnum; i++) {

                      aGridState[i] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

               }

               mcChessboard.addEventListener(MouseEvent.MOUSE_DOWN,AddMyChessman);

               btnStart.addEventListener(MouseEvent.CLICK,btnStart_Handler);

               btnReplay.addEventListener(MouseEvent.CLICK,btnReplay_Handler);

               mcSelectChessman.addEventListener(MouseEvent.MOUSE_DOWN,selectChessman);

        }

 

在选择开始后进行棋盘初始化private function init():void{

               btnStart.visible = false;

               for(var i:int=0;i<aChessmen.length;i++){

                      mcChessboard.removeChild(aChessmen[i]);                           

               }

               for (var j:uint=0; j<gridnum; j++) {

                      aGridState[j] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

               }

               aChessmen = [];

               canPlay = true;

        }

玩家添加棋子的函数

        public function AddMyChessman(e:MouseEvent):void {

               //不能添加棋子的状态(棋局未开始、对方走、棋子没有落在棋盘里)

               if(!canPlay || crtSide != mySide || e.target.name != "mcChessboard")

                      return;

               if (mySide == crtSide) {

                      //计算鼠标落在哪一格

                      var crtx:uint = Math.floor(e.localX/gridsize);

                      var crty:uint = Math.floor(e.localY/gridsize);

                      //如果这一格已经有棋子就返回

                      if (aGridState[crty][crtx])

                             return;                               

                      //创建棋子

                      var chessman:Chessman;

                      if (mySide == BLACK) {

                             chessman = new BlackChessman();

                      } else {

                             chessman = new WhiteChessman();

                      }

                      chessman.bPlayer = true;

                      aGridState[crty][crtx] = mySide;

                      chessman.x = (crtx + .5) * gridsize;

                      chessman.y = (crty + .5) * gridsize;

                      aChessmen.push(chessman);

                      mcChessboard.addChild(chessman);

                      checkWinner(crtx,crty,crtSide);                                        

                      //对方走

                      crtSide = WHITE + BLACK - mySide;

                      //计算机走

                      var opos:Array = CalculateState(crtSide);

                      var cx:int = opos[0];

                      var cy:int = opos[1];

                      AddChessman(cx,cy);                                 

                      checkWinner(cx,cy,crtSide);

                      crtSide = mySide;

               }

        }

计算机添加旗子的函数

public function AddChessman(toX:int,toY:int):void {

               if(!canPlay)

                      return;

               var autox:int = toX;

               var autoy:int = toY;

              var chessman:Chessman;

               if (mySide == BLACK) {

                      chessman = new WhiteChessman();

               } else {

                      chessman = new BlackChessman();

               }

               chessman.x = (autox + .5)*gridsize;

               chessman.y = (autoy + .5)*gridsize;

               aGridState[autoy][autox] = (BLACK + WHITE) - mySide;

               aChessmen.push(chessman);

               mcChessboard.addChild(chessman);

        }

 

检测棋盘上每一各的分值,返回得分最高的棋格坐标

 

public function CalculateState(side):Array{

               var i:int,j:int,k:int;

               var otherside:int = WHITE + BLACK - side;    

               //填充玩家的棋形表和对手的棋形表

               for(i = 0;i<gridnum;i++){

                      for(j = 0;j<gridnum;j++){

                             if(aGridState[i][j] != NOTHING){

                                    aOpponent[i * gridnum + j] = {val:-1,x:j,y:i};

                                    aPlayer[i * gridnum + j] = {val:-1,x:j,y:i};

                             }

                             else{

                                    var v1 = getScore(aGridState,j,i,side);

                                    aOpponent[i * gridnum + j] = {val:v1,x:j,y:i};

                                    var v2 = getScore(aGridState,j,i,otherside);

                                    aPlayer[i * gridnum + j] = {val:v2,x:j,y:i};

                             }                                

                      }

               }

               //取得分值最大的棋格

               var maxO:Object = sortArray(aOpponent);

               var maxP:Object = sortArray(aPlayer);

               var apos:Array = [0,0];

               if(maxO.val < maxP.val)

                      apos = [maxP.x,maxP.y];

               else

                      apos = [maxO.x,maxO.y];

               return apos

        }

 

 

检测赢家

private function checkWinner(xp:int,yp:int,side:int){

               var str:String = (side * 11111).toString();

               var winner:int = 0;     

               var str1:String = getXLine(aGridState,xp,yp,side).join("");

               var str2:String = getYLine(aGridState,xp,yp,side).join("");

               var str3:String = getXYLine(aGridState,xp,yp,side).join("");

               var str4:String = getYXLine(aGridState,xp,yp,side).join("");

               if(str1.indexOf(str)>-1 || str2.indexOf(str)>-1 || str3.indexOf(str)>-1 || str4.indexOf(str)>-1)

                      winner = side;                  

               if(winner){

                      doWin(winner);

               }                  

        }

//取胜后触发的事件

        private function doWin(side:int):void{

              //现实游戏结果说明

               mcGameState.visible = true;

               //关闭棋局

               canPlay = false;

               //期盼设为半透明

               mcChessboard.alpha = .5;

               //根据玩家输赢展示不同的游戏结果

               if(side == mySide){

                      mcGameState.gotoAndStop("win");

               }

               else{

                      mcGameState.gotoAndStop("lose");

               }

        }

       //为数组排序的方法

        private function sortArray(arr):Object{

               var arrLen:int = arr.length;

               var ar:Array = [];

               for(var j=0;j<arrLen;j++){

                      ar[j] = arr[j];

               }

               //以数字方式对"val"字段进行排序

               ar.sortOn("val",Array.NUMERIC );                   

               return ar[ar.length-1];

        }

        //取得指定棋格的分数

        private function getScore(arr:Array,xp:int,yp:int,side:int):int{

               var s0:int = AnalysisLine(getXLine(arr,xp,yp,side),side);

               var s1:int = AnalysisLine(getYLine(arr,xp,yp,side),side);

               var s2:int = AnalysisLine(getXYLine(arr,xp,yp,side),side);                                                                                                                

               var s3:int = AnalysisLine(getYXLine(arr,xp,yp,side),side);                  

               return (s0 + s1 + s2 + s3);

        }    

        // -- 取得游戏中的一方在指定位置左右两边5格以内的状态

        private function getXLine(aposition:Array,xp:int,yp:int,side:int):Array{

               var arr:Array = [];

               var xs:int,ys:int,xe:int,ye:int;

               //起始位置

               xs = xp - 5>0 ? xp - 5:0;

               //结束位置

               xe = xp + 5>= gridnum?gridnum:xp + 5;

               for(var i:int=xs;i<=xe;i++){

                      if(i == xp)

                             arr.push(side);

                      else{

                             arr.push(aGridState[yp][i])

                      }                         

               }                  

               return arr;           

        }

        // | 取得游戏中的一方在指定位置上下两边5格以内的状态

        private function getYLine(aposition:Array,xp:int,yp:int,side:int):Array{

               var arr:Array = [];

               var xs:int,ys:int,xe:int,ye:int;

               //起始位置                                     

               ys = yp - 5>0 ? yp - 5:0;

               //结束位置

               ye = yp + 5>= gridnum?gridnum:yp + 5;

               for(var i:int=ys;i<ye;i++){

                      if(i == yp)

                             arr.push(side);

                      else{

                             arr.push(aposition[i][xp])

                      }

               }                  

               return arr;

        }

        // \ 取得游戏中的一方在指定位置左上右下两边5格以内的状态

        private function getXYLine(aposition:Array,xp:int,yp:int,side:int):Array{

               var arr:Array = [];

               var xs:int,ys:int,xe:int,ye:int;

               //起始位置

               xs = yp > xp ? 0 : xp - yp;

               ys = xp > yp ? 0 : yp - xp;

               //结束位置

               xe = gridnum - ys;

               ye = gridnum - xs;

               var pos:int;

               for(var i:int=0;i<(xe-xs<ye-ys?xe-xs:ye-ys);i++){                          

                             if(ys + i == yp && xs + i == xp){

                                    arr.push(side);

                                    pos = i;

                             }

                             else{

                                    arr.push(aposition[ys + i][ xs + i]);

                             }                                

               }

               arr = arr.slice(pos-4>0?pos-4:0,pos+5>arr.length?arr.length:pos+5);

               return arr;

        }

        // / 取得游戏中的一方在指定位置左下右上两边5格以内的状态

        private function getYXLine(aposition:Array,xp:int,yp:int,side:int):Array{

               var arr:Array = [];

               var xs:int,ys:int,xe:int,ye:int;

               var num:int = gridnum;

               var half:int = Math.ceil(gridnum/2);

               //起始位置

               xs = xp + yp < num?0:(xp + yp - num + 1);

               ys = xs;

               //结束位置

               xe = xp + yp >= num?num-1:(xp + yp);

               ye = xe;

               var pos:int;

               for(var i:int=0;i<(xp + yp>=num?2*num-xp-yp-1:xp+yp+1);i++){                           

                             if(ye - i == yp && xs + i == xp){

                                    arr.push(side);

                                    pos = i;

                             }

                             else

                                    arr.push(aposition[ye - i][ xs + i]);                       

               }

               arr = arr.slice(pos-4>0?pos-4:0,pos+5>arr.length?arr.length:pos+5);

               return arr;

        }

        //评估游戏中的一方在指定位置落子后某一方向可能取得的分值

        private function AnalysisLine(aline:Array,side:int):int{

               var otherside:int =  WHITE + BLACK - side;

               //以下注释中 *为本方棋子,o为对方棋子,_为空格

               // *****

               var five:String = (side * 11111).toString();

               // _****

               var four:String = "0" + (side * 1111).toString() + "0";

               // _***_

               var three:String = "0" + (side * 111).toString() + "0";

               // _**_

               var two:String = "0" + (side * 11).toString() + "0";

               // _*_*_

               var jtwo:String = "0" + (side * 101).toString() + "0";

               // ****_

               var lfour:String = otherside.toString() + (side * 1111).toString() + "0";

               // _****

               var rfour:String = "0" + (side * 1111).toString() + otherside.toString();

               // *_***

               var l_four:String = (side * 10111).toString();

               // ***_*

               var r_four:String = (side * 11101).toString();

               // o***_

               var lthree:String = otherside.toString() + (side * 111).toString() + "0";

               // _***o

               var rthree:String = "0" + (side * 111).toString() + otherside.toString();

               // o**_

               var ltwo:String = otherside.toString() + (side * 11).toString() + "0";

               // _**o

               var rtwo:String = "0" + (side * 11).toString() + otherside.toString();

               // ***_o

               var rfthree:String = (side * 111).toString() + "0" + otherside.toString();

               // o_***

               var lfthree:String = otherside.toString() + "0" + (side * 111).toString();

              

               var str:String = aline.join("");

               var res:int;

               if(str.indexOf(five)>=0){

                      res = FIVE;

                      if(side == otherSide)

                             res *=2;

               }

               else if(str.indexOf(four)>=0)

                      res = FOUR;

               else if(str.indexOf(three)>=0)

                      res = side!=mySide?THREE+4:THREE;

               else if(str.indexOf(two)>=0 || str.indexOf(jtwo)>=0 )

                      res = TWO;

               else if(str.indexOf(lfour)>=0 || str.indexOf(rfour)>=0 || str.indexOf(l_four)>=0 || str.indexOf(r_four)>=0)

                      res = SFOUR;

               else if(str.indexOf(lthree)>=0 || str.indexOf(rthree)>=0)

                      res = STHREE;

               else if(str.indexOf(ltwo)>=0 || str.indexOf(rtwo)>=0)

                      res = STWO;

               else if(str.indexOf(lfthree)>=0 || str.indexOf(rfthree)>=0)

                      res = FTHREE;

               else

                      res = 0;

                     

               return res;

        }           

        //开始游戏按钮触发的方法

        private function btnStart_Handler(e:MouseEvent):void{

               canPlay = true;

               if(mySide == WHITE){

                      AddChessman(Math.floor(gridnum/2),Math.floor(gridnum/2));

               }

               btnStart.visible = false;

        }

        //重玩一遍按钮触发的方法

        private function btnReplay_Handler(e:MouseEvent):void{

               mcGameState.visible = false;

               mcChessboard.alpha = 1;

               init();                  

               if(mySide == WHITE){

                      AddChessman(Math.floor(gridnum/2),Math.floor(gridnum/2));

               }

        }

        //选择棋子按钮触发的方法

        private function selectChessman(e:MouseEvent):void{

               if(canPlay){

                      mcSelectChessman.buttonMode = false;

                      return;

               }else{

                      mcSelectChessman.buttonMode = true;

                      mySide = otherSide;

                      otherSide = WHITE + BLACK - mySide;

                      if(mySide == WHITE){

                             mcSelectChessman.gotoAndStop("white");

                      }else{

                             mcSelectChessman.gotoAndStop("black");

                      }

                      crtSide = mySide;

               }

2创建棋子的类

package Classes{

import flash.display.MovieClip;

import flash.events.*;

public class Chessman extends MovieClip{

        private var inc:uint = 0;

        public var bPlayer:Boolean = false;

        public function Chessman(){                

               this.addEventListener(Event.ENTER_FRAME,twinkle);

        }

        public function twinkle(e:Event):void{              

               if(!bPlayer){

                      if(inc<15){

                             this.alpha = ((inc%5)/5) + .2;

                             inc ++;

                      }else{                        

                             this.removeEventListener(Event.ENTER_FRAME,twinkle);

                      }

               }

        }

}

}


 

第1章            五子棋游戏的实现和界面演示

 

 

玩家可以选择黑棋或者白棋,而来选择先走或者后走。

5.2判断输赢的界面

下棋输的界面

                   

下棋赢的局面。玩家可以用鼠标点击“再玩一遍”按钮来选择将继续游戏。


本论文研究的目标是在探索五子棋人机对战当中的算法,在算法详解,解决在开发过程中涉及的问题。

在本论文的理论研究过程中,经过了大量网络资料、文献的阅读和分析研究,主要有如下收获:

(1)    对人工智能算法有了初步了解。

2)对于用例图的使用有了一些了解,能够简单使用用例图来对软件中的工作流程进行规划。

3)对软件设计模式方面的经典理论进行了学习和探讨。

4)认真学习了软件工程相关知识,对以工程化的理念进行软件开发的实施步骤有了完整的认识。

5)对选用的软件开发工具进行了学习,通过flashas3.0语言对算法有了初步了解。

经过充分的理论研究后,在本论文的实践过程主要有如下收获:

1)严格按照软件开发中工程化的开发理念对软件进行了初期开发,在开发过程中对工程化开发理念实施的各个阶段形成了具体的认识,并在实施过程中体会到其益处。

2)对系统进行了需求分析,对系统的功能需求、客户需求、接口需求、性能需求作出了分析研究,在需求分析过程中掌握了各种需求分析工具的应用。

3)对面向对象的方法论进行了研究,并将其应用到本论文最终平台中各功能模块的实现,认识并掌握了面向对象的实现方法。

4)对简单的算法进行了研究,并将其应用到本论文中的各功能模块的实现。

 

本次研究主要针对五子棋的游戏性能进行了分析和研究,并在此基础上作出了系统实现。但由于自身知识及经验的局限性、主课题的研究性特性、本论文研究内容在主课题中的位置特点,使得整个研究过程仍不够完美,以理论性研究为主,最终的平台功能实现并不完善。虽初期系统已交付使用,但还需作更进一步的研究:

1)本次五子棋游戏只能进行人机对战,对玩家之间对战可以进行探讨。

2)本次游戏中电脑的下棋模式只有一种,无法针对不同层次玩家的要求改变下棋的难易程度。

3)本游戏的开发基于其运行环境及开发目的和成本的限制,对许多功能比如悔棋,

 

积分,排行榜,下棋时的游戏音乐等许多方面没有进行深入研究,游戏功能还有待完善。


 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验1 直线段的扫描转换 实验类型:设计实验类别:专业实验 实验目的 1. 通过实验,进一步理解直线段扫描转换的DDA算法、中点bresenham算法及bresenham算法的基本原理; 2. 掌握以上算法生成直线段的基本过程; 3. 通过编程,会在C/C++环境下完成用DDA算法、中点bresenham算法及bresenham算法对任意直线段的扫描转换。 实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用DDA算法中点bresenham算法及bresenham算法实现任意给定两点的直线段的绘制(直线宽度和线型可自定)。 实验步骤: 1、 复习有关算法的基本原理,明确实验目的和要求; 2、 依据算法思想,绘制程序流程图; 3、 设计程序界面,要求操作方便; 4、 用C/C++语言编写源程序并调试、执行; 5、 分析实验结果 6、 对程序设计过程中出现的问题进行分析与总结; 7、 打印源程序或把源程序以文件的形式提交; 8、 按格式要求完成实验报告。 实验报告要求: 1、 各种算法的基本原理; 2、 各算法的流程图 3、 实验结果及分析(比较三种算法的特点,界面插图并注明实验条件) 4、 实验总结(含问题分析及解决方法) 实验2 圆的扫描转换 实验类型:设计实验类别:专业实验 实验目的 1、 通过实验,进一步理解和掌握中点bresenham画圆算法的基本原理; 2、 掌握以上算法生成圆和圆弧的基本过程; 3、 掌握在C/C++环境下完成用中点bresenham算法圆或圆弧的绘制方法。 实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用中点(Besenham)算法实现圆或圆弧的绘制。 实验步骤 1. 复习有关圆的生成算法,明确实验目的和要求; 2. 依据算法思想,绘制程序流程图(注意圆弧生成时的输入条件); 3. 设计程序界面,要求操作方便; 4. 用C/C++语言编写源程序并调试、执行; 5. 分析实验结果 6. 对程序设计过程中出现的问题进行分析与总结; 7. 打印源程序或把源程序以文件的形式提交; 8. 按格式要求完成实验报告。 实验报告要求: 1. 分析算法的工作原理; 2. 画出算法的流程图 3. 实验结果及分析(比较圆与圆弧生成算法的不同) 4. 实验总结(含问题分析及解决方法) 实验3 多边形的区域填充 学时:2 实验类型:设计实验类别:专业实验 实验目的 1. 通过实验,进一步理解和掌握几种常用多边形填充算法的基本原理 2. 掌握多边形区域填充算法的基本过程 3. 掌握在C/C++环境下用多边形填充算法编程实现指定多边形的填充。 实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用种子填充算法和扫描线填充算法等任意两种算法实现指定多边形的区域填充。 实验步骤 1. 复习有关算法,明确实验目的和要求; 2. 依据算法思想,绘制程序流程图(指定填充多边形); 3. 设计程序界面,要求操作方便; 4. 用C/C++语言编写源程序并调试、执行(最好能用动画显示填充过程); 5. 分析实验结果 6. 对程序设计过程中出现的问题进行分析与总结; 7. 打印源程序或把源程序以文件的形式提交; 8. 按格式要求完成实验报告。 实验报告要求: 1. 分析算法的工作原理; 2. 画出算法的流程图 3. 实验结果及分析(比较两种算法的不同) 4. 实验总结(含问题分析及解决方法)
需求分析是软件工程中的一个重要阶段,它主要用于识别和理解用户的需求,并将其转化为可执行的软件规范。需求分析包括以下几个步骤: 1. 需求收集:通过与用户、利益相关者的沟通和访谈,收集关于系统需求的信息,包括功能需求、非功能需求、用户需求等。 2. 需求分析与建模:根据收集到的需求信息,进行需求分析和建模。这一步骤可以使用各种技术和工具,如用例图、活动图、状态图等,来帮助理解和表示需求。 3. 需求验证:对收集到的需求进行验证,确保其准确、一致和完整。可以通过与用户的反馈、原型验证、模拟测试等方法来验证需求。 概要设计是在需求分析之后进行的一项工作,它主要用于确定软件系统的整体结构和组成部分。概要设计包括以下几个方面: 1. 系统结构设计:确定系统的整体结构和模块之间的关系,包括模块划分、接口设计等。 2. 数据设计设计系统中需要使用的数据结构和数据库模型,包括数据表设计、数据流程设计等。 3. 接口设计设计系统与外部系统或模块之间的接口,包括输入输出接口、API设计等。 4. 系统行为设计设计系统的主要功能和行为,包括流程设计、状态转换设计等。 需求分析和概要设计是软件开发过程中的关键步骤,它们为后续的详细设计和实现提供了基础和指导。通过有效的需求分析和概要设计,可以确保软件系统能够满足用户的需求,并具备良好的可扩展性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值