(图片来源网络,侵删)
文档编号:项目名称 – 版本项目名称课程实践报告书制订人:学 号:2005年 5月 14日文档变更历史记录 序号变更日期变更人员变更内容详情描述版本12001/11/1张三创建1.022001/11/15王五增加了需求描述(见章节)1.1目录目录331、引言441.1 编写目的441.2 读者对象441.3 软件项目概述441.4 文档概述441.5 定义441.6 参考资料442、任务概述552.1目标552.2软件的开发和运行环境552.3 用户特征552.4 假设与约束552.5 进度要求552.6验收要求663、功能需求描述773.1 子功能1717173.2 子功能272727…774、界面要求775、测试方案776、功能设计886.1类的关系描述886.2类的设计887、使用指南888、维护接口889、总结881、引言1.1 编写目的本文档编写的目的是为了说明我所编写的五子棋软件具有的基本功能及其实现方法以及作为用户操作手册,方便用户使用我所编写的五子棋软件。1.2 读者对象本文档中关于具体实现部分涉及到C++面向对象编程技术和数据结构中有关模式匹配的知识,对于有这方面知识的用户可以读读,如果关于实现有什么建议或意见,可以跟我联系,电子邮箱 mash06@sina.com。而对于一般的用户则完全可以跳过这部分内容,直接阅读有关操作的使用说明。1.3 软件项目概述简要说明关于本软件项目的:项目名称:实用五子棋双人对战程序编写简称:五子棋项目代号:200306020034软件项目的大致功能和性能要求基本功能如下:1.记录游戏双方的落子过程,允许悔棋;2.实现保存棋谱和根据棋谱复盘的功能;3.判断双方输赢,先走出五子连珠的一方赢;4.响应用户鼠标消息,并显示棋盘信息;5.先下者落子时不允许走禁手。1.4 文档概述简要说明本文档的大致内容及其组织结构1.5 定义模式匹配:在一个字符串中寻找一给定字符串,如果存在,返回在其中的起始位置。否则返回-1。1.6 参考资料以列表或排序的方式给出重要的参考资料的名称、作者、单位、出版日期等信息。[1]《数据结构 C++语言描述(第二版)》熊岳山 陈怀义国防科技大学出版社 2004年1月2、任务概述2.1目标这个软件的开发主要是为了使我自己更好地掌握C++程序设计技能,特别是目前常用的C++程序设计环境,Visual C++6.0,通过课题实践的方式让我初步掌握C++和MFC编程的有关知识,为学习后序开设的算法设计与分析、数据库、软件工程等课程打下必要的基础。2.2软件的开发和运行环境借助Microsoft visual C++6.0编译器,在各种电脑上可运行,硬件要求能运行Microsoft visual C++6.0即可。2.3 用户特征用户主要是对五子棋有一定爱好的人或者对编程感兴趣的人士。而维护人员则要求掌握Microsoft visual C++6.0语言编程,熟悉MFC的各种操作,并且具有一定数据结构知识的人。2.4 假设与约束软件开发要求8周内完成,经费为0.功能包括能够记录游戏双方的落子过程,允许悔棋;实现保存棋谱和根据棋谱复盘的功能;判断双方输赢,先走出五子连珠的一方赢;响应用户鼠标消息,并显示棋盘信息;判断黑棋落子时不允许走禁手.2.5 进度要求描述目标软件系统的开发进度2.6验收要求要求无错误能正常运行,达到要求,并实现所要求功能。3、功能需求描述功能要求:正常落棋子,不会覆盖已有棋子。悔棋,并记录悔棋过程,即悔棋数目和位置。复盘,记录棋盘棋子的颜色,数目,位置,并能够一步步恢复棋盘,即重演落子过程。d) 对黑棋能够正确判断禁手。e)判断黑白两方的胜负。F)实现棋盘的保存。即在停止运行程序一段时间后能够接着以前下的接着下。3.1 子功能1打印棋盘棋盘是1919的方格棋盘,其中在(4,4),(4,16),(16,4),(16,16)处各打印一个小黑点。棋盘背景色为黄色的类似桌面颜色。3.2 子功能2下棋记录双方落子的过程,黑方先下,而且先下者必须落子(10,10) 位置。下棋时为响应鼠标左键的点击。当鼠标图标位于棋盘范围内时,每点一下,落子一个。双方交替落子3.3 子功能3悔棋当一方点击位于工具栏中的悔棋图标时,将会进入悔棋界面,每点击一下,悔掉最近落子的一步,直到用户再次在棋盘界面内点击鼠标左键开始下棋为止。3.4 子功能4复盘该功能用于当一盘棋局结束后,重现双方下棋落子以及悔棋的过程。该功能的控制位于控制栏的下棋菜单中,点击该菜单,在其下拉菜单中选择复盘,将进入复盘界面,将重现从开始到最后的落子或者悔棋过程,响应为鼠标点击,每点击鼠标一下,落子一下或者悔棋一步。当复盘过程完成后,会弹出提示对话框,告诉用户复盘过程已完成。3.5 子功能5保存用于当用户在下棋过程中由于什么意外的原因要离开现场,而又想等会回来接着刚才的棋局继续下时,此时用户可以点击下棋菜单的子菜单中的保存。当用户点击此项功能后,程序将会保存当前的棋盘,也将保存以前的落子过程。当用户下次再运行五子棋程序时,打印出来的棋盘是刚才下过的棋盘,用户可以接着刚才的棋盘继续下。4、界面要求描述用户对目标软件系统的界面要求,可在此处描述目标软件系统的原型。5、测试方案1:运行程序,棋盘正确与否。2:画棋子时,是否为先黑后白,并且不同的棋子不会发生重叠现象。3:能否正确判断五子连珠,并提示游戏胜利方同时结束游戏。4:能否正确实现悔棋,撤消,复盘及重下等功能。5:能否正确判断黑子禁手,禁手包括下面几种情况。五子连珠的禁手包括以下几种情况:三三禁手 三三禁手 四四禁手四四禁手 四四禁手 四四禁手四三三禁手 长连禁手6、功能设计6.1类的关系描述struct POINTME用于记录下棋过程的点类。class chess 为棋盘类。其中包括记录下棋过程的POINTME 类型数组Process[800]和记录棋盘当前状态的ChessBoard[19][19]数组。class CWzqView为用于输出棋盘信息的类。用于打印棋盘和落子,以及显示相关的悔棋过程和提供一些辅助性的对话框,用来实现人机交流。class CWzqDoc 为用于实现棋盘的一些基本属性的类。在该类中规定了棋盘的大小,为1919大小。struct POINTME 包含于class chess内,用于其中来记录下棋落子的过程,在 CWzqView.cpp 中声明了一个chess类对象C 用于下棋。Class CWzqView只是用于 对class chess进行操作,使其能够进行人机交互。class CWzqDoc 用于对class CWzqView的一些基本属性进行描述,如打印棋盘的方格数大小。6.2类的设计struct POINTME{CPoint point; //落棋点的坐标int flag; //该棋的类别:-1,未下过;0,现在有子;2,以前下过,现在已悔棋int color; //0,黑棋;1,白棋;};定义struct POINTME 的作用是为了更好的记录下棋和悔棋的过程以便于实现复盘和悔棋的功能。CPoint point记录落棋点的坐标;int flag用来记录point点的状态,其不同数值分别表示:-1,point点未下过;0,point点现在有子;2,point点以前下过,现在已悔棋。int color 用于记录当point点有子或者以前下过子现在已经悔棋了,该子的颜色。其不同的颜色分别表示: 0,黑棋;1,白棋;Class chess :其具体属性包括:public:int Ccount;//记录包括悔棋在内的所有步数int Rcount;//记录复盘过程中走的步数POINTME Process[800];//记录下棋的过程int ChessBoard[19][19]; //3,未下;0,黑棋;1,白棋;int DChessBoard[19][19]; //棋盘的表示的拷贝int lastColor;//最后一个棋的颜色;bool Recover; //标志是否处于复盘状态private:char T[4][10];//分别用于存储对四个不同的方向进行扫描时的结果char BFive; //黑五连时的字符串00000char WFive; //白五连时的字符串11111char Four; //活四char SFour[5];//五种冲四char Three[3];//三种活三char Six;//六腐char Lian;//长联FILE f;//文件指针,用于保存首先,我有必要说明我的棋盘存储方式。我用到int ChessBoard[19][19]来存储棋盘信息,其中ChessBoard[i][j]的不同数值来对应表示棋盘上(i,j)点的棋子信息。数值为3,表示该点未下子;为0,表示该点下了黑棋;为1,表示该点下了白棋。之所以用3来表示该点未落子,是为了更方便地实现后面的字符串模式匹配算法。为了实现对棋盘信息的有效保护,我设置了int DChessBoard[19][19]数组用来做为 int ChessBoard[19][19]的拷贝,主要用于可能修改需要修改棋盘的场合。POINTME Process[800]为用来记录双方下棋落子的过程,Process[]数组的下标即表示第几步。设置这个数组主要是为了方便复盘,复盘时只需从头到尾读取这个数组,根据其中的不同信息做出不同的打印动作即可。每次下棋落子或悔棋后都在Process[]数组中增加一项。int Ccount用于记录包括悔棋在内的所有步数int Rcount用于记录复盘过程中走的步数int lastColor;用来记录最后一个棋的颜色;bool Recover用来标志是否处于复盘状态下面分别解释私有数据中字符串的功能:这里是我最为我的程序感到骄傲的部分。它成功的运用了模式匹配的算法思想解决了禁手和胜负的判断问题。char T[4][10]用于存储void Scan(CPoint t);每落一子即对其四个不同的方向进行扫描时所得的结果。在胜负的判断和禁手的判断中我用到了字符串模式匹配的思想。即用char BFive 来存储黑五连时的字符串,字符串中的具体内容是00000;用char WFive来存储白五连时的字符串,字符串中的具体内容是11111;用char Four来存储黑子形成活四时的情形,字符串中的具体内容是300003;用char SFour[5]来存储五种不同的冲四,其内存储的内容分别为:SFour[0]="100003";SFour[1]="300001";SFour[2]="00030";SFour[3]="00300";SFour[4]="03000";用char Three[3]来存储三种不同的活三,其内存储的内容分别为:Three[0]="30003";Three[1]="300303";Three[2]="303003";用char Six来存储六腐,其内存储的内容为: Six="1300031";用char Lian来存储长联禁手,具体内容为:Lian="000000";FILE f是文件指针,用于指向保存时用的文件。基本方法:chess();virtual ~chess();bool IsPre(CPoint temp);//判断是否是以前下过的点void Scan(CPoint t);//落子时的扫描函数,每落一子即对其四个不同的方向进行扫描int Judge(CPoint t); //判断胜负int Prohibit(CPoint t);//判断禁手int Find ( char object, char target);//KMP模式匹配void Restore();//保存函数Next (char s, int next);//KMP模式匹配chess()和virtual ~chess()分别为class chess 的构造函数和析构函数。在 chess()函数内首先判断是处于开始状态还是处于保存过棋盘后继续状态,具体判断是通过看文件指针f是否为NULL来判断。当其为NULL时初始化棋盘时,按照没下过棋来初始化。如果其不为NULL,则从文件中读取相应的数据来初始化。bool IsPre(CPoint temp)是用来判断是否是以前下过的点的函数,如果是则返回true ,否则返回false.void Scan(CPoint t),落子时的扫描函数,每落一子即对其四个不同的方向进行扫描。每落子的四个不同方向进行扫描,扫描以落子点为中心的前后四个点的状态。扫描得到的结果存储在char T[4][10]数组。int Judge(CPoint t),判断胜负函数,每落一子通过对其调用Scan(CPoint t)函数扫描其四个方向,将其结果通过模式匹配与char BFive和char WFive进行匹配,如果成功,即为有一方胜利。返回1,否则返回-1。int Prohibit(CPoint t),判断禁手函数。共能判断几种简单的禁手,而对于复杂的嵌套禁手将无能为力,这是我这个程序的不足之处。几中简单的禁手分别为:五子连珠的禁手包括以下几种情况:三三禁手 三三禁手 四四禁手四四禁手 四四禁手 四四禁手四三三禁手 长连禁手void Restore(),保存函数。在用户选择保存后调用此函数,将当前棋盘的内容和下子过程记录进文件指针FILE f所指文件。其判断原理与判断胜负一样都是通过对黑方落子的四个方向进行扫描,将其结果存储于char T[4][10],然后通过模式匹配寻找在其四个方向形成了一些什么样的子力。对于形成双活三,双活四,一活四一冲四,长连的判为禁手,同时也注意到一些不是禁手的容易误判,例如六腐。int Find ( char object, char target),KMP模式匹配函数,见参考书籍[1]。Next (char s, int next),KMP模式匹配中next[]数组产生函数,见参考书籍[1]。class CWzqDoc : public CDocument在其中加入如下操作说明:public:int nGetBoardRowNum() const;void vSetBoardRowNum(int nRows);CPoint ptGetPiecePos() const;void vSetPiecePos(CPoint piecePos);int nGetBoardRowNum,返回BoardRowNum的大小,即返回棋盘的大小。void vSetBoardRowNum(int nRows),设置BoardRowNum的大小,即棋盘的大小。CPoint ptGetPiecePos() ,返回当前点的坐标,函数返回值类型是VC内部定义的类型CPoint.表示棋盘上点的坐标。void vSetPiecePos(CPoint piecePos),设置当前点的坐标为CPoint piecePos的点。class CWzqView : public CView加入如下操作说明:protected:void vDrawPiece(POINTME temp, CDC pDC);CPoint ptConvertVP2BP(CPoint pointView) const;CPoint ptConvertBP2VP(CPoint pointView) const;CPoint ptConvertVP2BP(int x, int y) const;CPoint ptConvertBP2VP(int x, int y) const;BOOL bPointInBoard(CPoint pointView, int nBoardRowNum) const;在这里还对系统的两个重要的函数进行了修改。其中一个是virtual void OnDraw(CDC pDC),在它里面加入了有关绘制棋盘和下棋过程的实现。另一个是afx_msg void OnLButtonDown(UINT nFlags, CPoint point),使其能够在下棋过程中响应鼠标的左键点击和在复盘过程中响应鼠标的点击。void vDrawPiece(POINTME temp, CDC pDC),在POINTME temp点画图,根据temp 所包含的不同信息,进行不同的动作,如画黑棋,白棋和悔棋,(即画与背景颜色一样的棋子,然后再在刚才画过的区域画两条线)CPoint ptConvertVP2BP(CPoint pointView) ,工具函数。把视频上的象素点转变成为棋盘上的点。CPoint ptConvertBP2VP(CPoint pointView) ,工具函数。将棋盘上的点转变成视频上的象素点。CPoint ptConvertVP2BP(int x, int y) ,重载的工具函数。将视频上(x,y)CPoint ptConvertBP2VP(int x, int y) ,重载的工具函数。将棋盘上的点转变成视频上的象素点。BOOL bPointInBoard(CPoint pointView, int nBoardRowNum) ,判断CPoint pointView 是否在棋盘内部的函数。7、使用指南软件无须安装,只要求安装有Microsoft visual C++6.0即可,使用时,运行源程序即可。菜单中,除下棋菜单外,其它菜单无须或者无法使用。下棋菜单中的悔棋,允许下棋者悔棋,如果悔棋错误,并可点击撤消菜单撤消悔棋,重下菜单重新开始一局五子棋对战,复盘菜单根据棋盘记录恢复棋盘。8、维护接口介绍软件进一步维护的方法,描述对现有系统进行改进和维护的相关模块,介绍维护的软件接口。9、总结通过本次实践使我MFC编程有了一定的认识,提高了我对于C++面向对象程序设计功能优点的认识度。由于是第一次接触到MFC编程,所以有很多概念不是很明白,在进行实践活动的过程中,我又自学了一些关于MFC编程的书籍,了解了进行MFC编程的一些深层次的问题,比如,对于MFC主要是一个消息驱动编程思想的认识。在自学的过程中,进一步提高了我寻找信息,和筛选信息的能力。也同时提高了我的自学能力。但是在本次实践活动中,由于主观和客观的各种因素,我没能完成人机对战和网络对战的编写,自己感觉很是遗憾。不过,我还是感到庆幸的是,通过这次实践活动,把我带进MFC编程这个美丽的,充满魅力的殿堂。师傅领进门,修行在个人。在这次实践活动结束以后,就完全是修行在个人了,我感谢给我指明方向,带我进入这个编程的殿堂的人,我也将在这个神奇,美丽的殿堂里慢慢学习。事在人为。
0 评论