当前位置:   article > 正文

三子棋小游戏,实现人机对战,电脑可做简单拦截(C语言版)_memset(board,'',row*col)

memset(board,'',row*col)

前言

相信很多同学在学了一小部分C语言之后,总是对自己的能力有疑问,不知道自己现在是什么水平,大家可以尝试一下博主的简易的三子棋游戏,大家可以去练练手。下面是博主的三子棋游戏实现的主要步骤(博主的篇幅可能较大,但是很详细,希望大家能看完。)


一、具体步骤

1.先创建一个二维数组,用来存放棋子。

2.初始化数组,让这个数组全为空格

3.打印棋盘

4.玩家下棋

5.电脑下棋

6.判断输赢

二、代码的实现

菜单的展示

1.第一步是打印菜单,选择1是开始游戏,选择2是退出游戏

  1. void menu()
  2. {
  3. printf("########################\n");
  4. printf("#######1.开始游戏#######\n");
  5. printf("#######2.退出游戏#######\n");
  6. printf("########################\n");
  7. }

2.第二步是在打印玩菜单之后,要用循环语句来实现游戏(用循环语句的原因是:可以多次玩,而不是玩一次就玩完了) 

  1. int main()
  2. {
  3. int input = 0;
  4. srand((unsigned int)time(NULL));
  5. printf("请输入数字:->\n");
  6. do
  7. {
  8. menu();
  9. scanf("%d", &input);
  10. switch (input) {
  11. case 1:
  12. printf("开始游戏\n");
  13. game();
  14. break;
  15. case 2:
  16. printf("退出游戏\n");
  17. input = 0;
  18. break;
  19. default:
  20. printf("选择错误,请重新选择\n");
  21. break;
  22. }
  23. } while (input);
  24. return 0;
  25. }

这里让玩家从键盘输入的值来作为循环判断的条件,这样就可以实现让玩家选择玩还是不玩 (这里的srand可能大家不知道是什么,不要着急,下面会讲它的具体使用)

主体代码的展示 

下面的是主体代码,这里博主采用了分模块的形式去完成这个游戏(模块化的好处是可以让整个程序看起来有层次感,让大家更容易看懂理解)

1"game.h"头文件 

 所有要用到的方法的声明、引用的头文件和常量的声明,博主都放在了"game.h"的头文件中

  1. #pragma once
  2. #define ROW 3
  3. #define COL 3
  4. #include<stdio.h>
  5. #include<string.h>
  6. #include<time.h>
  7. #include<stdlib.h>
  8. //键盘的初始化
  9. void Initboard(char board[ROW][COL], int row, int col);
  10. //棋盘的打印:
  11. void Displayboard(char board[ROW][COL], int row, int col);
  12. //玩家下棋
  13. void Player_move(char board[ROW][COL], int row, int col);
  14. //电脑下棋
  15. void Computer_move(char board[ROW][COL],int row,int col);
  16. //判断胜负
  17. char Win(char board[ROW][COL], int row, int col);
  18. //判断平局
  19. int Full(char board[ROW][COL], int row, int col);
  20. //电脑拦截
  21. void simplealgorithm(char board[ROW][COL], int row, int col, int* x,int* y);

 这里把棋盘的行(ROW)和列(COL)采用了宏定义,就是为了以后方便其他的程序猿对棋盘的扩展,到时候要拓展只能在这里改一下就可以了,而不用去每个用到行和列的地方去逐一更改,这样节约了大把时间。

2."game.c"源文件

