五子棋课程设计

德州学院信息管理学院

课程设计报告

实习名称 自主学习能力 设计题目 五子棋小游戏 实习时间 2015.04.01--2014.04.30 专业班级 14级计算机科学与技术 指导老师 曹金凤 教学单位

小组分工情况:

二〇一四年五月二十五日

i

目 录

1 实习目的 ................................................................ 2 2 需求分析 ................................................................ 2 3 概要设计 ................................................................ 2 3.1 游戏背景 ............................................................ 2 3.2 游戏玩法 ............................................................ 3 3.3 程序需求分析 ........................................................ 3 3.4 开发平台 ............................................................ 3 3.5程序流程设计 ........................................................ 4 4 棋盘与棋子的生成 ........................................................ 5 4.1引言 ................................................................ 5 4.2 程序语句 .......................................... 错误!未定义书签。 5 棋子移动与落子 .......................................................... 6 5.1引言 ................................................................ 6 5.2程序语句 ............................................................ 6 6 胜负判断 ............................................................... 16 6.1引言 .............................................. 错误!未定义书签。 6.2程序设计 ........................................................... 17 7 调整改进 ............................................................... 18 7.1引言 ............................................................... 18 7.2程序功能及调整 ..................................................... 18 7.3总程序语句 ......................................................... 19 8 总结 ................................................................... 28 参考文献: ............................................................... 29

ii

五子棋小游戏的设计与实现

1 实习目的

(1)熟练的运用计算机语言,培养了对计算机编程的热爱程度. (2)学会怎样用c语言做一个完整的系统。 (3)掌握c语言的编辑,链接,运行等环节。

(4)掌握c语言中链表的建立,插入,删除,保存节点。 (5)熟练掌握for while do-while循环语句的使用。

(6)熟练掌握函数的定义、说明、参数传递及嵌套和递归调用方法。 (7)提高遇到困难解决困难的能力。 (8)提高书写代码的速度与正确率。

(9)独立实践,将课本上的理论知识和实际有机的结合起来,锻炼学生的分析解决实际问题的能力,提高学生适应实际,实践编程的能力。

2 需求分析

目前,随着计算机网络的的发展,PK已经成为现在人生活的一部分,人们 以不同的方式通过网络来娱乐,休闲。以计算机技术和网络技术为核心的现代网络技术已经在现实生活和生产中得到了广泛的使用,休闲类网络游戏集趣味性,娱乐性,互动性和益智性于一体,已经成为多数人群的休闲方式,也为多数人所喜好。当然,为了满足没有网络同样能娱乐的要求,许多小游戏做成了单机和网络的双功能。

3 概要设计

3.1 游戏背景

五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;它既有简单易学的特性,为人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既

3

有“场”的概念,亦有“点”的连接。它是中西文化的交流点,是古今哲理的结晶。

3.2 游戏玩法

五子棋是一种两人对弈的纯策略 型棋类游戏,五子棋棋子分为黑白两色,棋盘为19×19,棋子放置于棋盘线交叉点上或网格中。两人对局,各执一色,轮流下一子,先将横、竖或斜线的5个同色棋子连成不间断的一排者为胜。

3.3程序需求分析

根据功能需求,将程序分为图形显示、玩家控制、胜负判断和系统帮助四个模块,以下分析各模块的需求。

图形显示模块:程序开始运行时,给出欢迎界面;游戏开始后要求生成19×19的棋盘图像,并在棋盘上方提示 当前落子方棋子颜色,游戏进行过程中,要求实时显示棋盘上已落下的棋子;分出胜负后,要求给出游戏结束画面。 玩家控制模块:程序开始时,需玩家确定而后开始游戏;游戏过程中,两个玩家通过不同的按键移动光标,选择落子;游戏结束时,有玩家选择是否开始新棋局。

胜负判断模块:实时监测棋盘上棋子,一旦某一色棋子出现五子连线,终止游戏程序,弹出该色玩家胜出界面。

系统帮助模块:弹出窗口,窗口中 显示帮助信息,包括棋子移动与落子按 键介绍,获胜方式等。

除以上主要模块之外,程序中还可以添加其他辅助程序,如中途退出等。程序的关键在于胜负判断模块,该模块的设计直接关系到程序的运行速率和运行结果的正确与否。

3.4 开发平台

系统: Windows 7 旗舰版(64位)

处理器: AMD A8-5545M APU with Radeon(tm) HD Graphics 1.70GHz

4

内存: 4.00 GB

程序开发软件:Microsoft Visual C++ 6.0 文档编写:Microsoft Word 2010

3.5 程序流程设计

根据程序需求分析结果,可以得出程序的总体结构图如图1:

图1 程序总体流程图图

程序总体流程图如图2:

5

图2 程序总体设计图

4.棋盘与棋子的生成

4.1引言

根据五子棋的基本规则,棋盘采用19×19方格棋盘,棋子为黑白二色圆形棋子;游戏进行过程中棋盘始终显示,落子后棋子在落子处始终显示;棋盘在程序结束时消失,已落下的棋子在 程序结束时或开始新游戏是消失。

4.2程序语句

棋盘的显示由游戏开始与结束部分控制,棋子的显示与保留由玩家操控部分决定。

