资源描述
目目 录录一、设计目的 .3二、设计要求 .3三、所需仪器设备 .3四、课题分析 .3五、具体设计过程 .45.1、设计思路.45.2、程序设计流程图.45.3、函数实现说明.75.4、图形库函数介绍.85.5、程序源代码及注释 .95.6、调试结果.19六、设计心得体会 .20七、参考文献 .212黑白棋游戏黑白棋游戏CC 语言课程设计语言课程设计一、设计目的一、设计目的本课程设计是计算机软件技术基础重要的实践性环节之一,是在学生学习完程序设计语言(C)课程后进行的一次全面的综合练习。本课程设计的目的和任务: (1)巩固和加深学生对 C 语言课程的基本知识的理解和掌握;(2)掌握 C 语言编程和程序调试的基本技能; (3)利用 C 语言进行基本的软件设计,掌握软件设计一般方法,了解软件设计的思路;(4)掌握书写程序设计报告的能力;(5)提高运用 C 语言解决实际问题的能力;这个程序也是对编程基本功的一个训练,对于初学 C 语言的人,讲分支、循环、数组函数综合应用,而不仅限于编制独立的小程序,能够大大提高变成水平。二、设计要求二、设计要求(1)收集资料,全面分析课题,分解问题,形成中体编程思路;(2)深入分析各个小问题,编写个部分程序模块;(3)对于设计中用到的关键函数,要联系实际 问题进行具体介绍;(4)上机调试,确保程序能正确运行;(5)设计完成后提交课程设计报告;三、所需仪器设备三、所需仪器设备(1)硬件要求能运行 Windows 2000/XP 操作系统的微机系统。(2)C 语言程序设计及相应的开发环境。 (本设计用的是 Turbo C for Windows 集成实验与学习环境 V6.0)四、课题分析四、课题分析编写一个黑白棋游戏的 C 程序,包括以下功能:初始状态:在一个 8*8 的棋盘中央交叉排放黑白棋子各两枚,白棋先走。(1)每个棋手下棋时,摆子的位置必须是以自己的棋子能包围住对方一个或多个棋子,被包围住的对方棋子将成为自己的棋子。包围的方向可以是上下左右以及斜线 8 个方向,只要能连成一线即可。(2)当轮到某一个棋手下子,但是他没有可以包围对方棋子的位置时,他必须停步,让对方走棋,直到他可以走为止。(3)当棋盘上一方的棋子为 0 或者下满 64 格,游戏结束,棋子少者输。3五、具体设计过程五、具体设计过程5.15.1、设计思路、设计思路程序界面应是一个二维平面图,所以数据的表示用二维数组,数组两个下标可以表示棋盘上的位置,数组元素的值代表棋格中的状态,共有三种情况,分别是空格、黑棋和白棋。这样给数组元素的取值设定为 0、1、2,其中 0 代表空格,1 代表白色棋子,2 代表黑色棋子。这样程序的主要工作是接收棋手按键操作,一旦接收到回车键,说明棋手摆子,先判断是不是有效位置,也就是能不能包围住对方棋子,如果能,便为棋子所在的位置往上下、左右、左上、左下、右上、右下 8 个方向寻找被包围住的所有棋子(必须是连续的,中间不能有空格) ,将这些被包围住的对方棋子都变成自己的棋子,然后对当前棋盘中的黑白棋个数进行统计并输出结果。如果没有这样的位置可以落子,则停步,让对方走棋,重复上述步骤,直到游戏结束。如果想提前终止游戏,可以按 Esc 键。 5.25.2、程序设计流程图、程序设计流程图(1)由上述设计思路可画出程序整体流程图,如下图所示:4图 1 程序整体流程图开 始结 束 游 戏初始化图形系统画出棋盘按键操作是否为有效位置?按键是否为回车键?落 棋变成自己的棋子统计黑白棋个数,输出成绩。输出胜利者信息关闭图形系统否是否是5(2)人人对战模块程序流程图如下图所示: 图 2 人人对战模块流程图(3) 成绩输出模块程序流程图如下图所示 6图 3 成绩输出模块程序流程图5.35.3、函数实现说明函数实现说明(1)main()主函数在主函数中,首先定义使用到的常数、全局变量、函数原型说明。盘状态用数组 a88,初值为 0,表示空格。函数的实体部分,开始初始化图形系统,然后通过调用函数DrawQp()先画出棋盘,调用 playtoplay()人人对战函数开始游戏,一旦游戏结束后,关闭图形系统,程序结束。(2)DrawQp()画棋盘函数背景颜色设为蓝色,从坐标(100,100)开始每隔 40 个单位用白色画一条水平直线,一条垂直线,构成棋盘,用循环语句实现。函数 setfillstyle()可以设置填充模式和填充颜色,fillellipse(int x,int y,xradius,int yradius)以 x 和 y 为圆心,xradius和 yradius 为水平和垂直轴画一填充椭圆,当 xradius 和 yradius 相等时,则画出的是圆,用它表示棋子。(3)SetPlayColor()设置棋子的颜色 函数的参数为整型变量 t,根据 t 的值来设计填充棋子的当前颜色,值为 1 代表白棋,值为 2 代表黑棋。(4)MoveColor()恢复原来格子的状态7由于棋手在走棋的时候,他的棋子总是首先出现在棋盘的左上角,棋手要通过移动光标走到要落子的位置,在经过的路程上显示当前棋子,就会覆盖原来的棋盘状态,所以一旦棋子走过后,就应恢复原来的状态,是空格的依然显示空格,是棋子的就显示原来棋子的颜色。因为棋子移动过程并没有改变数组元素的值,所以可以根据数组元素的值判定原来的状态,如果值是 1,就恢复白色棋子,值是 2 则恢复黑色棋子,否则恢复蓝色空格。(5) 、playtoplay()人人对战函数 这是游戏进行的函数,主要是接收棋手的按键消息,其处理过程如下: 1)按 Esc 键程序可以随时结束。 2)按上下左右光标键,则改变棋子移动的坐标值。 3)按回车键后判断: 如落子的位置已经有棋则无效,继续压键。 如落子位置是空格,可以将棋子落入格内,调用函数 QpChange()判断是否引起棋盘的变化,函数值为 1 有变化,为 0 没变化。如果棋盘有变化,说明将包围的对方棋子吃掉,统计当前分数,如果棋盘没有变化,则说明落子的位置无法包围对方的棋子也视为无效棋,可以继续寻找合适的位置,但开始统计其落子次数,一旦尝试次数超过当前棋盘的空格数,则说明他无棋可走,则放弃此步,让对方下棋。 如果棋子变化后,格子已占满 64 格或一方棋子为 0,则游戏结束,显示胜利方信息。按任意键程序结束。 重复上述步骤,直到游戏结束。 (6) 、QpChange()判断棋盘变化当棋手按回车键落子后,就要分别往 8 个方向判断是否包围住对方棋子,如果是,则改变棋盘,也就是棋盘上黑白棋子的个数要发生变化。如果所有方向都判断过,并且没有引起棋盘的变化,则棋盘变化标志值 yes 为 0,返回 yes,结束本函数。(7) 、DoScore()处理分数 根据当前数组元素的值判断分数,也就是各方棋子的个数,如果数组元素值为 1,白棋棋子数累加;如果数组元素值为 2,则黑棋棋子数累加。(8) 、PrintScore()输出成绩 利用设置实体填充模式填充矩形条清除掉前次的成绩,再利用 sprintf()函数将整数转换为字符串的形式,再利用 outtextxy()函数将成绩输出。(9) 、playWin()输出胜利者结果 根据分数值 score1 和 score2 的大小得出下棋的结果,输出赢者信息。如果是白方胜就输出“white win!” ,黑方胜就输出“black win!” ,平局就输出“you all win!” 。5.45.4、图形库函数介绍、图形库函数介绍图形库 是 TC 里面的图形库,分为:像素函数、直线和线型函数、多边形函数、填充函数等。在本程序中主要应用到了以下功能函数:8(1)、line() 画线函数功能: 函数 line()使用当前绘图色、线型及线宽,在给定的两点间画一直线。 函数原型: void line(int startx,int starty,int endx,int endy); 说明: 参数 startx,starty 为起点坐标,endx,endy 为终点坐标,函数调用前后,图形状态下屏幕光标(一般不可见)当前位置不改变。 (2)、setcolor()图形屏幕函数 函数原型:void setcolor(int color) 功能:将当前图形屏幕的当前笔画颜色置为 color.(3)、setfillstyle() 设置填充图样和颜色函数函数原型: void far setfillstyle(int pattern, int color);功 能: 设置填充模式和颜色 (4) 、fillellipse() 画椭圆区函数功 能: 画出并填充一椭圆 函数原型: void far fillellipse(int x, int y, int xradius, int yradius); 说明:填充边框所定义的椭圆的内部,该边框由一对坐标、一个宽度和一个高度指定。(5) 、setbkcolor()功能:该函数用指定的颜色值来设置当前的背景色函数原型:Void far SetBkColor(int Color );(6) 、C 语言中的颜色表及填充模式如下两表所示:95.55.5、程序源代码及注释、程序源代码及注释 #include graphics.h /*图形系统头文件*/#define LEFT 0 x4b00 /*光标左键值*/10#define RIGHT 0 x4d00 /*光标右键值*/#define DOWN 0 x5000 /*光标下键值*/#define UP 0 x4800 /*光标上键值*/#define ESC 0 x011b /* ESC 键值*/#define ENTER 0 x1c0d /* 回车键值*/int a88=0,key,score1,score2;/*具体分数以及按键与存放棋子的变量*/char playone3,playtwo3;/*两个人的得分转换成字符串输出*/void playtoplay(void);/*人人对战函数*/void DrawQp(void);/*画棋盘函数*/void SetPlayColor(int x);/*设置棋子第一次的颜色*/void MoveColor(int x,int y);/*恢复原来棋盘状态*/int QpChange(int x,int y,int z);/*判断棋盘的变化*/void DoScore(void);/*处理分数*/void PrintScore(int n);/*输出成绩*/void playWin(void);/*输出胜利者信息*/*主函数*/void main(void)int gd=DETECT,gr;initgraph(&gd,&gr,c:tc); /*初始化图形系统*/DrawQp();/*画棋盘*/playtoplay();/*人人对战*/getch();closegraph();/*关闭图形系统*/void DrawQp()/*画棋盘*/int i,j;score1=score2=0;/*棋手一开始得分都为 0*/setbkcolor(BLUE);for(i=100;i=64-score1-score2) /*如果尝试超过空格数则停步*/MoveColor(x,y);fillellipse(x,y,15,15);break;elsecontinue;/*如果按键无效*/DoScore();/*分数的改变*/break;/*棋盘变化了,则轮对方走棋*/else/*已经有棋子就继续按键*/continue;else /*四个方向按键的判断*/if(key=LEFT&x120)/*左方向键*/MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);x-=40;fillellipse(x,y,15,15);elseif(key=RIGHT&x80)/*右方向键*/MoveColor(x,y);13fillellipse(x,y,15,15);SetPlayColor(t);x+=40;fillellipse(x,y,15,15);elseif(key=UP&y120)/*上方向键*/MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);y-=40;fillellipse(x,y,15,15);elseif(key=DOWN&y400)/*下方向键*/MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);y+=40;fillellipse(x,y,15,15);if(key=ESC)/*结束游戏*/break;if(score1+score2)=64|score1=0|score2=0)/*格子已经占满或一方棋子为 0 判断胜负*/playWin();/*输出最后结果*/break;t=t%2+1; /*一方走后,改变棋子颜色即轮对方走*/cc=0; /*计数值恢复为 0*/ /*endwhile*/14void SetPlayColor(int t)/*设置棋子颜色*/if(t%2=1)setfillstyle(SOLID_FILL,15);/*白色*/elsesetfillstyle(SOLID_FILL,8);/*灰色*/void MoveColor(int x,int y)/*走了一步后恢复原来格子的状态*/if(y100)/*如果是从起点出发就恢复蓝色*/setfillstyle(SOLID_FILL,BLUE);else/*其他情况如果是 1 就恢复白色棋子,2 恢复黑色棋子,或恢复蓝色棋盘*/switch(a(x-120)/40(y-120)/40)case 1:setfillstyle(SOLID_FILL,15);break; /*白色*/case 2:setfillstyle(SOLID_FILL,8);break; /*黑色*/default:setfillstyle(SOLID_FILL,BLUE); /*蓝色*/int QpChange(int x,int y,int t)/*判断棋盘的变化*/int i,j,k,kk,ii,jj,yes;yes=0;i=(x-120)/40; /*计算数组元素的行下标*/j=(y-120)/40; /*计算数组元素的列下标*/SetPlayColor(t);/*设置棋子变化的颜色*/*开始往 8 个方向判断变化*/if(j6)/*往右边*/for(k=j+1;k8;k+)if(aik=aij|aik=0)/*遇到自己的棋子或空格结束*/break;if(aik!=0&k8)15for(kk=j+1;kkk&k1)/*判断左边*/for(k=j-1;k=0;k-)if(aik=aij|!aik)break;if(aik!=0&k=0)for(kk=j-1;kkk&k=0;kk-)aikk=aij;fillellipse(120+i*40,120+kk*40,15,15);if(kk!=j-1)yes=1;if(i6)/*判断下边*/for(k=i+1;k8;k+)if(akj=aij|!akj)break;if(akj!=0&k8)for(kk=i+1;kkk&k1)/*判断上边*/for(k=i-1;k=0;k-)if(akj=aij|!akj)break;if(akj!=0&k=0)for(kk=i-1;kkk&k=0;kk-)akkj=aij;fillellipse(120+kk*40,120+j*40,15,15);if(kk!=i-1)yes=1;if(i1&j=0&kk=0&kkk&k=0;ii-,jj+)aiijj=aij;fillellipse(120+ii*40,120+jj*40,15,15);if(ii!=i-1)yes=1;17if(i1)/*左下*/for(k=i+1,kk=j-1;k=0;k+,kk-)if(akkk=aij|!akkk)break;if(akkk!=0&k=0)for(ii=i+1,jj=j-1;iik&k1&j1)/*左上*/for(k=i-1,kk=j-1;k=0&kk=0;k-,kk-)if(akkk=aij|!akkk)break;if(akkk!=0&k=0&kk=0)for(ii=i-1,jj=j-1;iik&k=0;ii-,jj-)aiijj=aij;fillellipse(120+ii*40,120+jj*40,15,15);if(ii!=i-1)yes=1;if(i6&j6)/* 右下*/18for(k=i+1,kk=j+1;kk8&kk8;k+,kk+)if(akkk=aij|!akkk)break;if(akkk!=0&kk8&k8)for(ii=i+1,jj=j+1;iik&k8;ii+,jj+)aiijj=aij;fillellipse(120+ii*40,120+jj*40,15,15);if(ii!=i+1)yes=1;return yes;/*返回是否改变过棋子颜色的标记*/void DoScore()/*处理分数*/int i,j;score1=score2=0;/*重新开始计分数*/for(i=0;i8;i+)for(j=0;jscore1)/*开始判断最后的结果*/outtextxy(100,50,black win!);elseif(score2score1)outtextxy(100,50,white win!);elseouttextxy(60,50,you all win!);5.6、调试结果、调试结果(1)本程序是在 Turbo C for Windows 集成实验与学习环境 V6.0 环境下运行的。运行程序后,会得到如下图 4 所示初始界面,初始棋盘上黑白双方各有两粒棋子,白棋先走。然后双方交替找棋,同时显示比分,直到把棋盘走满,最后看看黑白双方谁的棋子多, 输出胜利者息。如图 5 所示。20 图 4 游戏初始界面 图 5 白方胜利的界面(2) 程序运行所遇问题:程序能够正常运行,但在 DOS 全屏环境下无法截屏,我尝试过用 printscreen 键和 QQ 截图等很多方法,但都不行。所以,最后只能用相机把运行结果拍下来,如上两图所示,截图有点斜,就是这个原因。六、设计心得体会六、设计心得体会 以前也做过一次 c 语言课程设计,但那时候对 c 语言基本的知识点都不是很懂,21更别说要我们编出那种图形界面的程序来。所以感觉 C 语言很枯燥,也总认为 c 语言只能编出那种黑底白字的程序。但经过这次计算机软件技术课程设计,真正使我对计算机编程培养了浓厚的兴趣。当我看到了用 C 语言做出的黑白棋游戏系统后,我才真正感受到了 C 程序设计的强大和神奇。原来 C 语言一样也能做出那种很漂亮的图形界面来。这让我真正认识到了学习编程的必要性。在大一的时候我就过了国二,但说实话,那基本上只是对 C 语言基础知识点的考查,要我们编出这样的程序来还有很远距离。虽然说这黑白棋游戏系统程序不是我自己编写出来的,但在老师的指导下,我自己查了很多资料,认认真真地读了程序,也仔细分析程序的逻辑思路。使我对 C 语言编程有了更深入更真切的了解,具体如下:(1) 、模块化思想。虽然平常上课老听老师说要有模块化思想,但自己在编写实例中具体如何模块化就不是很清楚了。通过这次课程设计,使我切实理解了模块化思想,比如在黑白棋游戏系统中就可以分为画棋盘模块、人人对战模块、分数处理模块等,要实现哪个功能就直接读和修改对应的哪个模块,这样就大大提高了程序的可读性和易修改性。(2) 、分析程序先从主函数 main()入手。Main()函数是 C 源程序编译时的开始,从main()函数开始读函数可将其他函数的功能理解得更透彻。(3) 、本次课程设计我收获最大的就是对图形库的认识和了解,平时我们编程很少用到也不知道怎么用这图形库,所以一直认为 C 语言编不出那种很漂亮的图形界面。通过本次课设,我学会了如何调用图形库里面的功能函数,比如调用 line() 画线函数、setfillstyle() 设置填充图样和颜色函数、fillellipse() 画椭圆区函数、setbkcolor()设置背景颜色函数等等,对这些函数的原型和功能都有所了解。(4) 、除此之外,我还学会了如何对文档的整体排版和报告格式的书写等等很多处理文档的能力,是对我们以后撰写论文的一次很好的锻炼。 总而言之,通过本次课程设计,无论是在学习上还是其他方面,都使我受益匪浅。七、参考文献七、参考文献1 谭浩强, C 程序设计(第三版) ,清华大学出版社,2005.72 郭翠英,C 语言课程设计案例精编, 中国水利水电出版社,2004.33 朱振元,数据结构(面向对象语言描述) ,清华大学出版社,2004.24 张翔, C 语言函数大全 ,电子工业出版社,2002.45徐金梧, TURBO C 实用大全 ,机械工业出版社,1996.522
展开阅读全文