• 【C语言】三子棋


     

    前言:

    三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小,三子棋在很多时候会出现和棋的局面。

    设计思路:

    先开一个test.c文件用来进行游戏的逻辑测试,再开一个game.h头文件和game.c文件分别用来进行函数声明和实现游戏的逻辑,然后就是打印菜单、生成棋盘、实现玩家下棋、实现电脑下棋、判断游戏的输赢、游戏优化。

    1. 打印菜单

    test.c

    1. void menu()
    2. {
    3. printf("***************************\n");
    4. printf("******** 1.play ********\n");
    5. printf("******** 2.exit ********\n");
    6. printf("***************************\n");
    7. }
    8. int main()
    9. {
    10. int input = 0;
    11. do
    12. {
    13. menu();
    14. printf("请选择>:");
    15. scanf("%d", &input);
    16. switch (input)
    17. {
    18. case 1:
    19. game();
    20. break;
    21. case 0:
    22. printf("退出游戏.\n");
    23. break;
    24. default:
    25. printf("输入有误,请重新输入.\n");
    26. }
    27. } while (input);
    28. return 0;
    29. }

    2. 生成棋盘

    2.1 初始化棋盘

    我们可以用空格将每一个格子初始化。

    test.c文件:

    1. board[ROW][COL] = { 0 };
    2. InitBoard(board, ROW, COL);

     game.c文件:

    1. void InitBoard(char board[ROW][COL], int row, int col)
    2. {
    3. for (int i = 0; i < row; i++)
    4. {
    5. for (int j = 0; j < col; j++)
    6. {
    7. board[i][j] = " ";
    8. }
    9. }
    10. }

    其中的ROW和COL是两个宏定义。

     game.h

    1. #define ROW 3
    2. #define COL 3

    2.2 打印棋盘

    打印棋盘时我们可以一些符号隔开不同的空格,这样就会使我们的棋盘更加美观。比如我们可以使用“|”将同一行的空格分开,用“-”将不同行的空格分开,这样我们就可以得到一个如下的九宫格了。

     

     game.c文件:

    1. void DisplayBoard(char board[ROW][COL], int row, int col)
    2. {
    3. for (int i = 0; i < row; i++)
    4. {
    5. for (int j = 0; j < col; j++)
    6. {
    7. printf(" ");
    8. if (j < col - 1)
    9. {
    10. printf("|");
    11. }
    12. }
    13. printf("\n");
    14. if (i < row - 1)
    15. {
    16. for (int j = 0; j < col; j++)
    17. {
    18. printf("---");
    19. if (j < col - 1)
    20. printf("|");
    21. }
    22. printf("\n");
    23. }
    24. }
    25. }

     3. 实现玩家下棋和电脑下棋

    为了游戏的可实行性,当玩家或电脑下完一个棋子后我们需要考虑以下两点:

    1.玩家或电脑所下的坐标是否在棋盘的范围内。

    2.玩家或电脑所下的位置是否已经被下过棋子了。

    依据上面的两点条件的我们需要分别写一个条件语句,判断玩家是否合法下棋。

    3.1 玩家下棋

    game.c文件:

    1. void PlayerMove(char board[ROW][COL], int row, int col)
    2. {
    3. int x = 0, y = 0;
    4. printf("玩家下棋:\n");
    5. while (1)
    6. {
    7. printf("请输入你要落子的坐标:");
    8. scanf("%d%d", &x, &y);
    9. if (x >= 1 && x <= row && y >= 1 && y <= col)
    10. {
    11. if (board[x - 1][y - 1] == ' ')
    12. {
    13. board[x - 1][y - 1] = '*';
    14. break;
    15. }
    16. else
    17. {
    18. printf("输入的坐标已被占用,请重新输入\n");
    19. }
    20. }
    21. else
    22. {
    23. printf("坐标非法,请重新输入\n");
    24. }
    25. }
    26. }

    3.2 电脑下棋

    思路: 

    我们可以在让电脑生成随机数,这样就可以使其随机生成一个坐标下棋子,那么我们就可以简单的实现电脑下棋的效果了。

    随机数的生成则可以使用rand函数、srand函数以及time函数。

    game.c文件:

    1. void ComputerMove(char board[ROW][COL], int row, int col)
    2. {
    3. printf("电脑下棋:>\n");
    4. while (1)
    5. {
    6. int x = rand() % row;
    7. int y = rand() % row;
    8. if (x <= row && x >= 1 && y <= row && y >= 1)
    9. {
    10. if (board[x][y] == ' ')
    11. {
    12. board[x][y] = '#';
    13. break;
    14. }
    15. }
    16. }
    17. }

    test.c文件:

    srand((unsigned int)time(UNLL))

    game.h文件:

    1. #include
    2. #include

    为了实现玩家下一个棋,然后电脑下一个棋的功能我们还需加上一个while循环。如下:

    test.c文件:

    1. while(1)
    2. {
    3. //玩家下棋
    4. PlayerMove(board, ROW, COL);
    5. DisplayBoard(board, ROW, COL);
    6. //电脑下棋
    7. ComputerMove(board, ROW, COL);
    8. DisplayBoard(board, ROW, COL);
    9. }

     4. 判断游戏的输赢

     思路:

    此游戏无非只有三种结果:要么玩家赢,要么电脑赢,要么平局。所以我们可以写一个函数判断是这几种结果的哪一种,然后规定如果是玩家赢此函数返回“*”,如果是电脑赢则返回“#”,平局则返回“Q”,这几种都不是就说明游戏继续,那么就返回“C”.

    要判断是否有赢的一方,无非就是判断是否出现了三个相同的棋子练成一条直线,而棋子连成的线无非就只有三种情况:竖线、横线、对角线。所以我们只需要判断是否出现了这三种情况的其中一种就可以了。而要判断是平局,则判断九宫格是否还有没有空格。

    game.c文件:

    1. int ItFull(char board[ROW][COL], int row, int col)
    2. {
    3. for (int i = 0; i < row; i++)
    4. {
    5. for (int j = 0;j < col; j++)
    6. {
    7. if (board[i][j] == ' ')
    8. {
    9. return 0;
    10. }
    11. }
    12. }
    13. return 1;
    14. }
    15. char ItWin(char board[ROW][COL], int row, int col)
    16. {
    17. //行
    18. for (int i = 0; i < row; i++)
    19. {
    20. if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
    21. return board[i][1];
    22. }
    23. //列
    24. for (int j = 0; j < col; j++)
    25. {
    26. if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
    27. return board[1][j];
    28. }
    29. //对角线
    30. if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
    31. {
    32. return board[1][1];
    33. }
    34. if (ItFull(board, row, col))
    35. {
    36. return 'Q';
    37. }
    38. return 'C';
    39. }

    test.c文件:

    1. //玩家下棋
    2. PlayerMove(board, ROW, COL);
    3. DisplayBoard(board, ROW, COL);
    4. //判断输赢
    5. char ret = ItWin(board, ROW, COL);
    6. if (ret != 'C')
    7. {
    8. if (ret == '*')
    9. {
    10. printf("玩家赢了!!!\n");
    11. }
    12. break;
    13. }
    14. //电脑下棋
    15. ComputerMove(board, ROW, COL);
    16. DisplayBoard(board, ROW, COL);
    17. //判断输赢
    18. ItWin(board, ROW, COL);
    19. if (ret != 'C')
    20. {
    21. if (ret == '#')
    22. {
    23. printf("电脑赢了!!!\n");
    24. }
    25. break;
    26. }

    完整代码:

    game.h文件:

    1. #include
    2. #include
    3. #include
    4. #define ROW 3
    5. #define COL 3
    6. void InitBoard(char board[ROW][COL],int row,int col);
    7. void DisplayBoard(char board[ROW][COL], int row, int col);
    8. void PlayerMove(char board[ROW][COL], int row, int col);
    9. void ComputerMove(char board[ROW][COL], int row, int col);
    10. char ItWin(char board[ROW][COL], int row, int col);

    test.c文件:

    1. #include"game.h"
    2. void menu()
    3. {
    4. printf("***************************\n");
    5. printf("******** 1.play ********\n");
    6. printf("******** 2.exit ********\n");
    7. printf("***************************\n");
    8. }
    9. void game()
    10. {
    11. //第一步打印棋盘。
    12. char board[ROW][COL] = { 0 };
    13. //初始化棋盘
    14. InitBoard(board, ROW, COL);
    15. //打印棋盘
    16. DisplayBoard(board, ROW, COL);
    17. char ret;
    18. while(1)
    19. {
    20. //玩家下棋
    21. PlayerMove(board, ROW, COL);
    22. DisplayBoard(board, ROW, COL);
    23. //判断输赢
    24. char ret = ItWin(board, ROW, COL);
    25. if (ret != 'C')
    26. {
    27. if (ret == '*')
    28. {
    29. printf("玩家赢了!!!\n");
    30. }
    31. break;
    32. }
    33. //电脑下棋
    34. ComputerMove(board, ROW, COL);
    35. DisplayBoard(board, ROW, COL);
    36. //判断输赢
    37. ItWin(board, ROW, COL);
    38. if (ret != 'C')
    39. {
    40. if (ret == '#')
    41. {
    42. printf("电脑赢了!!!\n");
    43. }
    44. break;
    45. }
    46. }
    47. }
    48. int main()
    49. {
    50. srand((unsigned int)time(NULL));
    51. int input = 0;
    52. do
    53. {
    54. menu();
    55. printf("请选择>:");
    56. scanf("%d", &input);
    57. switch (input)
    58. {
    59. case 1:
    60. game();
    61. break;
    62. case 0:
    63. printf("退出游戏.\n");
    64. break;
    65. default:
    66. printf("输入有误,请重新输入.\n");
    67. }
    68. } while (input);
    69. return 0;
    70. }

    game.c文件:

    1. #include"game.h"
    2. void InitBoard(char board[ROW][COL], int row, int col)
    3. {
    4. for (int i = 0; i < row; i++)
    5. {
    6. for (int j = 0; j < col; j++)
    7. {
    8. board[i][j] = ' ';
    9. }
    10. }
    11. }
    12. void DisplayBoard(char board[ROW][COL], int row, int col)
    13. {
    14. for (int i = 0; i < row; i++)
    15. {
    16. for (int j = 0; j < col; j++)
    17. {
    18. printf(" %c ",board[i][j]);
    19. if (j < col - 1)
    20. printf("|");
    21. }
    22. printf("\n");
    23. if (i < row - 1)
    24. {
    25. for (int j = 0; j < col; j++)
    26. {
    27. printf("---");
    28. if (j < col - 1)
    29. printf("|");
    30. }
    31. printf("\n");
    32. }
    33. }
    34. }
    35. void PlayerMove(char board[ROW][COL], int row, int col)
    36. {
    37. int x = 0, y = 0;
    38. printf("玩家下棋>:\n");
    39. while (1)
    40. {
    41. printf("请输入你要落子的坐标:");
    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. }
    54. }
    55. else
    56. {
    57. printf("坐标非法,请重新输入\n");
    58. }
    59. }
    60. }
    61. void ComputerMove(char board[ROW][COL], int row, int col)
    62. {
    63. printf("电脑下棋:>\n");
    64. while (1)
    65. {
    66. int x = rand() % row;
    67. int y = rand() % row;
    68. if (x <= row && x >= 1 && y <= row && y >= 1)
    69. {
    70. if (board[x][y] == ' ')
    71. {
    72. board[x][y] = '#';
    73. break;
    74. }
    75. }
    76. }
    77. }
    78. int ItFull(char board[ROW][COL], int row, int col)
    79. {
    80. for (int i = 0; i < row; i++)
    81. {
    82. for (int j = 0;j < col; j++)
    83. {
    84. if (board[i][j] == ' ')
    85. {
    86. return 0;
    87. }
    88. }
    89. }
    90. return 1;
    91. }
    92. char ItWin(char board[ROW][COL], int row, int col)
    93. {
    94. //行
    95. for (int i = 0; i < row; i++)
    96. {
    97. if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
    98. return board[i][1];
    99. }
    100. //列
    101. for (int j = 0; j < col; j++)
    102. {
    103. if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
    104. return board[1][j];
    105. }
    106. //对角线
    107. if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
    108. {
    109. return board[1][1];
    110. }
    111. if (ItFull(board, row, col))
    112. {
    113. return 'Q';
    114. }
    115. return 'C';
    116. }

    运行图:

    游戏优化: 

    让电脑生成一个数的方式来实现一个电脑下棋的效果,肯定是没有什么可玩性的,等后面学习算法之后,我们就加入一些算法将其变为一个棋艺高超的棋手了。

  • 相关阅读:
    junit 单元测试类,一个工具库类,做测试方法使用
    湖南衡阳3D扫描在生物仿真研究的应用高精度三维扫描螃蟹-CASAIM中科广电
    自动驾驶感知算法面经(20+)
    指尖上的 NFT|在 G2 上评价 Ambire,有机会获得限量版收藏品
    使用ORDER BY 排序
    热门高薪岗位大数据开发 自学转行如何就业(自学教程 学习路线 方法建议)
    钉钉统一授权登录第三方网站
    Socket通信
    SpringCloud尚硅谷全部
    将conda虚拟环境打包并集成到singularity镜像中
  • 原文地址:https://blog.csdn.net/weixin_58252863/article/details/136735996