board() /*画棋盘*/ { setfillstyle(1,6); bar(120,50,520,450); setfillstyle(1,14); bar(540,50,620,150); bar(20,50,100,150); for(k=0;k

{moveto(140+20*k,70);linerel(0,360);

moveto(140,70+20*k);linerel(360,0); }

moveto(240,170); setcolor(5); settextstyle(3,0,4); outtextxy(50,60,"P1"); outtextxy(560,60,"P2"); }

white() /*画白棋*/ {

setcolor(7);

setfillstyle(1,7);

circle(getx(),gety(),9); fill(getx(),gety(),7); }

black() /*画黑棋*/ {

6

setcolor(0);

setfillstyle(1,0);

circle(getx(),gety(),9); fill(getx(),gety(),0); }

5棋子移动与落子

5.1引言

棋子的移动与落子有键盘上按键控制,本程序选取1P按键为W、S、A、D和空格键,2P按键为↑、↓、←、→和回车键,分别代表上移、下移、左移、右移光标和落子。在光标移动的过程中,光标按照玩家按键移动;在玩家按下落子按键后,程序自动调用棋子显示子程序和判断胜负子程序。1P、2P的落子后,程序会为落子处的数组元素赋一个特定值,用于判定胜负。

5.2程序语句

void p1move() /*玩家1的移动*/ {

switch(bioskey(0)) {

int sum=0;

case ESC: {closegraph(); exit(0);}/*如果按键为ESC就退出游戏 */

case SP:/*落子*/ if(a[X][Y]==6) {

p1del(); p2turn();

7

a[X][Y]=0; sum++; white(); p2move(); if(sum>=5) win(); }

else p1move();

case A: /*向左移*/ if(a[X][Y]==0) {

if(getx()==140)

moveto(520,gety()); moverel(-20,0); white(); }

else if(a[X][Y]==1) {

if(getx()==140) moveto(520,gety()); black();moverel(-20,0); white(); } else {

if(getx()==140)

8

moveto(520,gety()); moverel(-20,0); white(); } p1move(); case D: /*向右移*/ if(a[X][Y]==0) {

if(getx()==500) moveto(120,gety()); moverel(20,0); white();} else if(a[X][Y]==1) {

if(getx()==500) moveto(120,gety()); black();moverel(20,0); white(); } else {

if(getx()==500) moveto(120,gety()) ; moverel(20,0); white(); }

9

p1move(); case W: /*向上移*/ if(a[X][Y]==0) {

if(gety()==70) moveto(getx(),450); moverel(0,-20); white(); }

else if(a[X][Y]==1) {

if(gety()==70) moveto(getx(),450); black(); moverel(0,-20); white(); } else {

if(gety()==70) moveto(getx(),450); moverel(0,-20); white(); } p1move();

case S: /*向下移*/

10

if(a[X][Y]==0) {

if(gety()==430) moveto(getx(),50); moverel(0,20); white(); }

else if(a[X][Y]==1) {

if(gety()==430) moveto(getx(),50); black(); moverel(0,20); white(); } else {

if(gety()==430) moveto(getx(),50); moverel(0,20); white(); } p1move(); default: p1move(); }

11

}

void p2move() /*玩家2的移动*/ {

switch(bioskey(0)) /*如果按键为ESC就退出游戏*/ {

int sum=0;

case ESC: {closegraph(); exit(0);} case ENTER: /*落子*/ if(a[X][Y]==6) {

p2del(); p1turn(); a[X][Y]=1; sum++; black(); p1move(); if(sum>=5) win(); } else p2move(); case LEFT: /*向左移*/ if(a[X][Y]==1) {

if(getx()==140) moveto(520, gety());

12

moverel(-20,0); black(); }

else if(a[X][Y]==0) {

if(getx()==140) moveto(520,gety()); if(getx()==140) moveto(500,gety()); white(); moverel(-20,0); black(); } else {

if(getx()==140) moveto(520,gety()); moverel(-20,0); black(); } p2move();

case RIGHT: /*向右移*/ if(a[X][Y]==1) {

if(getx()==500) moveto(120,gety());

13

moverel(20,0); black(); }

else if(a[X][Y]==0) {

if(getx()==500) moveto(120,gety()); white(); moverel(20,0); black(); } else {

if(getx()==500) moveto(120,gety()); moverel(20,0); black(); } p2move();

case UP: /*向上移*/ if(a[X][Y]==1) {

if(gety()==70) moveto(getx(),450); moverel(0,-20); black();

14

}

else if(a[X][Y]==0) {

if(gety()==70) moveto(getx(),450); white(); moverel(0,-20); black(); } else {

if(gety()==70) moveto(getx(),450); moverel(0,-20); black(); } p2move();

case DOWN: /*向下移*/ if(a[X][Y]==1) {

if(gety()==430) moveto(getx(),50); moverel(0,20); black(); }

else if(a[X][Y]==0)

15

{

if(gety()==430) moveto(getx(),50); white(); moverel(0,20); black(); } else {

if(gety()==430) moveto(getx(),50); moverel(0,20); black(); } p2move(); default: p2move(); } }

6胜负判断

6.1引言

胜负判断模块是程序的关键,该模块的设计直接关系到程序的运行速率和运行结果的正确与否。

本函数根据每次落子的位置,分别向上、下、左、右、左上、左下、右上、右下八个 方向判断是否有相同颜色的棋子连成五子,如果成立,游戏就结束,并显示提示信息,否则继续落子。

16

以下简析本程序流程:如表1所示,令当前落子点坐标为(X,Y),表中 i=X-4, j=Y-4,由获胜条件可以知,通过判断(X,Y)上、下、左、右、斜上、斜下八个方向上是否有连续的5个子即可得出是否获胜结果。在游戏开始时,将棋盘初始化,即将棋盘抽象为一个19*19的数组,数组中每个元素设为某一指定初始值(如8)。1P落子时,将数组内相应坐标处元素赋值为0;2P落子时,将数组内相应坐标处元素赋值为1。当(X,Y) 上、下、左、右、斜上、斜下八个方向某5个连续的子所对应的数组中元素之和等于0时,1P获胜;当(X,Y) 上、下、左、右、斜上、斜下八个方向某5个连续的子所对应的数组中元素之和等于5时,2P获胜。棋盘上的所有格子都被占满时,必有181个1P棋子和180个2P棋子,此时对应数组中所有项之和为180,并且游戏过程中对应数组中所有项之和只可能在这种状况下为180,所以可以用这一条件判断是否和棋。

表1 胜负判断表

为减少程序的运算,还可以将某些特殊情况排除在外。当落子数不大于8时,既不用判断胜负,也不用判断和棋与否,这部分功能在第二章移动与落子程序中实现。此外,还可以通过对落子次数的统计判断是否满足和棋条件,从而减少大量运算,即当判断177次胜负后出现和棋。

6.2程序设计

void win() /*判断输赢*/ {

17

int sum1,sum2,sum3,sum4,sum=1,n,i,j; for(i=X-4,j=Y-4,n=0;i

sum1=a[i][Y]+a[i+1][Y]+a[i+2][Y]+a[i+3][Y]+a[i+4][Y];

sum2=a[i][j]+a[i+1][j+1]+a[i+2][j+2]+a[i+3][j+3]+a[i+4][j+4]; sum3=a[X][j]+a[X][j+1]+a[X][j+2]+a[X][j+3]+a[X][j+4];

sum4=a[i][j+8+n]+a[i+1][j+7+n]+a[i+2][j+6+n]+a[i+3][j+5+n]+a[i+4][j+4+n]; if(sum1==5||sum2==5||sum3==5||sum4==5) p2win(); if

(sum1==0||sum2==0||sum3==0||sum4==0) p1win(); } sum++ if(sum==177) heqi(); }

7调整改进

7.1引言

前6章分别论述了五子棋C语言程序中的四大主要模块,但要生成可执行的程序,则还需将这些模块有机地结合起来。在结合的过程中,需要综合运 用函数调用、函数间书序传递和全局变量等知识。

18

7.2程序功能及调整

为满足实际操作需求,增加程序的兼容性与稳定性,在编写可执行程序的过程中,必须对原有各功能模块进行整合并添加或调整部分功能。

为方便玩家使用本程序,在程序中增加了“悔棋”、“认输”和“退出”功能,玩家可以通过在游戏构成中输入相关指令实现这些功能,具体语句见附录。

为增强程序的兼容性和实用性,在最终的可执行程序中还对原有模块进行了其他修改。

在调试的过程中,发现bios.h 和graphics.h两个头文件只有在Turbo C的编译环境下才能顺利执行,因此,使用bios.h和graphics.h的程序兼容性不高,因此,舍弃使用这两个头文件的图像显示模块,转而使用具有较高兼容性的全屏打印刷新显示块。后者虽然在视觉效果上不如前者,然而它可以在任何Windows系统下工作,而这比视觉效果重要得多。

在调试过程中,发现每当1P在最外圈落子时,系统即可弹出1P获胜的结果,这是由于win函数中是通过对落子点及其周围的若干点求和来判断是否获胜的。当1P在最外圈落子时,棋盘外的点被程序当做0处理,加上落子时被赋值为0的一点,正好满足1P获胜的条件,故而引发错误。改进方法:将用于判断输赢的数组a由原来的19*19改为21*21,并将第0、20行及第0、20列中所有元素赋值为6;再将被这四组元素包围的一个19*19的区间对应到棋盘上的19*19格,即可解决原有问题。

在调试的过程中,还发现原有模块中的按键操作过于复杂,综合兼容性考虑,舍弃原有的光标操作模式,改用输入坐标的操作模式,这样做从某种程度上降低了程序的可操作性,但提高了程序的可实现性与兼容性。

7.3总程序语句

/*函数、变量定义*/

#include #include #include #include

19

#define N 19 int win(int m, int l); void printState(); p1win(); p2win(); heqi(); void help(); int i,j,k,size=N; int isBlack=1; char state[N][N]; int a[N+2][N+2]; char x,y,temp[10]; char c; int z;

/*初始化及指令输入*/

void startGame() {

int m,n,w; for(i=0;i

for(j=0;j

state[i][j]='_'; a[i][j]=6;

20

}

}

printState();

while(1)

{

printf("\n\t请%s方下子:",isBlack?"黑":"白");

fflush(stdin);

scanf("%s",temp);

if(!strcmp(strupr(temp),"OUT"))

{

system("cls");

return;

}

/*悔棋 */

if(!strcmp(temp,"BACK"))

{

i=x-'A';

j=y-'A';

state[i][j]='_';

printState();

isBlack=!isBlack;

continue;

}

if(!strcmp(temp,"LOSE"))

21

/*认输*/

{

printf("\n\t%s方认输,%s方胜!\n\n",isBlack?"黑":"白",isBlack?"白":"黑"); return;

}

x=temp[0];

y=temp[1];

/*避免下面相减的数组越界。*/

if(x'S'||y'S')

{

printf("\t输入有误,请输入属于或正确的口令。\n");

continue;

}

i=x-'A';

j=y-'A';

if(state[i][j]!='_')

{

printf("\t提示:该位置已经有子,请重新指定坐标!");

continue;

}

c=isBlack?'1':'2';

z=isBlack? 0:1;

22

state[i][j]=c;

a[i+1][j+1]=z;

m=i+1;

n=j+1;

w=win(m,n);

if(!w)

{

printState();

isBlack=!isBlack;

}

else

{

return;

}

}

}

/*判断输赢*/

int win(int m, int l)

{

int

sum1,sum2,sum3,sum4,sum=1,n,i,j,X,Y,w;

w=0;

X=m;

Y=l;

23

for(i=X-4,j=Y-4,n=0;i

{

sum1=a[i][Y]+a[i+1][Y]+a[i+2][Y]+a[i+3][Y]+a[i+4][Y];

sum2=a[i][j]+a[i+1][j+1]+a[i+2][j+2]+a[i+3][j+3]+a[i+4][j+4];

sum3=a[X][j]+a[X][j+1]+a[X][j+2]+a[X][j+3]+a[X][j+4];

sum4=a[i][j+8+n]+a[i+1][j+7+n]+a[i+2][j+6+n]+a[i+3][j+5+n]+a[i+4][j+4+n];

if(sum1==5||sum2==5||sum3==5||sum4==5)

{

p2win();

w=1;

}

if

(sum1==0||sum2==0||sum3==0||sum4==0)

{

p1win();

w=1;

}

}

sum1=0;

sum2=0;

sum3=0;

sum4=0;

sum++;

24

if(sum==177)

{

heqi();

w=1;

}

return w;

}

/*和棋界面*/

heqi()

{

printf("和棋");

return;

}

/*玩家1获胜界面*/

p1win()

25

{

printf("玩家1获胜");

return;

}

/*玩家2获胜界面*/

p2win()

{

printf("玩家2获胜");

return;

}

/*帮助*/

void help()

{

system("cls");

printf("\t本程序采用19*19的游戏格式\n\n");

printf("\t输入格子的坐标下子: 先横坐标后纵坐标。比如输入:GG\n\n");

printf("\t输入out(退回主菜单)、back(悔棋)、lose(认输)\n\n");

}

26

/*主函数*/

int main()

{

system("color f1");

while(1)

{

printf("\n\t-----C Programming Language课程作业:五子棋-----\n\n");

printf("\t\t 1.开始游戏\n");

printf("\t\t 2.帮助\n");

printf("\t\t 3.退出\n");

printf("\n\t请选择:");

L:k=scanf("%d",&i);

switch(i)

{

case 1: startGame(); break;

case 2: help(); break;

case 3: return 0;

default:printf("\t 无此选项\n");break;

}

}

}

/*显示、刷屏*/

void printState()

27

{

char p='A';

system("cls");

printf("\t棋盘如下:\n\n");

printf("\t ");

for(i=0;i

{

printf("%c ",p+i);

}

printf("\n\t");

for(i=0;i

{

printf("%c ",p+i);

for(j=0;j

{

printf("%c ",state[i][j]);

}

printf("%c \n\t",p+i);

}

printf(" ");

for(i=0;i

{

printf("%c ",p+i);

}

printf("\n");

}

28

8 总结

C语言课程设计时一次对我们c语言学习的综合检验,它要求我们将所学的c语言代码进行综合运用,设计出一个简单的系统,这不仅是对我们基础知识的检验,还考验我们的动手动脑以及团队协作能力,在这一年学习中要将这些基础知识掌握已经不容易了,在这么短的时间又要做出一个系统更是一次重大的挑战,然而只有迎难而上才能收获成功,做出一个完整的系统。

回顾这次课程设计,至今我感慨颇多。很多的知识只是停留在基本的应用上,当需要结合使用时,往往出现无从入手的情况。在C语言课程设计的过程中,让我深深体会到了这点。一些细节的地方没有看清楚,或者思考妥当,就无法让系统运行,而当一系列调试后,程序能够运行。

通过对各子程序的设计与优化,本程序完成了五子棋软件的主体的设计与制作,基本达到了使用五子棋软件的核 心要求。然而程序还有一些不足之处,首先,程序在判断胜负后无法显示第五枚棋子,输入五子连环的第五个棋子坐标之后直接跳出了重新开始的界面,这是由程序的显示原理造成的;其次,程序的界面过于简陋,而且坐标输入操作也不利于玩家使用。

对于这次课程设计我很不满意,没有达到自己想要的效果,系统中还存在着许多的漏洞,在本次课程设计过程中我也发现了自己的很多缺点,比如做事不认真,粗心大意,考虑问题不够全面等。最后,谢谢老师的教导。

参考文献

[1] 五 子 棋 [EB].

http://baike.baidu.com/view/2697.htm.

[2] C语言制作五子棋[EB].

http://www.vcworld.net/news/200905/022217.html

[3] C语言五棋源代码 设计报告[EB].

http://wenku.baidu.com/view/e253a2c66137ee06eff91859.html

29

[4] C语言五子棋算法[EB].

http://www.4oa.com/Article/html/6/31/445/2005/1541 3.htm

30

注:实习成绩由指导教师或答辩小组评定出成绩,分优秀、良好、中等、及格、不及格五级,分别给小组的每个成员打分。

31

32

德州学院信息管理学院

课程设计报告

实习名称 自主学习能力 设计题目 五子棋小游戏 实习时间 2015.04.01--2014.04.30 专业班级 14级计算机科学与技术 指导老师 曹金凤 教学单位

小组分工情况:

二〇一四年五月二十五日

i

目 录

1 实习目的 ................................................................ 2 2 需求分析 ................................................................ 2 3 概要设计 ................................................................ 2 3.1 游戏背景 ............................................................ 2 3.2 游戏玩法 ............................................................ 3 3.3 程序需求分析 ........................................................ 3 3.4 开发平台 ............................................................ 3 3.5程序流程设计 ........................................................ 4 4 棋盘与棋子的生成 ........................................................ 5 4.1引言 ................................................................ 5 4.2 程序语句 .......................................... 错误!未定义书签。 5 棋子移动与落子 .......................................................... 6 5.1引言 ................................................................ 6 5.2程序语句 ............................................................ 6 6 胜负判断 ............................................................... 16 6.1引言 .............................................. 错误!未定义书签。 6.2程序设计 ........................................................... 17 7 调整改进 ............................................................... 18 7.1引言 ............................................................... 18 7.2程序功能及调整 ..................................................... 18 7.3总程序语句 ......................................................... 19 8 总结 ................................................................... 28 参考文献: ............................................................... 29

ii

五子棋小游戏的设计与实现

1 实习目的

(1)熟练的运用计算机语言,培养了对计算机编程的热爱程度. (2)学会怎样用c语言做一个完整的系统。 (3)掌握c语言的编辑,链接,运行等环节。

(4)掌握c语言中链表的建立,插入,删除,保存节点。 (5)熟练掌握for while do-while循环语句的使用。

(6)熟练掌握函数的定义、说明、参数传递及嵌套和递归调用方法。 (7)提高遇到困难解决困难的能力。 (8)提高书写代码的速度与正确率。

(9)独立实践,将课本上的理论知识和实际有机的结合起来,锻炼学生的分析解决实际问题的能力,提高学生适应实际,实践编程的能力。

2 需求分析

目前,随着计算机网络的的发展,PK已经成为现在人生活的一部分,人们 以不同的方式通过网络来娱乐,休闲。以计算机技术和网络技术为核心的现代网络技术已经在现实生活和生产中得到了广泛的使用,休闲类网络游戏集趣味性,娱乐性,互动性和益智性于一体,已经成为多数人群的休闲方式,也为多数人所喜好。当然,为了满足没有网络同样能娱乐的要求,许多小游戏做成了单机和网络的双功能。

3 概要设计

3.1 游戏背景

五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;它既有简单易学的特性,为人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既

3

有“场”的概念,亦有“点”的连接。它是中西文化的交流点,是古今哲理的结晶。

3.2 游戏玩法

五子棋是一种两人对弈的纯策略 型棋类游戏,五子棋棋子分为黑白两色,棋盘为19×19,棋子放置于棋盘线交叉点上或网格中。两人对局,各执一色,轮流下一子,先将横、竖或斜线的5个同色棋子连成不间断的一排者为胜。

3.3程序需求分析

根据功能需求,将程序分为图形显示、玩家控制、胜负判断和系统帮助四个模块,以下分析各模块的需求。

图形显示模块:程序开始运行时,给出欢迎界面;游戏开始后要求生成19×19的棋盘图像,并在棋盘上方提示 当前落子方棋子颜色,游戏进行过程中,要求实时显示棋盘上已落下的棋子;分出胜负后,要求给出游戏结束画面。 玩家控制模块:程序开始时,需玩家确定而后开始游戏;游戏过程中,两个玩家通过不同的按键移动光标,选择落子;游戏结束时,有玩家选择是否开始新棋局。

胜负判断模块:实时监测棋盘上棋子,一旦某一色棋子出现五子连线,终止游戏程序,弹出该色玩家胜出界面。

系统帮助模块:弹出窗口,窗口中 显示帮助信息,包括棋子移动与落子按 键介绍,获胜方式等。

除以上主要模块之外,程序中还可以添加其他辅助程序,如中途退出等。程序的关键在于胜负判断模块,该模块的设计直接关系到程序的运行速率和运行结果的正确与否。

3.4 开发平台

系统: Windows 7 旗舰版(64位)

处理器: AMD A8-5545M APU with Radeon(tm) HD Graphics 1.70GHz

4

内存: 4.00 GB

程序开发软件:Microsoft Visual C++ 6.0 文档编写:Microsoft Word 2010

3.5 程序流程设计

根据程序需求分析结果,可以得出程序的总体结构图如图1:

图1 程序总体流程图图

程序总体流程图如图2:

5

图2 程序总体设计图

4.棋盘与棋子的生成

4.1引言

根据五子棋的基本规则,棋盘采用19×19方格棋盘,棋子为黑白二色圆形棋子;游戏进行过程中棋盘始终显示,落子后棋子在落子处始终显示;棋盘在程序结束时消失,已落下的棋子在 程序结束时或开始新游戏是消失。

4.2程序语句

棋盘的显示由游戏开始与结束部分控制,棋子的显示与保留由玩家操控部分决定。

board() /*画棋盘*/ { setfillstyle(1,6); bar(120,50,520,450); setfillstyle(1,14); bar(540,50,620,150); bar(20,50,100,150); for(k=0;k

{moveto(140+20*k,70);linerel(0,360);

moveto(140,70+20*k);linerel(360,0); }

moveto(240,170); setcolor(5); settextstyle(3,0,4); outtextxy(50,60,"P1"); outtextxy(560,60,"P2"); }

white() /*画白棋*/ {

setcolor(7);

setfillstyle(1,7);

circle(getx(),gety(),9); fill(getx(),gety(),7); }

black() /*画黑棋*/ {

6

setcolor(0);

setfillstyle(1,0);

circle(getx(),gety(),9); fill(getx(),gety(),0); }

5棋子移动与落子

5.1引言

棋子的移动与落子有键盘上按键控制,本程序选取1P按键为W、S、A、D和空格键,2P按键为↑、↓、←、→和回车键,分别代表上移、下移、左移、右移光标和落子。在光标移动的过程中,光标按照玩家按键移动;在玩家按下落子按键后,程序自动调用棋子显示子程序和判断胜负子程序。1P、2P的落子后,程序会为落子处的数组元素赋一个特定值,用于判定胜负。

5.2程序语句

void p1move() /*玩家1的移动*/ {

switch(bioskey(0)) {

int sum=0;

case ESC: {closegraph(); exit(0);}/*如果按键为ESC就退出游戏 */

case SP:/*落子*/ if(a[X][Y]==6) {

p1del(); p2turn();

7

a[X][Y]=0; sum++; white(); p2move(); if(sum>=5) win(); }

else p1move();

case A: /*向左移*/ if(a[X][Y]==0) {

if(getx()==140)

moveto(520,gety()); moverel(-20,0); white(); }

else if(a[X][Y]==1) {

if(getx()==140) moveto(520,gety()); black();moverel(-20,0); white(); } else {

if(getx()==140)

8

moveto(520,gety()); moverel(-20,0); white(); } p1move(); case D: /*向右移*/ if(a[X][Y]==0) {

if(getx()==500) moveto(120,gety()); moverel(20,0); white();} else if(a[X][Y]==1) {

if(getx()==500) moveto(120,gety()); black();moverel(20,0); white(); } else {

if(getx()==500) moveto(120,gety()) ; moverel(20,0); white(); }

9

p1move(); case W: /*向上移*/ if(a[X][Y]==0) {

if(gety()==70) moveto(getx(),450); moverel(0,-20); white(); }

else if(a[X][Y]==1) {

if(gety()==70) moveto(getx(),450); black(); moverel(0,-20); white(); } else {

if(gety()==70) moveto(getx(),450); moverel(0,-20); white(); } p1move();

case S: /*向下移*/

10

if(a[X][Y]==0) {

if(gety()==430) moveto(getx(),50); moverel(0,20); white(); }

else if(a[X][Y]==1) {

if(gety()==430) moveto(getx(),50); black(); moverel(0,20); white(); } else {

if(gety()==430) moveto(getx(),50); moverel(0,20); white(); } p1move(); default: p1move(); }

11

}

void p2move() /*玩家2的移动*/ {

switch(bioskey(0)) /*如果按键为ESC就退出游戏*/ {

int sum=0;

case ESC: {closegraph(); exit(0);} case ENTER: /*落子*/ if(a[X][Y]==6) {

p2del(); p1turn(); a[X][Y]=1; sum++; black(); p1move(); if(sum>=5) win(); } else p2move(); case LEFT: /*向左移*/ if(a[X][Y]==1) {

if(getx()==140) moveto(520, gety());

12

moverel(-20,0); black(); }

else if(a[X][Y]==0) {

if(getx()==140) moveto(520,gety()); if(getx()==140) moveto(500,gety()); white(); moverel(-20,0); black(); } else {

if(getx()==140) moveto(520,gety()); moverel(-20,0); black(); } p2move();

case RIGHT: /*向右移*/ if(a[X][Y]==1) {

if(getx()==500) moveto(120,gety());

13

moverel(20,0); black(); }

else if(a[X][Y]==0) {

if(getx()==500) moveto(120,gety()); white(); moverel(20,0); black(); } else {

if(getx()==500) moveto(120,gety()); moverel(20,0); black(); } p2move();

case UP: /*向上移*/ if(a[X][Y]==1) {

if(gety()==70) moveto(getx(),450); moverel(0,-20); black();

14

}

else if(a[X][Y]==0) {

if(gety()==70) moveto(getx(),450); white(); moverel(0,-20); black(); } else {

if(gety()==70) moveto(getx(),450); moverel(0,-20); black(); } p2move();

case DOWN: /*向下移*/ if(a[X][Y]==1) {

if(gety()==430) moveto(getx(),50); moverel(0,20); black(); }

else if(a[X][Y]==0)

15

{

if(gety()==430) moveto(getx(),50); white(); moverel(0,20); black(); } else {

if(gety()==430) moveto(getx(),50); moverel(0,20); black(); } p2move(); default: p2move(); } }

6胜负判断

6.1引言

胜负判断模块是程序的关键,该模块的设计直接关系到程序的运行速率和运行结果的正确与否。

本函数根据每次落子的位置,分别向上、下、左、右、左上、左下、右上、右下八个 方向判断是否有相同颜色的棋子连成五子,如果成立,游戏就结束,并显示提示信息,否则继续落子。

16

以下简析本程序流程:如表1所示,令当前落子点坐标为(X,Y),表中 i=X-4, j=Y-4,由获胜条件可以知,通过判断(X,Y)上、下、左、右、斜上、斜下八个方向上是否有连续的5个子即可得出是否获胜结果。在游戏开始时,将棋盘初始化,即将棋盘抽象为一个19*19的数组,数组中每个元素设为某一指定初始值(如8)。1P落子时,将数组内相应坐标处元素赋值为0;2P落子时,将数组内相应坐标处元素赋值为1。当(X,Y) 上、下、左、右、斜上、斜下八个方向某5个连续的子所对应的数组中元素之和等于0时,1P获胜;当(X,Y) 上、下、左、右、斜上、斜下八个方向某5个连续的子所对应的数组中元素之和等于5时,2P获胜。棋盘上的所有格子都被占满时,必有181个1P棋子和180个2P棋子,此时对应数组中所有项之和为180,并且游戏过程中对应数组中所有项之和只可能在这种状况下为180,所以可以用这一条件判断是否和棋。

表1 胜负判断表

为减少程序的运算,还可以将某些特殊情况排除在外。当落子数不大于8时,既不用判断胜负,也不用判断和棋与否,这部分功能在第二章移动与落子程序中实现。此外,还可以通过对落子次数的统计判断是否满足和棋条件,从而减少大量运算,即当判断177次胜负后出现和棋。

6.2程序设计

void win() /*判断输赢*/ {

17

int sum1,sum2,sum3,sum4,sum=1,n,i,j; for(i=X-4,j=Y-4,n=0;i

sum1=a[i][Y]+a[i+1][Y]+a[i+2][Y]+a[i+3][Y]+a[i+4][Y];

sum2=a[i][j]+a[i+1][j+1]+a[i+2][j+2]+a[i+3][j+3]+a[i+4][j+4]; sum3=a[X][j]+a[X][j+1]+a[X][j+2]+a[X][j+3]+a[X][j+4];

sum4=a[i][j+8+n]+a[i+1][j+7+n]+a[i+2][j+6+n]+a[i+3][j+5+n]+a[i+4][j+4+n]; if(sum1==5||sum2==5||sum3==5||sum4==5) p2win(); if

(sum1==0||sum2==0||sum3==0||sum4==0) p1win(); } sum++ if(sum==177) heqi(); }

7调整改进

7.1引言

前6章分别论述了五子棋C语言程序中的四大主要模块,但要生成可执行的程序,则还需将这些模块有机地结合起来。在结合的过程中,需要综合运 用函数调用、函数间书序传递和全局变量等知识。

18

7.2程序功能及调整

为满足实际操作需求,增加程序的兼容性与稳定性,在编写可执行程序的过程中,必须对原有各功能模块进行整合并添加或调整部分功能。

为方便玩家使用本程序,在程序中增加了“悔棋”、“认输”和“退出”功能,玩家可以通过在游戏构成中输入相关指令实现这些功能,具体语句见附录。

为增强程序的兼容性和实用性,在最终的可执行程序中还对原有模块进行了其他修改。

在调试的过程中,发现bios.h 和graphics.h两个头文件只有在Turbo C的编译环境下才能顺利执行,因此,使用bios.h和graphics.h的程序兼容性不高,因此,舍弃使用这两个头文件的图像显示模块,转而使用具有较高兼容性的全屏打印刷新显示块。后者虽然在视觉效果上不如前者,然而它可以在任何Windows系统下工作,而这比视觉效果重要得多。

在调试过程中,发现每当1P在最外圈落子时,系统即可弹出1P获胜的结果,这是由于win函数中是通过对落子点及其周围的若干点求和来判断是否获胜的。当1P在最外圈落子时,棋盘外的点被程序当做0处理,加上落子时被赋值为0的一点,正好满足1P获胜的条件,故而引发错误。改进方法:将用于判断输赢的数组a由原来的19*19改为21*21,并将第0、20行及第0、20列中所有元素赋值为6;再将被这四组元素包围的一个19*19的区间对应到棋盘上的19*19格,即可解决原有问题。

在调试的过程中,还发现原有模块中的按键操作过于复杂,综合兼容性考虑,舍弃原有的光标操作模式,改用输入坐标的操作模式,这样做从某种程度上降低了程序的可操作性,但提高了程序的可实现性与兼容性。

7.3总程序语句

/*函数、变量定义*/

#include #include #include #include

19

#define N 19 int win(int m, int l); void printState(); p1win(); p2win(); heqi(); void help(); int i,j,k,size=N; int isBlack=1; char state[N][N]; int a[N+2][N+2]; char x,y,temp[10]; char c; int z;

/*初始化及指令输入*/

void startGame() {

int m,n,w; for(i=0;i

for(j=0;j

state[i][j]='_'; a[i][j]=6;

20

}

}

printState();

while(1)

{

printf("\n\t请%s方下子:",isBlack?"黑":"白");

fflush(stdin);

scanf("%s",temp);

if(!strcmp(strupr(temp),"OUT"))

{

system("cls");

return;

}

/*悔棋 */

if(!strcmp(temp,"BACK"))

{

i=x-'A';

j=y-'A';

state[i][j]='_';

printState();

isBlack=!isBlack;

continue;

}

if(!strcmp(temp,"LOSE"))

21

/*认输*/

{

printf("\n\t%s方认输,%s方胜!\n\n",isBlack?"黑":"白",isBlack?"白":"黑"); return;

}

x=temp[0];

y=temp[1];

/*避免下面相减的数组越界。*/

if(x'S'||y'S')

{

printf("\t输入有误,请输入属于或正确的口令。\n");

continue;

}

i=x-'A';

j=y-'A';

if(state[i][j]!='_')

{

printf("\t提示:该位置已经有子,请重新指定坐标!");

continue;

}

c=isBlack?'1':'2';

z=isBlack? 0:1;

22

state[i][j]=c;

a[i+1][j+1]=z;

m=i+1;

n=j+1;

w=win(m,n);

if(!w)

{

printState();

isBlack=!isBlack;

}

else

{

return;

}

}

}

/*判断输赢*/

int win(int m, int l)

{

int

sum1,sum2,sum3,sum4,sum=1,n,i,j,X,Y,w;

w=0;

X=m;

Y=l;

23

for(i=X-4,j=Y-4,n=0;i

{

sum1=a[i][Y]+a[i+1][Y]+a[i+2][Y]+a[i+3][Y]+a[i+4][Y];

sum2=a[i][j]+a[i+1][j+1]+a[i+2][j+2]+a[i+3][j+3]+a[i+4][j+4];

sum3=a[X][j]+a[X][j+1]+a[X][j+2]+a[X][j+3]+a[X][j+4];

sum4=a[i][j+8+n]+a[i+1][j+7+n]+a[i+2][j+6+n]+a[i+3][j+5+n]+a[i+4][j+4+n];

if(sum1==5||sum2==5||sum3==5||sum4==5)

{

p2win();

w=1;

}

if

(sum1==0||sum2==0||sum3==0||sum4==0)

{

p1win();

w=1;

}

}

sum1=0;

sum2=0;

sum3=0;

sum4=0;

sum++;

24

if(sum==177)

{

heqi();

w=1;

}

return w;

}

/*和棋界面*/

heqi()

{

printf("和棋");

return;

}

/*玩家1获胜界面*/

p1win()

25

{

printf("玩家1获胜");

return;

}

/*玩家2获胜界面*/

p2win()

{

printf("玩家2获胜");

return;

}

/*帮助*/

void help()

{

system("cls");

printf("\t本程序采用19*19的游戏格式\n\n");

printf("\t输入格子的坐标下子: 先横坐标后纵坐标。比如输入:GG\n\n");

printf("\t输入out(退回主菜单)、back(悔棋)、lose(认输)\n\n");

}

26

/*主函数*/

int main()

{

system("color f1");

while(1)

{

printf("\n\t-----C Programming Language课程作业:五子棋-----\n\n");

printf("\t\t 1.开始游戏\n");

printf("\t\t 2.帮助\n");

printf("\t\t 3.退出\n");

printf("\n\t请选择:");

L:k=scanf("%d",&i);

switch(i)

{

case 1: startGame(); break;

case 2: help(); break;

case 3: return 0;

default:printf("\t 无此选项\n");break;

}

}

}

/*显示、刷屏*/

void printState()

27

{

char p='A';

system("cls");

printf("\t棋盘如下:\n\n");

printf("\t ");

for(i=0;i

{

printf("%c ",p+i);

}

printf("\n\t");

for(i=0;i

{

printf("%c ",p+i);

for(j=0;j

{

printf("%c ",state[i][j]);

}

printf("%c \n\t",p+i);

}

printf(" ");

for(i=0;i

{

printf("%c ",p+i);

}

printf("\n");

}

28

8 总结

C语言课程设计时一次对我们c语言学习的综合检验,它要求我们将所学的c语言代码进行综合运用,设计出一个简单的系统,这不仅是对我们基础知识的检验,还考验我们的动手动脑以及团队协作能力,在这一年学习中要将这些基础知识掌握已经不容易了,在这么短的时间又要做出一个系统更是一次重大的挑战,然而只有迎难而上才能收获成功,做出一个完整的系统。

回顾这次课程设计,至今我感慨颇多。很多的知识只是停留在基本的应用上,当需要结合使用时,往往出现无从入手的情况。在C语言课程设计的过程中,让我深深体会到了这点。一些细节的地方没有看清楚,或者思考妥当,就无法让系统运行,而当一系列调试后,程序能够运行。

通过对各子程序的设计与优化,本程序完成了五子棋软件的主体的设计与制作,基本达到了使用五子棋软件的核 心要求。然而程序还有一些不足之处,首先,程序在判断胜负后无法显示第五枚棋子,输入五子连环的第五个棋子坐标之后直接跳出了重新开始的界面,这是由程序的显示原理造成的;其次,程序的界面过于简陋,而且坐标输入操作也不利于玩家使用。

对于这次课程设计我很不满意,没有达到自己想要的效果,系统中还存在着许多的漏洞,在本次课程设计过程中我也发现了自己的很多缺点,比如做事不认真,粗心大意,考虑问题不够全面等。最后,谢谢老师的教导。

参考文献

[1] 五 子 棋 [EB].

http://baike.baidu.com/view/2697.htm.

[2] C语言制作五子棋[EB].

http://www.vcworld.net/news/200905/022217.html

[3] C语言五棋源代码 设计报告[EB].

http://wenku.baidu.com/view/e253a2c66137ee06eff91859.html

29

[4] C语言五子棋算法[EB].

http://www.4oa.com/Article/html/6/31/445/2005/1541 3.htm

30

注:实习成绩由指导教师或答辩小组评定出成绩,分优秀、良好、中等、及格、不及格五级,分别给小组的每个成员打分。

31

32


相关内容

  • 五子棋课程设计及源代码
  • 五子棋 课程设计项目研究报告 一 项目简介 1.1 项目名称 简单的多用户五子棋游戏程序 1.2 开发人员 1.3 指导教师 二 项目设计要求 2.1 项目要求 通过课程设计完成一个五子棋游戏,程序中要实现GUI 图形界面的棋盘.黑子.白子功能,实现开始.重来.认输等功能,实现输赢自动判别算法,实现 ...

  • 五子棋课程纲要
  • 五子棋课程纲要 开发背景 五子棋有着悠久历史,其流传或许始于尧舜.下五子棋意在锻炼智慧,纯洁性情.随着社会的发展,给越来越多的孩子提供了接近五子棋的机会.也有越来越多的家长重视起五子棋对孩子成长所起的作用.社会也给予五子棋更多的关注,研究表明,五子棋是很好的素质教育工具.我们北台小学的办学理念正是为 ...

  • 校本课程介绍
  • 佟楼中学校本课程介绍 科技类: 航模 以培养学生动手动脑的能力,丰富学生的课余生活,陶冶学生的情操,促进学生全面发展为宗旨.对学生学习航空知识.增长实践创新能力.培养科学素养.团队合作意识.增强爱国主义精神都具有积极作用,是贯彻实施青少年学生素质教育的一个极好途径和载体. 电脑设计 为培养学生学习使 ...

  • web前端研发工程师-简历示例
  • 服桥 凛言苯挖喻仟 质剃魔泊哟 济虏振冶水妓 闭家铆雄饰 议阑糠惮掌牡 教绸矿弯故 涎蜡慢趋抗 彭冕陷蜜闭各 枕格凛西御 股尊拥席泞锥 搜智虫阔酸 跪曝遮气锻控 僻唆喂殷俺 糟点英脾拈褐 番蓟话勤岩 药蒸滩桩喉胜 镇碌逃井遮 健抑仆轴黄 酒靴巍寄蹦乃 影匪学娄光 歉矽爱刃纷藕 嗽比落哈粗 呆淬楷婶沟 ...

  • 五子棋程序设计报告
  • 宜宾学院 面向对象课程设计 学院:_计算机与信息工程学院_班级: 2014级6班 学生姓名: 郑亮学号:141106020 设计地点(单位)_________宜宾学院__________ 设计题目:____________双人五子棋_____________ 完成日期:2015年 12月 5日 目录 ...

  • 幼儿园课程资源棋类游戏
  • 幼儿园课程资源开发 --棋类游戏 广饶县稻庄镇中心幼儿园 张静 棋类游戏利于开发幼儿的多元智能,培养幼儿的抗挫能力,形成良好的合作与竞争意识.在棋类活动中,有许多有价值的教育资源,它涉及到体.智.德.美等多方面的教育资源,以往我们开展的棋类游戏只局限于棋盘,让孩子们投入到区域活动中,往往忽视了更多的 ...

  • 五子棋小组活动计划方案等许秀芹
  • 小学五子棋教学计划 为了丰富学生的课外生活,陶冶学生的情操,我校每周三下午开设了学生自主学习日课程.五子棋是科学.文化.艺术.竞技融为一体的智力体育项目.有助于青少年智力开发,逻辑思维和想象能力的培养,同时又能培养学生的耐心细心等意志品质,增进友谊,陶冶高雅情操.因此本学期我们开设五子棋教学活动. ...

  • N多毕业设计题目
  • 基于Ajax技术的WEB应用的设计 又快到毕业的时候了,大家该准备做毕业设计了.大学问问特意收集了一些毕业设计(论文)的题目,供大家选择. VB售楼管理系统 VB无纸化考试系统 VB小区物业管理系统 VB航空公司管理信息系统 VB计算机机房管理系统 VB房地产评估系统VB+SQL2000 VB光盘信 ...

  • 二年级校本课程[三字经]教学工作总结
  • 二年级校本<三字经>课程的教学工作 中华民族历史悠久,文化经典更是灿若星河.这些经典美文,凝聚了先贤的大智大慧,睿语哲思,浓缩了华夏五千年的思想精粹,感染熏陶了一代又一代中国人,是古人留给我们最为宝贵的精神财富. 为了丰富我校的人文底蕴,启迪学生的智慧,本学年,我校开发了以<三字经 ...