这里放了所有在"game.h"中声明的方法的实现

  1. #include"game.h"
  2. void Initboard(char board[ROW][COL],int row,int col)
  3. {
  4. memset(board, ' ', row * col);
  5. }
  6. void Displayboard(char board[ROW][COL], int row, int col)
  7. {
  8. int i = 0;
  9. for (i = 0; i < row; i++)
  10. {
  11. int j = 0;
  12. for (j = 0; j < col; j++)
  13. {
  14. //打印数据
  15. printf(" %c ", board[i][j]);
  16. if (j < col - 1)
  17. {
  18. printf("|");
  19. }
  20. }
  21. printf("\n");
  22. //打印分割行
  23. if (i < row - 1)
  24. {
  25. for (j = 0; j < col; j++)
  26. {
  27. printf("---");
  28. if (j < col - 1)
  29. printf("|");
  30. }
  31. printf("\n");
  32. }
  33. }
  34. }
  35. void Player_move(char board[ROW][COL], int row, int col)
  36. {
  37. int x = 0;//棋子的坐标
  38. int y = 0;
  39. printf("玩家下棋:\n");
  40. while (1)
  41. {
  42. scanf("%d %d", &x, &y);
  43. if ((x >= 1) && (x <= row) && (y >= 1) && (y <= col))
  44. {
  45. if (board[x-1][y-1] == ' ')
  46. {
  47. board[x-1][y-1] = '*';
  48. break;
  49. }
  50. else
  51. {
  52. printf("该位置已经有棋子,请重新输入坐标\n");
  53. continue;
  54. }
  55. }
  56. else
  57. printf("坐标非法,请重新输入\n");
  58. }
  59. }
  60. void Computer_move(char board[ROW][COL], int row, int col)
  61. {
  62. int x = 0, y = 0;
  63. printf("电脑下棋:\n");
  64. while (1)
  65. {
  66. x = rand() % row;//用rand函数产生0到row-1之间的随机数
  67. y = rand() % col;//用rand函数产生0col-1之间的随机数
  68. simplealgorithm(board, row, col, &x, &y);
  69. again:
  70. if (board[x][y] == ' ')
  71. {
  72. board[x][y] = '#';
  73. break;
  74. }
  75. else
  76. {
  77. x = rand() % row;
  78. y = rand() % col;
  79. goto again;
  80. }
  81. }
  82. }
  83. char Win(char board[ROW][COL], int row, int col)
  84. {
  85. //返回*,代表玩家胜利,返回#,代表电脑胜利
  86. // 返回F,代表平局,返回C,代表继续
  87. //判断行
  88. for (int i = 0; i < row; i++)
  89. if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')
  90. return board[i][0];
  91. //判断列
  92. for (int i = 0; i < col; i++)
  93. if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')
  94. return board[0][i];
  95. //判断主对角线
  96. if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
  97. return board[1][1];
  98. //判断次对角线
  99. if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
  100. return board[1][1];
  101. //判断平局
  102. if (Full(board, ROW, COL))
  103. return 'F';
  104. else
  105. return 'C';
  106. }
  107. int Full(char board[ROW][COL], int row, int col)
  108. {
  109. //检查棋盘是否还有空格
  110. for(int i = 0; i < row; i++)
  111. {
  112. for (int j = 0; j < col; j++)
  113. {
  114. if (board[i][j] == ' ')
  115. {
  116. return 0;
  117. }
  118. }
  119. }
  120. return 1;
  121. }
  122. void simplealgorithm(char board[ROW][COL], int row, int col, int* x, int* y)
  123. {
  124. for (int i = 0; i <= row; i++)//
  125. {
  126. if ((board[i][0] == board[i][1] && board[i][0] == '*'))
  127. {
  128. *x = i;
  129. *y = 2;
  130. }
  131. else if ((board[i][1] == board[i][2] && board[i][1] == '*'))
  132. {
  133. *x = i;
  134. *y = 0;
  135. }
  136. else if ((board[i][0] == board[i][2] && board[i][1] == '*'))
  137. {
  138. *x = i;
  139. *y = 1;
  140. }
  141. }
  142. for (int i = 0; i <= col; i++)//
  143. {
  144. if ((board[0][i] == board[1][i] && board[0][i] == '*'))
  145. {
  146. *x = 2;
  147. *y = i;
  148. }
  149. else if ((board[1][i] == board[2][i] && board[1][i] == '*'))
  150. {
  151. *x = 0;
  152. *y = i;
  153. }
  154. else if ((board[0][i] == board[2][i] && board[0][i] == '*'))
  155. {
  156. *x = 1;
  157. *y = i;
  158. }
  159. }
  160. for (int i = 0; i <= col; i++)//对角线
  161. {
  162. if ((board[i][i] == board[i + 1][i + 1] && board[i][i] == '*'))
  163. {
  164. if (i == 0)
  165. {
  166. *x = 2;
  167. *y = 2;
  168. }
  169. else if (i == 1)
  170. {
  171. *x = 0;
  172. *y = 0;
  173. }
  174. }
  175. else if ((board[i][2] == board[i + 1][i + 1] && board[i][2] == '*'))
  176. {
  177. if (i == 0)
  178. {
  179. *x = 2;
  180. *y = 0;
  181. }
  182. else if (i == 1)
  183. {
  184. *x = 0;
  185. *y = 2;
  186. }
  187. }
  188. }
  189. }

