C语言 - 五子棋(无鼠标事件)

更新时间:2023-11-16 10:48:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

五子棋 C语言

目录

·五子棋内容简介 ·需求分析 ·系统设计 ·主模块 ·棋盘模块 ·下棋模块 ·判断输赢模块 ·信息模块

一. 五子棋内容简介

五子棋规则

⑴.对局双方各执一色棋子; ⑵.空棋盘开盘;

⑶.黑先,白后,交替下子,每次只能下一子;

⑷.棋子下定后,不得向其他点移动,不得从棋盘上拿掉或者拿起另落到别处; ⑸.黑棋的第一颗棋子可以下在棋盘的任意交叉点上; ⑹.轮流下子是双方的权利,但允许任何一方放弃下子权;

二. 需求分析

主要功能是实现两人之间的对弈,在画好的棋盘上,两个玩家轮流选择自己的落子坐标,

然后由五子棋系统自动识别判断游戏的进展,知道一方的五子连成一条线或者棋盘已经无法落子时游戏结束。

选定五子棋的棋盘大小为19*19,玩家可以在这个棋盘上选择落子坐标位置,通过在棋盘

上显示不同的符号来代替不同玩家所下的棋子,实心圆代表A玩家,空心圆代表B玩家。玩家每次落子之后游戏系统都会对落子位置进行检查,如果落子坐标输入有错应提示错误,并要求玩家继续输入。

当出现同一玩家五子连成一线时,无论是行、列或是对角线的五子连线,都表示玩家游戏

胜利,退出游戏。

三.系统设计

五个模块

·棋盘模块

该模块要求的功能是实现棋盘的显示及棋子的显示,在每次下棋后要对棋盘进行刷新,将棋盘的状态

变化为当前最新状态,然后等待另一个玩家下棋。

·下棋模块

该模块的功能是让玩家能够在棋盘上下棋,玩家每次选择好下棋的行和列坐标,并在该位置落子。下

棋模块将该坐标保存以备后面使用。

·判断输赢模块

其功能是玩家每次落子后对棋盘上的每一行,每一列进行判断,看是否有五子同时连成一线的,并据

此判断输赢。如果棋盘上已经无地方落子,则游戏为和棋退出。

·信息模块

其功能是进行提示信息的输出,包括欢迎信息,游戏结束提示及和棋提示信息等。 ·主模块

主模块的功能是调用各个模块协同工作来实现整个系统的功能。 棋盘模块

下棋模块

判断输赢模块 五子棋游戏

信息模块

主模块

四.主模块

在主模块中首先要定义系统中要使用的变量,还要根据功能调用相应的模块,通过宏定义和数组可以实现对棋盘和棋子坐标的控制。代码如下

/*******************棋盘大小****************/ #define N 19

/***************1为A子,2为B子***********/ int pieces[N][N]={0};

/***************1为A子,2为B子***********/ int flag=1;

1. pieces数组作为棋盘上每一个焦点坐标的状态

2. flag为全局变量,表示整个游戏进行的状态,值为1时,A玩家下棋;值为2时,B玩家下

棋 主模块的代码

/***************主函数***********/ void main() { int x,y;

//落子行列的坐标 //代表赢家 //计算落子数

//欢迎界面 //画棋盘

int winner; welcome(); DrawPanel(); {

//获取下子的行列坐标 x= zouqihang(); y= zouqilie(); x=x-1; y=y-1;

//判断是否可以落子 if(pieces[x][y] == 0 ) {

//可以落子 pieces[x][y] = flag; countpieces++; //改变游戏状态 if(flag == 1) { }else { }

//判断游戏是否继续 winner = check(x,y); if(winner==1) { {

//B赢了

printf(“恭喜B○赢了!\\n”); //A赢了

printf(“恭喜A●赢了!\\n”); break; flag = 1; flag = 2;

int countpieces = 0

while(countpieces

}else if(winner==2)

}

}

break;

}else{

//不能落子 printf(“ERROR!\\n”);

printf(“落子行列错误,请按任意键重新输入!\\n”); getchar(); getchar();

//重画棋盘 DrawPanel(); }

if(countpieces ==N*N) { }else {

over(); } }

//游戏结束

heqi();

//和棋

执行流程

