资源描述
五子棋游戏实验报告课程名称计算机程序设计(VB)学 号 姓 名 班 级 提交时间五子棋软件设计一、实验目的1通过五子棋软件设计或者自拟题目设计,巩固本课程所学的各个章节重点知识,自拟题目的同学需尽早向教师提出自己的想法及设计方案。2通过开发一个较大的系统,增强软件开发能力。3通过调试系统,增强逻辑思维能力。二、实验内容1 基本要求:( 1 )输入两个对手名字,然后进入游戏界面。(2)用鼠标点击的方式在棋盘上摆放棋子,黑白交替。 (棋盘 15*15)( 3 )可以悔棋。( 4 )五子连在一起的时候能判断胜利,并且显示出胜利者的名字。( 5 )能够将棋局的结果保存,保存该棋局结束的状态、对手名字、 棋局名字(棋局名字在保存时由用户在相应的界面下添入) (此功能要求用数据库和文件两种技术实现) 。( 6 )棋局能够恢复,即重新打开,打开后出现棋局结束的状态、对手名字(此功能要求用数据库和文件两种技术实现) 。2其它要求:( 1 )界面友好、漂亮。( 2 )程序尽可能无bug 。( 3 ) 程序健壮性强, 基本上达到无论用户如何操作,软件都不出错,都有相应的处理方法。3设计步骤( 1 )首先做界面界面包括几个窗体,窗体上有相应的控件。因为需要画棋盘,所以必须有图形容器,这里用 picturebox 框第一个窗体是登陆界面, 因为玩家姓名需要在程序中不断变换, 因此需要将玩家名定义成两个变量,又因为这两个变量在几个窗体中都用到,所以在模块中定义为全局变量当五子棋主界面启动之后,首先系统要自动绘制棋盘。思路: 用直线绘制棋盘直线是由点绘制的-每个点都有坐标 改变坐标系为用户坐标系用户坐标系的定义要在窗体启动时实现。( 2 )坐标系的两个顶点坐标的确定?考虑到五子棋15*15 ,确定棋盘坐标系顶点为 (-8, 8) , (8, -8)( 3 )棋子的绘制与存储棋子的绘制用实心圆模式,颜色为黑色及白色两种。棋子在内存中的存储方式: 因为表示各个棋子的数据类型都相同, 所以考虑用数组存储, 因为棋盘是二维的,因此棋子用二维数组 a 存储。 a(i,j) 表示用户坐标( i,j )的棋子状态, 0 表 示此处无棋子, 1 表示此处为黑子, 2 表示此处为白子,下棋初始时,棋盘所有位置的初始状态都为 0( 4 )下棋子的步骤鼠标点击棋盘交叉点附近的位置,系统应实现自动识别鼠标点击位置附近的交叉点解决方法: 坐标系的变换已经将棋盘交叉点坐标整数化, 因此系统所需要实现的功能即是将鼠标所点击的位置坐标化为整数即可,例如将( 6.2, -5.3)变成( 6, -5) 。在交叉点上交替下黑白棋子。解决方法:定义一个逻辑数据类型变量blackwhite ,该变量的值为真时下黑子,为假时下白子,每下一个棋子,该变量的值都要取反( NOT ) 。判断赢棋每次下子时都必须进行赢棋判断, 判断的依据是5 个子按照横线、 竖线或斜线连成一行。解决方法:2 层循环。当有一方胜利时,棋局结束,此时在棋盘上继续点击,将不再下棋。解决方法:设置一个逻辑变量wuziqi , 其值为真时说明棋局没有结束, 可以在棋盘上放棋子,该值为假时,说明该棋局结束,不能放棋子。( 6 )五子棋保存棋局思路:保存棋局的功能即把内存中与棋局相关的数据(棋局名称、棋子位置、棋子颜色、棋局状态(即棋局是否结束) )存入外存中,以便以后能够恢复棋局。保存的实现用两种技术实现:文件和数据库。采用数据库技术实现棋局保存:数据库设计:数据表字段:棋局名、 x 坐标、 y 坐标、该点状态值、下棋状态。每条记录表示棋盘上一个存储的点的信息。要实现用数据库保存数据,就必须使程序连接到数据库上,这里用的是data 控件,通过在程序中对 data 控件属性的设置来连接数据库、数据表。首先判断如果输入的棋局名和当前记录的棋局名相等, 说明表中有输入棋局名对应的棋局信息,将其删除,判断过程是将用户输入的棋局名(字符串)从记录集(即表)的棋局字段顶端至下逐一比较在表的最后,也就是最后一条记录后加上新保存棋局的各条记录因为棋盘上空点居多,大部分点的信息为 0 ,因此只需保存有棋子的点的信息用文件技术进行棋局保存,思路相同。( 7 )五子棋恢复棋局思路:首先从数据库文件中找到要恢复棋局的数据(即曾经保存的数据) ,然后把这些数据赋值给内存中相应的数组或者变量中, 按照这些数据重新绘制棋盘和棋子, 即完成了对棋局的恢复。窗体启动事件应该完成的事情:组合框中应该显示曾经保存的棋局名。 因为每次保存棋局时, 都是将棋局所有棋子的记录添加在表的最后, 因此表中关于棋局名的记录只能是类似于aaabbbbccccc 的形式, 而不可能是abbcacc 的形式,根据这个特点编程序取出表中不同的棋局名。具体算法:用一个字符串变量strfile 初始值为空, 从表的顶端向下依次移动记录指针, 如果当前记录的棋局名字段和 strfile 不相等, 说明进入另一个棋局的记录中, 将该棋局记录的棋局名赋值给strfile ,并加入到组合框中,一直到表中最后一个记录因为要从数据库中取出相关数据到 a 数组中,因此要将a 数组所有数据清零。要建立一个data 控件,与数据库连接起来,而后识别棋局(即表中的棋局名字段与在列表框中选择的棋局名比较) ,将数据库该棋局中所有信息都赋值给a 数组及相关变量。刚才仅仅是数据的恢复, 即将数据库中已经保存过的数据恢复到内存中, 下一步应该根据内存中的数据重新绘制棋盘以及棋子。重新绘制棋盘是独立的一块功能,因此考虑用全局子过程来实现,该子过程定义在模块中。思路如下:清屏绘制棋盘根据 a 数组中的每一项的两个下标来决定绘制棋子的位置, 根据每一项的值是 1 还是 2 来决定在该位置绘制何颜色的棋子。决定该黑白方走的blackwhite 变量当时没有保存,可以采用在数据库中保存的方式来解决,本例中解决方法是通过数黑白棋子个数来决定恢复棋局后该谁走的。因此设置了一个变量做计数器,每走一步棋计数器的值加一。用文件技术实现棋局恢复,思路相同。( 8 )悔棋悔一步棋: 用几个变量来表示关于一步棋的几个信息, 每次下子都将该子的信息赋值给那几个变量,悔一步棋即将那几个变量所表示的点的 a 数组信息清零。而后调用paint ()过程重画。以上是教师带着学生完成的软件功能。遗留问题:保存棋手姓名和棋局名并在恢复棋局的时候显示。 (需要同学们自己完成)思路:在数据表中多建立两个字段,分别表示两个棋手姓名,同其它数据的保存类似。三、设计日期十二月四、完成日期十二月五、实验体会其实,一开始学习 vb 我就对它不抱有一定的热情,可能是因为要用到计算机以及编程问题,当时一想到有代码,就会无比的苦恼,但是为了让这门课顺利通过,我还是怀着一颗必须要学的心情。 起初,我对待这门新课程和其他课程一样,保持着必须认真听讲的决心。但是由于理论课太过枯燥,没学几次,我就败下阵来,开始有一节没一节的听,但是心里还是存有愧疚, 就得自己不该这样懒惰, 所以总是坐在前边几排座位上, 逼着自己一定要学些什么,这总归要比坐在后边效果要好一些。在学了这半学期 vb 之后,我同样有了一些体会,虽然不会比创新程序的同学深刻, 但是也让我相信了, 起码在老师他自己的课堂上, 他讲的要点都是对的。1、一定要认真听讲做笔记,这是提高效率最快的方法,就像老师说的。有了上机课, 我才能真正懂得听课的重要性, 其实有些课件虽然老师为了学生能够及时的进行自我复习传上去一些,但有些东西终归是老师上课讲的,而并没有写入课件的。所以,当真正自己写的时候,一遍一遍的被程序提示出错,内心其实很着急,因为老师只有一个,而且也不会围着你团团转, 所以这时候, 请教同学是唯一的方法, 但是这唯一的方法也不是时时都能发挥作用, 同学也有不会, 还是需要老师。其实我知道, 大部分的问题都是上课老师已经讲过的, 只是自己没听。 或者是一知半解, 经常写丢一些重要程序, 导致程序一直无法运行。比如我经常把退出子过程exit sub 弄丢,自己当时没觉得它很重要,虽然老师讲过如果没有这个,后边的程序会很麻烦。当时,我也只是那么一听,没在意,后来编程黑白子竖方向赢棋时没把它加上, 之后麻烦就出现了, 我的黑白子一直都没法完成竖方向赢棋总是有一个方向没法判断, 起初老师告诉我看看是否有算法上的错误, 但是, 我找了一节多课 (我承认我这个人太固执,必须要知道为什么错了,才会做下一步) ,我觉得我的算法一定没问题,但是不明白为什么错,后来在读别人的程序时,才发现是我的 exit sub 没写,造成的,只有退出我上一个的子过程, 这个过程才能正常运行。 所以可见没听老师的话, 是多么可怕,尤其还是在我也没听他讲课的前提下根本不懂代码意思,乱删改造成的后果。 所以,不管是在哪里,学知识是对任何事情在打基础。做每一步都要问一句问什么,凡是都有原因。2、学会独立思考,多问自己为什么,求帮助是下策在最初的的上机试验里, 我总会问老师一些我自己可以解决的问题, 自己不愿动脑想, 希望以最快捷的方式,获得最佳的结果。但是,往往会被老师教育一下,因为在其中,有一半是拼写错误,而自己没注意,另一半是写程序时不够完整 (认真说起来是根本没怎么想,只是将课上抄录下来的不完整笔记,凭借自己的主观意愿,编写的程序,不问为什么) 。其实后来想一想,确实是自己的问题,既耽误自己时间,也耽误老师时间。 这些程序老师只是给一个思路, 教你如何编写程序, 但是完整的需要自己来做,这些都需要弄清思路, 才会懂得我需要什么, 从而编写出什么, 这样犯错几率才会大大减少。 这也是锻炼自己思路逻辑性的时候, 也是老师让我们学的地方。只是当时没有听进去。 就像老师说的,只有这样才能将程序融为自己的,真正有能力去编自己想要边的程序。3、任何新鲜的事物都需要一个熟悉的过程,凡是要趁热打铁,效率才会高。其实, 这也是老师经常说的,可我们总是在做错事之后, 才会想起来, 原来某某某说的话是多么的对,但是总是忽略它事前的作用。我确实每次上完课,笔记连翻都不翻, 到真正上机的时候才会开始琢磨这个程序的意思,所以每一次的上机,我的速度都是比别人慢好多,而且尤其是笔记也没有记得很全的时候(也没有及时的补) ,上机时间都不够我完成上次所讲的程序的。所以会很后悔,没有好好听讲,没有好好记笔记、补笔记,造成了效率低下的局面。所以,凡事都要趁热打铁,才会尽快吸收。4、 任何事情都不是一气呵成, 事先的计划会是你事半功倍, 而实践是检验真理的唯一标准,程序亦是如此。这是我这两天在研究程序为什么这么写的原因时, 才开始领悟到的。 这一点老师也有可能说过。我在抛开老师所编写的五子棋的程序下,想通过自己的思考,把五子棋的思路捋顺,所以开始自己画结构图 (真正开始有这种想法的是在我看到老师给我们展示的他的往届同学做贪吃蛇的心得中,才发觉重要性) 。一开始我花了一个很短的一段时间,画出一个我自认为很满意思路图, 但是当我在重新用一些数去实验, 当我再对比我写的图与老师编写的程序有何不同的时候,就会发现,有很多漏洞。比如,我想到了有下棋,但没有想到下棋前要清屏,防止程序之前有任何痕迹, 防止出错;还有我想到了下棋之后要判断赢棋,但是当我到赢棋的那一步思路, 我才想到, 要判断赢棋, 就必须有五个相同颜色的子连一起, 那么在这之前我就要加上关于数组的赋值,来代表每一种颜色的棋子,从而构造if 条件语句,完成应其目的等等。其实这些都不是我一开始做程序就想到的,只有当按照计划实施的过程中,才能验证思路的正确性, 才能知道自己的思路与逻辑缺陷在哪里, 从而弥补不足。 这也是将自己的逻辑思维进一步完善的过程,也是老师想让我们得到的东西。所以,通过这次的课程, 我能体会到老师的良苦用心, 也感谢老师一直不厌倦的一遍遍教 我们,一遍遍告诉我们不愿意听的忠言。我会将我从这里学到的态度,以及做事的思维方式, 运用到其他事情上,哪怕是一点点,也会让我的效率比以往更有提高。六、全部界面和代码Form 1Private Sub Command1_Click()If Trim(Textl.Text) = Or Trim(Text2.Text) = ThenMsgBox 请输入玩家姓名End IfIf Trim(Text1.Text) = Trim(Text2.Text) ThenMsgBox 不能输入相同姓名!Exit SubEnd Ifb = Text1.Textw = Text2.TextForm2.ShowUnload MeEnd SubForm 2打开d同文件里万年到T才毋毋破桂接保存快周h月已保存据局升必游戒41保存在(1):1我的文若生另存为文件名QJ)保存类型注):我最近的文档保存棋局文件打开棋局丈件O里面该白方Tcxt2走Q91 Mobile二)360jx FilesjBaiduFlayerScreenshot iDoynloftdz口NY Sina FilesLnRonRen口Tencent FilesXL-Android-Asi slant*Youku Fils口暴风分码口美困国库 二图片收藏 啊我的说嫉三我的音乐“ 5243n2b2U的 1,侬 C48f8c5494f 三J d033b9014a90f6C保存童)取消Dim m As IntegerDim n As IntegerDim i As IntegerDim j As IntegerPrivate Sub Form_Load()Form2.Picture1.Scale (-8, 8)-(8, -8)End SubPrivate Sub 开始游戏 _Click()Picture1.ClsFor i = -7 To 7Picture1.Line (-7, i)-(7, i), QBColor(0)Picture1.Line (i, -7)-(i, 7), QBColor(0)NextFor i = -11 To 11For j = -11 To 11a(i, j) = 0NextNextLabel1.Caption = 该黑方 + b + 走blackwhite = Truewuziqi = TrueEnd IfEnd SubPrivate Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)m = CInt(X)n = CInt(Y)If CInt(X) = -7 And CInt(X) = 7 And CInt(Y) = -7 And wuziqi = TrueThenPicture1.FillStyle = 0If blackwhite = True And a(m, n) = 0 ThenPicture1.FillColor = QBColor(0)Picture1.Circle (m, n), 0.3, QBColor(0)a(m, n) = 1Label1.Caption = 该白方 + w + 走blackwhite = FalseEnd IfIf blackwhite = False And a(m, n) = 0 ThenPicture1.FillColor = QBColor(15)Picture1.Circle (m, n), 0.3, QBColor(15)a(m, n) = 2Label1.Caption = 该黑方 + b + 走blackwhite = TrueFor i = m - 4 To mIf a(i, n) = 1 And a(i + 1, n) = 1 And a(i + 2, n) = 1 And a(i + 3, n) = 1 And a(i + 4, n) = 1 ThenMsgBox 黑方胜利! wuziqi = FalseExit SubEnd IfIf a(i, n) = 2 And a(i + 1, n) = 2 And a(i + 2, n) = 2 And a(i + 3, n) = 2 And a(i + 4, n) = 2 ThenMsgBox 白方胜利! wuziqi = FalseExit SubEnd IfNextFor j = n - 4 To nIf a(m, j) = 1 And a(m, j + 1) = 1 And a(m, j + 2) = 1 And a(m, j + 3) = 1 And a(m, j + 4) = 1ThenMsgBox 黑方胜利! wuziqi = FalseExit SubEnd IfIf a(m, j) = 2 And a(m, j + 1) = 2 And a(m, j + 2) = 2 And a(m, j + 3) = 2 And a(m, j + 4) = 2ThenMsgBox 白方胜利! wuziqi = FalseExit SubEnd IfNextFor i = 4 To 0 Step -1If a(m - i, n + i) = 1 And a(m - i + 1, n + i - 1) = 1 And a(m - i + 2, n + i - 2) = 1 And a(m - i + 3, n + i - 3) = 1 And a(m - i + 4, n + i - 4) = 1 ThenMsgBox 黑方胜利! wuziqi = FalseExit SubEnd IfIf a(m - i, n + i) = 2 And a(m - i + 1, n + i - 1) = 2 And a(m - i + 2, n + i - 2) = 2 And a(m - i + 3, n + i - 3) = 2 And a(m - i + 4, n + i - 4) = 2 ThenMsgBox 白方胜利! wuziqi = FalseExit SubEnd IfNextFor i = 4 To 0 Step -1If a(m + i, n + i) = 1 And a(m + i - 1, n + i - 1) = 1 And a(m + i - 2, n + i - 2) = 1 And a(m + i - 3, n + i - 3) = 1 And a(m + i - 4, n + i - 4) = 1 ThenMsgBox 黑方胜利! wuziqi = FalseExit SubIf a(m + i, n + i) = 2 And a(m + i - 1, n + i - 1) = 2 And a(m + i - 2, n + i - 2) = 2 And a(m + i - 3, n + i - 3) = 2 And a(m + i - 4, n + i - 4) = 2 ThenMsgBox 白方胜利! wuziqi = FalseExit SubEnd IfNextEnd IfEnd SubPrivate Sub 保存棋局 _Click()Form3.ShowEnd SubPrivate Sub 打开已保存棋局_Click()Form4.ShowEnd SubPrivate Sub 悔棋 _Click()If wuziqi = True Thena(m, n) = 0Call paintEnd IfEnd SubPrivate Sub 保存棋局文件_Click()CommonDialog1.Filter = *.wzq/*.wzqCommonDialog1.Action = 2Open CommonDialog1.FileName For Output As #1Print #1, wuziqiFor i = -7 To 7For j = -7 To 7If a(i, j) 0 ThenPrint #1, iPrint #1, jPrint #1, a(i, j)Print #1, bPrint #1, wEnd IfNextNextClose #1End SubPrivate Sub 打开棋局文件_Click()For i = -7 To 7For j = -7 To 7a(i, j) = 0NextNextCommonDialog1.Filter = *.wzq/*.wzqCommonDialog1.Action = 1Open CommonDialog1.FileName For Input As #1Line Input #1, strwzqwuziqi = CBool(strwzq)Do While Not EOF(1)Line Input #1, striLine Input #1, strjLine Input #1, straLine Input #1, strbLine Input #1, strwa(Val(stri), Val(strj) = Val(stra)LoopClose #1Call paintEnd SubForm 3悔根保育拱岗打开已保才保再曝与支 件力才博与文 件Dim recount As IntegerPrivate Sub Command1_Click()With Datal五子棋棋库.mdb”.RecordSource =五子棋棋库.RefreshIf Trim(Text1.Text) = ThenMsgBox ”棋局名不能为空Exit SubEnd IfIf .Recordset.RecordCount 0 Then.Recordset.MoveLastrecount = .Recordset.RecordCount.Recordset.MoveFirstFor i = 1 To recountIf .Recordset.Fields(棋局名)=Text1.Text Then.Recordset.DeleteEnd IfIf Not .Recordset.EOF Then.Recordset.MoveNextEnd IfNextEnd IfFor i = -7 To 7For j = -7 To 7If a(i, j) 0 Then.Recordset.AddNew.Recordset.Fields( 棋局名 ) = Text1.Text.Recordset.Fields(执黑棋者)=b.Recordset.Fields(执白棋者)=w.Recordset.Fields(X 坐标 ) = i.Recordset.Fields(Y 坐标 ) = j.Recordset.Fields(该点状态值“)=a(i, j).Recordset.Fields(下棋状态)=wuziqi.Recordset.UpdateEnd IfNextNextUnload MeEnd WithEnd SubForm 4,保存樵国Dim recount As IntegerPrivate Sub Form_Load()Combol.Text =请选择所要打开的棋局 strfile =With Data1五子棋棋库.mdb”.RecordSource =五子棋棋库.RefreshIf .Recordset.RecordCount 0 Then.Recordset.MoveLastrecount = .Recordset.RecordCount.Recordset.MoveFirstFor i = 1 To recountIf .Recordset.Fields(棋局名) strfile Thenstrfile = .Recordset.Fields(棋局名”)Combo1.AddItem strfileEnd IfIf Not .Recordset.EOF Then.Recordset.MoveNextEnd IfNextEnd IfEnd WithEnd SubPrivate Sub Command1_Click()For i = -7 To 7For j = -7 To 7a(i, j) = 0NextNextWith Data1五子棋棋库.mdb.RecordSource = 五子棋棋库.RefreshIf .Recordset.RecordCount 0 Then.Recordset.MoveLastrecount = .Recordset.RecordCount.Recordset.MoveFirstFor i = 1 To recountIf .Recordset.Fields( 棋局名 ) = Combo1.Text Thena(.Recordset.Fields(X 坐标 ), .Recordset.Fields(Y 坐标 ) = .Recordset.Fields( 该点状态 值)End IfIf Not .Recordset.EOF Then.Recordset.MoveNextEnd IfNext.Recordset.MoveFirstFor i = 1 To recountIf .Recordset.Fields( 棋局名 ) = Combo1.Text Thenwuziqi = .Recordset.Fields( 下棋状态 )Exit ForEnd IfIf Not .Recordset.EOF Then.Recordset.MoveNextEnd IfNextEnd IfEnd WithCall paintUnload MeEnd Sub
展开阅读全文