1.其中的Initboard方法对数组进行初始化,博主用了一个memset方法,作用是在一段内存块中填充某个给定的值,第一个参数是要被填充的内存块,这里需要填充的是数组,所以就放入数组名就可以了,第二个参数是被填入的值是什么,这里要初始化为空格,所以填入空格就可以了,第三个参数是需要填充的大小,因为博主是3*3的棋盘,所以就填入ROW*COL就可以了(填入ROW*COL和好处是以后要更改填充的大小,直接改"game.h"中的宏定义即可)

2.其中的Displayboard方法是打印棋盘,大致的效果是下面这样的

 

3.其中的Player_move方法,我们写这个不仅要程序猿自己能玩,又要让不懂编程的人也能玩 ,所以这里没有用下标为0作为开始,而是从1开始,因为不懂编程的人不知道数组的下标是从0开始的,要考虑其他人的是怎样去下棋的(规定玩家下的棋子是'*')

 

4.其中的Computer_move方法,就是让电脑下棋,用了一个rand方法去产生一个随机的坐标,而rand方法的使用又要srand的配合 ,srand方法是用来设置rand方法产生一个随机数时的随机数种子,参数seed是整数,所以通常我们用time(NULL)的返回值来作为srand的参数,这样我们就可以得到一个随机数了,但是得到的随机数不是我们想要的(这里大家可以直接去试一试,看看产生的随机数,这里博主就不过多讲解了),所以我们要模上ROW和COL,这样我们就可以得到0-ROW-1之间的整数和0-COL-1之前的整数了。在其中还有一个电脑拦截的方法,就是让电脑阻止玩家,在快要连成一条线的地方去下。(规定电脑下得棋是'#')

5.其中的Win方法就比较简单了,就是去按照三子棋获胜的规则去书写的代码(某一行、某一列、主对角线、次对角线和平局这五种情况)

6.其中的F是用来判断平局的(主要的原理是看棋盘是否还有空格)

3."test.c"源文件

这里放了主函数和主函数中game方法的实现

  1. void game()
  2. {
  3. char board[ROW][COL];
  4. Initboard(board, ROW, COL);
  5. char ret = '0';
  6. while (1)
  7. {
  8. Player_move(board, ROW, COL);
  9. Displayboard(board, ROW, COL);
  10. ret = Win(board, ROW, COL);
  11. if (ret != 'C')
  12. {
  13. break;
  14. }
  15. Computer_move(board, ROW, COL);
  16. Displayboard(board, ROW, COL);
  17. ret=Win(board, ROW, COL);
  18. if (ret != 'C')
  19. {
  20. break;
  21. }
  22. }
  23. if (ret == '*')
  24. {
  25. printf("玩家胜利\n");
  26. }
  27. else if (ret == '#')
  28. {
  29. printf("电脑胜利\n");
  30. }
  31. else
  32. {
  33. printf("平局\n");
  34. }
  35. }

 在这里博主规定了,Win的返回值的具体意义:

'F'代表着平局;'C'代表着继续;'*'代表着玩家胜利;'#'代表着电脑胜利

最终的效果是这样的:

 

总结

这是博主做的第一个小游戏,做为小菜鸡的我,在编程的时候遇到了很多麻烦,但是庆幸都一一解决了。博主把自己的方法分享出来,希望大家能对博主进行指正,这样博主才能进步,欢迎大家发表自己的意见。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/1017767
推荐阅读
相关标签
  

闽ICP备14008679号