1. 先调用欢迎模块welcome()显示欢迎界面,接着调用DrawPanel()函数将棋盘的初始界面画出来。 2. 玩家的下棋过程是通过while循环来实现的。while(countpieces

数就可以继续下子,否则退出循环。每次落子正确,落子总数countpieces就会增加一个。

3. 在while循环体中先调用zouqihang()和zouqilie()两个函数来获取落子的行坐标和列坐标,在得到玩家

落子坐标后,下一步就是判断该坐标是否可以落子,这就要根据pieces[x][y]的值来判断。当对应的数组元素pieces[x][y]的值为0时表示改位置可以落子,此时只要给pieces[x][y]变量赋值为当前游戏状态值(flag)就可以表示此处的落子事属于哪位玩家的。棋盘落子处的状态一旦改变了就必须更改游戏状态,表示轮到下一位玩家下棋了。通过if语句修改flag变量的值即可更改游戏状态。

4. 接下来是进行的是检查棋盘,判断现在是否分出了胜负,如果胜负已分,那么就输出胜负信息,在每

次循环的最后都要进行的一步是画棋盘。

5. 最后,通过落子数来判断是否是和棋还是游戏顺利结束,并输出相关信息。

开始

是否落子正确 欢迎 画棋盘 N 落子数

棋盘模块主要实现棋盘的刷新,每次只要棋盘有所变化都要重新画出棋盘,同时,在每次棋子

输出字符的时候,都需要判断该坐标是否有棋子以及是哪一玩家的棋子。 void DrawPanel() { 3 6

int count=1; int i,j;

system(“CLS”); for(i=0;i<=N;i++) {

if(i==0)

//清屏

//计数

16 18 19 23 27 }

}

{ }else { }

printf(“M”,count); count++; printf(““);

printf(“\\n”); count=1; { }

for(j=-1;j

printf(“\\n”);

else { }

if(pieces[i][j] == 0) {

printf(“.”); }else if(pieces[i][j]==1) { printf(“●”)}; else if(pieces[i][j] == 2) {printf(“○”);}

//根据落子情况输出相应的符号标志

if(j==-1) {

printf(“-”,count); count++;

//如果是第一列,输出字符

//重置count变量为1

for(i=0;i

//输出每一行

代码说明

1. 第三行定义的count变量实现了计数功能

2. 第五行使用清屏函数system(“CLS”),使用函数是需要引入头文件stdlib.h,每次调用该函数都会

清理屏幕上的内容。

3. 程序的6~16行的for语句用来输出列标志。如果有19列,那么就输出从1~19个序号。 4. 程序的18行将count变量置为一,用来输出行号。

5. 程序第19-41行的for循环语句用来输出棋盘上的每一行,包括行号及两方玩家棋子标志。 6. 程序第23~27的if语句用来输出每一行的行号,每次进入内层的for循环j的初始值都为-1,因此,

每次都要先执行该if语句用来输出该行的行号。注意到count变量每次都是自增的(count变量进入循环前的值为1),因此可以循环输出1~19行的行号。

7. 程序第28`40行是else语句,该语句的作用为根据落子的情况输出相应的符号标志。在else复合

语句中,对pieces[i][j]的值进行了判断,如果其值为0,则表示棋盘上该位置可以落子,此时输出“.”;如果pieces[i][j]的值为1,则表示该位置上已有棋子,且该棋子为玩家A的,对应输出“●”;如果pieces[i][j]的值为2,则表示棋盘上该位置已有棋子,且该棋子为B玩家的,因此输出B玩家棋子相对应的符号“○”。

8. 程序的39行表示次内层的for循环结束后都进行换行,即显示下一行的内容。

六.下棋模块

该模块的功能是获取用户输入的下棋坐标的位置,并通过对落子位置的判断,确保用户每次的落子位

置都是合法的和正确的,即都落在棋盘中。

1. /**********************走棋行*****************/ 2. int zouqihang() 3. { 4. int x; 5. if(flag == 1) 6. { 7. 8. }else 9. { 10. 11. }

12. printf(“请输入要走棋子所在的行数!\\n”); 13. printf(“x=”); 14. scanf(“%d”.&x); 15. while(x>N-1 || x<1) 16. { 17. 18. 19. 20. 21. }else 22. { 23. 24. }

25. printf(“请输入要走棋子所在的列数!\\n”); 26. printf(“x=”); 27. scanf(“%d”.&x); 28. } 29. return x; 30. }

31. /**********************走棋列****************/ 32. int zouqilie() 33. { 34. int y;

printf(“玩家B○”); printf(“ERROR!\\n”); if(flag == 1) {

printf(“玩家A●”); printf(“玩家B○”); printf(“玩家A●”);

35. if(flag == 1) 36. { 37. 38. }else 39. { 40. 41. }

42. printf(“请输入要走棋子所在列数!\\n”); 43. printf(“y=”); 44. scanf(“%d”,&y); 45. while(y>N-1 || y<1) 46. { 47. 48. 49. 50. 51. }else 52. { 53. 54. }

55. printf(“请输入要走棋子所在的列数!\\n”); 56. printf(“y=”); 57. scanf(“%d”.&y); 58. } 59. return y; 60. }

printf(“玩家B○”); printf(“ERROR!\\n”); if(flag == 1) {

printf(“玩家A●”); printf(“玩家B○”); printf(“玩家A●”);

代码说明

1. 2.

程序第2~30行定义了zouqihag()函数,用来检查用户输入的行是否在棋盘的正确范围内。该函数的返回值为用户输入的行号。

在zouqihang()函数中,首先根据flag变量中的值来确定当前应该是哪个玩家下棋。如果flag变量中的值为1,则轮到玩家A下棋;如果flag变量的值为2时,则轮到玩家B下棋。 3. 4.

程序14行是玩家想输入下棋的行。

程序第15~28行的while语句是用来对玩家输入行的合法判断的。如果输入的行数大于N-1或者小于1,都不正确,此时输出错误提示信息并再次要求用户输入合法的行号。知道用户输入正确的行号,此时退出while循环,否则会要求用户一直重新输入。 5.

程序的32~60行定义了zouqilie()函数,用来检查用户输入的列是否在棋盘的正确范围内,其他同2,3,4条一样。

七.判断输赢模块

判断输赢模块的作用是每次玩家落子后判断是否已分出胜负,如果是,则返回胜利者相关信息;如

果不是,则返回0。这里传入的参数是落子处的坐标,因为当一个玩家落子后,如果五子已经连成一条线,那么这五个棋子的坐标必定含有该落子处的坐标,因此每次只需要对落子处的行,列及斜行(左斜行和右斜行)进行检查就可以判断是否出现了五子连成一条线的情况。

其代码如下

1. /*返回1表示A赢;返回2表示B赢;否则继续*/ 2. int check(int x, int y) 3. { 4. //检查行 5. int count=1 6. int i=x,j = y; 7. j++; 8. //向右数

9. while(j

11. if(pieces[i][j]==pieces[x][y]) 12. { 13. 14. }else 15. { 16. 17. } 18. j++; 19. } 20. //向左数 21. j=y-1;

22. while(j>=0&&count<5) 23. {

24. if(pieces[i][j]==pieces[x][y]) 25. { 26. 28. { 29. 30. } 31. j--; 32. }

33. if(count==5) 34. {

35. return pieces[x][y]; 36. } 37. //检查列 38. i=x; 39. j=y; 40. count=1;

//返回pieces[x][y]中的值

//形成五子连成一条线的状态

break;

//退出循环

count++;

//五落子或不是同一玩家

27. }else

//判断是否有落子及是否为同一玩家

//退出上一个while循环时count小于5

break; count++;

//判断是否有落子及是同一玩家

//为count设置初始值

41. //往下数 42. i=i+1;

43. while(i

45. if(pieces[i][j]==pieces[x][y]) 46. { 47. 48. }else 49. { 50. 51. } 52. i++; 53. } 54. //往上数 55. i=N-1;

56. while(i>=0&&count<5) 57. {

58. if(pieces[i][j]==pieces[x][y]) 59. { 60. 62. { 63. 64. } 65. i--; 66. }

67. if(count==5) 68. {

69. return pieces[x][y]; 70. } 71. ,. 72. i=x; 73. j=y; 74. count=1; 75. //左斜往上 76. i=i-1; 77. j=j-1;

78. while(i>=0 && count<5) 79. {

80. if(pieces[i][j]==pieces[x][y]) 81. { 82. 83. }else 84. {

count++;

//返回pieces[x][y]中的值

//形成五子连成一条线的状态

break;

//退出循环

count++;

//五落子或不是同一玩家

61. }else

//判断是否有落子及是否为同一玩家

break; count++;

//判断是否有落子及是否为同一玩家

263. 264. 265. 266. 267. } { } i--; break; 268. if(count == 5) 269. { 270. 271. } 272. //左斜行 273. i=x; 274. j=y; 275. count = 1; 276. //左斜往上 277. i=i-1; 278. j=j-1; 279. while(i>=0 && j>=0 && count <5) 280. { 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. } 291. //左斜往下 292. i=x+1; 293. j=y+1; 294. while(i=0 && j= 0 && j

printf(\printf(\printf(\printf(\printf(\printf(\printf(\

*\\n\*\\n\*\\n\*\\n\

*\\n\ 和棋

*\\n\362. printf(\363. 364. 365. 366. } *\\n\

*\\n\*\\n\printf(\printf(\

printf(\367. //***********游戏结束******** 368. void over() 369. { 370. 371. 372. 373. 374. 375. 376. 377.

system(\printf(\printf(\printf(\printf(\printf(\printf(\printf(\

*\\n\*\\n\*\\n\*\\n\*\\n\*\\n\游戏结束

378. printf(\379. 380. 381. 382. } *\\n\

*\\n\*\\n\printf(\printf(\

printf(\383. //***********游戏开始******** 384. void welcome() 385. { 386. 387. 388. 389. 390. 391. 392. 393.

system(\printf(\printf(\printf(\printf(\printf(\printf(\printf(\

*\\n\*\\n\*\\n\*\\n\游戏开始

*\\n\

*\\n\394. printf(\*\\n\395. 396. 397. 398. 399. 400. } printf(\printf(\

*\\n\*\\n\printf(\printf(\getchar();

本文来源:https://www.bwwdw.com/article/t6hv.html

Top