目录
  • 三子棋
  • 创建项目环境
    • 头文件内容
  • 编写main函数(test.c)
    • 实现每一个接口函数
      • 1.board
      • 2.printfboard
      • 3.play
      • 4.computerplay
      • 5.win
    • 总结

      三子棋

      大家小时候应该都玩过三子棋吧,学习了这么久的C语言,我们其实已经具备了做三子棋这种小型项目的能力,今天我会尽量沉浸式的教大家实现三子棋,如果看完这篇博客还是不会的可以去我最后附上的gitee仓库链接中寻找。但我还是希望大家能自己完成,在三子棋中体现自己的风格。

      创建项目环境

      首先,第一步,打开我们的vs编译器,新建一个三子棋项目

      在这个新建的项目中创建三个文件

      1.test.c

      2.game.c

      3.game.h

      C语言新手初阶教程之三子棋实现

      我们把函数声明和头文件的引入放在game.h这个头文件中

      将一些自定义函数定义放在game.c中

      将主函数的编写放在test.c中

      现在直接上头文件的内容,一会一步一步的教大家实现头文件中的接口和引用头文件的原因

      头文件内容

      #ifndef __GAME_H__
      #define __GAME_H__
      #include<stdio.h>
      #include<stdlib.h>
      #include<time.h>
      #include<Windows.h>
      #define H 3
      #define L 3
      void menu();
      void game();
      void board(char arr[H][L],int x,int y);
      void printfboard(char arr[H][L], int x,int y);
      void  play(char arr[H][L], int x, int y);
      void computerplay(char arr[H][L], int x, int y);
      char win(char arr[H][L],int x,int y);
      #endif 
      
      #ifndef #define #endif是为了防止头文件重复引入,其实在大家自己创建头文件时自带的
      #pramga once
      同样也可以达到目的
      

      编写main函数(test.c)

      写test.c第一步引用头文件game.h即
      #include"game.h"
      玩游戏一定要有一个菜单,所以我们需要打印写一个菜单,这个菜单函数的实现就在test.c中进行即可
      但我们先需要在头文件中声明void menu();
      接下来实现菜单
      void menu(){
      printf("*******************\n");
      printf("***1.play 0.exit***\n");
      printf("*******************\n");
      }
      我们使用了printf函数,我们这个时候需要引用带有标准输入输出流的头文件stdio.h
      然后我们在game.h中加上#include<stdio.h>
      
      像这种选择1,开始游戏,选择退出程序的模式,我们可以直接用switch来实现
      游戏肯定不止一把,只要用户不选择0,就让用户一直玩,所以我们这样编写主函数
      int main() {
          int input;
          do{
          menu();
      again:    
          printf("请输入:");
          scanf("%d", &input);
          switch (input) {
          case 1:
              game();
              break;
          case 0:
              printf("退出游戏\n");
              break;
          default:
              printf("输入错误,请重新输入\n");
              goto again;
          }
          } while (input);
          return 0;
      }
      为了防止用户输入错误,直接退出了程序,我们利用goto的特性来实现
      

      接下来我们组装一下,text.c就完成了

       #include"game.h"
      void menu() {
          printf("*********************\n");
          printf("**1.play  0.exit*****\n");
          printf("*********************\n");
      }
      int main() {
          int input;
          do{
          menu();
      again:
          printf("请输入:");
          scanf("%d", &input);
          switch (input) {
          case 1:
              game();
              break;
          case 0:
              printf("退出游戏\n");
              break;
          default:
              printf("输入错误,请重新输入\n");
              goto again;
          }
          } while (input);
          return 0;
      }
      

      实现每一个接口函数

      这一个过程可能有点复杂,大家可能需要多多上手实验

      game函数是相当于game.c的main函数,我们需要一步一步去构建

      1.board

      在下三子棋之前我们应该知道用什么来承载棋子,三行三列的棋子,正好对应了二维数组的行和列
      我们就用二维数组来进行
      在game函数中我们可以加入
      int arr[3][3];
      但是在实际设计程序中,不建议大家使用数字,可能会出现错误,而且直接定义三行三列
      之后我们想改造三子棋为五子棋会很麻烦,这个时候我们可以用常量来代替
      所以我们应该在头文件中加入这两行代码,H代表行,L代表列
      #define H 3
      #define L 3
      
      void game(){
      char arr[H][L];
      board(arr,H,L);
      }
      board函数是用来实现初始化棋盘的,没有下子的位置都将其初始化为空,即空格
      void board(char arr[H][L], int x, int y) {
          int i, j;
          for (i = 0; i < x; i++) {
              for (j = 0; j < y; j++) {
                  arr[i][j] = ' ';
              }
          }
      }
      

      2.printfboard

      初始化之后,我们需要打印棋盘这个printfboard函数是用来打印棋盘的,这一步比较重要,也比较困难,这个需要大家多动手尝试,先给大家看看我们理想的棋盘效果

      C语言新手初阶教程之三子棋实现

      从图中我们可以看到,我们用|和-作为分割符

      void printfboard(char arr[H][L], int x, int y) {
          for (int i = 0; i < x; i++) {
              for (int j = 0; j < y; j++) {
                  printf(" %c ", arr[i][j]);
                  if (j < y - 1)
                      printf("|");
              }
              printf("\n");
              if (i < x - 1) {
                  for (int j = 0; j < y; j++) {
                      printf("---");
                      if (j < y - 1)
                          printf("|");
                  }
                  printf("\n");
              }
          }
      }
      
      接下来讲game函数改造为
      void game(){
      char arr[H][L];
      board(arr,H,L);
      printfboard(arr,H,L);
      }
      

      这个函数的实现并不简单,希望大家多多尝试

      3.play

      接下来我们开始下棋了,我们先人为固定,我们下的是‘*’,电脑下的是‘#’

      首先,用户并不知道数组下标是从零开始的,我们需要设计从1开始

      其次,我们需要提醒用户的错误下棋,比如下在已有棋子的地方和下在棋盘以外

      最后,我们需要提醒用户正确的下棋方法,防止出现程序错误

      void play(char arr[H][L], int x,int y) {
          int i, j;
          again:
          printf("(提示,以x y的形式输入,x代表行,y代表列)请输入你要下棋的位置:");
          scanf("%d %d", &i, &j);
          if (i >= 1 && i <= 3 && j >= 1 && j <= 3) {
              if (arr[i - 1][j - 1] != ' ') {
                  printf("该位置以有棋子,请重新输入");
                  goto again;
              }
              else
              {
                  arr[i-1][j-1] = '*';
                  printfboard(arr, x, y);//下完棋打印棋盘
              }
          }
          else
          {
              printf("输入错误,请重新输入");
              goto again;
          }
       
      }
      

      4.computerplay

      玩家下完之后,需要电脑来下棋,电脑下棋就需要随机数rand来进行

      首先我们在头文件中引用
      #include<time.h>
      #include<stdlib.h>
      
      computerplay的要点与play一致
      void computerplay(char arr[H][L], int x, int y) {
          int i, j;
          srand((unsigned)time(NULL));//作为随机数的生成起点
      again:    i = rand()%x;   //这样i和j都只能是0 1 2符合数组下标规则
          j = rand() % y;
          if (arr[i][j] == ' ')
          {
              arr[i][j] = '#';
              printfboard(arr, H, L);
          }
          else goto again;
      }
      
      电脑和人在还没有结束之前需要一直下,而且电脑有时候下的很快,我们需要用Sleep休息一下
      void game() {
          char arr[H][L] = { 0 };
          board(arr, H, L);
          printfboard(arr, H, L);
          while (1) {
              play(arr, H, L);
              printf("电脑正在下棋请稍等\n");
              Sleep(1000);
              computerplay(arr, H, L);
          }
      }

      5.win

      接下来便是整个三子棋的最后一步,判断输赢

      我们先想一想输赢的条件,连成一条线就是赢,没有位置就是平局
      平局的条件比较好判断,但判断赢我们找不到好的方法就只能一一列举
      但是我们可以想一些有用的思路,我们从行和列交叉一次判读
      如果相等且不为空格直接返回
      当棋盘满了,返回!
      char win(char arr[H][L], int x, int y) {
          int i, j;
          int flag = 0; 
          for (i = 0; i < x; i++) {   //行
              for (j = 0; j < y - 2; j++) {
                  if (arr[i][j] == arr[i][j + 1] && arr[i][j + 1] == arr[i][j + 2] && arr[i][j] != ' ')
                      return arr[i][j];
              }
          }
          for (j = 0; j < y; j++) {  //列
              for (i = 0; i < x - 2; i++) {
                  if (arr[i][j] == arr[i + 1][j] && arr[i + 1][j] == arr[i + 2][j] && arr[i][j] != ' ')
                      return arr[i][j];
              }
          }
          for (i = 0; i < x - 2; i++) {  //对角线
              for (j = 0; j < y - 2; j++) {
                  if (arr[i][j] == arr[i + 1][j + 1] && arr[i + 1][j + 1] == arr[i + 2][j + 2] && arr[i][j] != ' ')
                      return arr[i][j];
              }
              for (i = 0; i < x; i++) {//对角线
                  for (j = y - 1; j > 1; j--) {
                      if (arr[i][j] == arr[i + 1][j - 1] && arr[i + 1][j - 1] == arr[i + 2][j - 2] && arr[i][j] != ' ')
                          return arr[i][j];
                  }
       
              }
       
          }
          for (i = 0; i < x; i++) {
              for (j = 0; j < y; j++) {
                  if (arr[i][j] == ' ')
                      flag = 1;
              }
          }
          if (flag == 1)
              return ' ';
          else
              return '!';
      }
      

        再将game进行改造

      void game() {
          char arr[H][L] = { 0 };
          char ret;
          board(arr, H, L);
          printfboard(arr, H, L);
          while (1) {
              play(arr, H, L);
              ret = win(arr, H, L);
              if (ret != ' ')
                  break;
              printf("电脑正在下棋请稍等\n");
              Sleep(1000);
              computerplay(arr, H, L);
              ret = win(arr, H, L);
              if (ret != ' ')
                  break;
          }
          if (ret == '*')
              printf("恭喜你获胜了\n");
          else if (ret == '#')
              printf("很遗憾你输了\n");
          else
              printf("势均力敌,再接再厉\n");
      }
      

      然后将game.c拼装在一起就完事了

      #include"game.h"
      void board(char arr[H][L], int x, int y) {
          int i, j;
          for (i = 0; i < x; i++) {
              for (j = 0; j < y; j++) {
                  arr[i][j] = ' ';
              }
          }
      }
      void printfboard(char arr[H][L], int x, int y) {
          for (int i = 0; i < x; i++) {
              for (int j = 0; j < y; j++) {
                  printf(" %c ", arr[i][j]);
                  if (j < y - 1)
                      printf("|");
              }
              printf("\n");
              if (i < x - 1) {
                  for (int j = 0; j < y; j++) {
                      printf("---");
                      if (j < y - 1)
                          printf("|");
                  }
                  printf("\n");
              }
          }
      }
      void play(char arr[H][L], int x,int y) {
          int i, j;
          again:
          printf("(提示,以x y的形式输入,x代表行,y代表列)请输入你要下棋的位置:");
          scanf("%d %d", &i, &j);
          if (i >= 1 && i <= 3 && j >= 1 && j <= 3) {
              if (arr[i - 1][j - 1] != ' ') {
                  printf("该位置以有棋子,请重新输入");
                  goto again;
              }
              else
              {
                  arr[i-1][j-1] = '*';
                  printfboard(arr, x, y);
              }
          }
          else
          {
              printf("输入错误,请重新输入");
              goto again;
          }
       
      }
      void computerplay(char arr[H][L], int x, int y) {
          int i, j;
          srand((unsigned)time(NULL));//作为随机数的生成起点
      again:    i = rand()%x;   //这样i和j都只能是0 1 2符合数组下标规则
          j = rand() % y;
          if (arr[i][j] == ' ')
          {
              arr[i][j] = '#';
              printfboard(arr, H, L);
          }
          else goto again;
      }
      char win(char arr[H][L], int x, int y) {
          int i, j;
          int flag = 0;
          for (i = 0; i < x; i++) {
              for (j = 0; j < y - 2; j++) {
                  if (arr[i][j] == arr[i][j + 1] && arr[i][j + 1] == arr[i][j + 2] && arr[i][j] != ' ')
                      return arr[i][j];
              }
          }
          for (j = 0; j < y; j++) {
              for (i = 0; i < x - 2; i++) {
                  if (arr[i][j] == arr[i + 1][j] && arr[i + 1][j] == arr[i + 2][j] && arr[i][j] != ' ')
                      return arr[i][j];
              }
          }
          for (i = 0; i < x - 2; i++) {
              for (j = 0; j < y - 2; j++) {
                  if (arr[i][j] == arr[i + 1][j + 1] && arr[i + 1][j + 1] == arr[i + 2][j + 2] && arr[i][j] != ' ')
                      return arr[i][j];
              }
              for (i = 0; i < x; i++) {
                  for (j = y - 1; j > 1; j--) {
                      if (arr[i][j] == arr[i + 1][j - 1] && arr[i + 1][j - 1] == arr[i + 2][j - 2] && arr[i][j] != ' ')
                          return arr[i][j];
                  }
       
              }
       
          }
          for (i = 0; i < x; i++) {
              for (j = 0; j < y; j++) {
                  if (arr[i][j] == ' ')
                      flag = 1;
              }
          }
          if (flag == 1)
              return ' ';
          else
              return '!';
      }
      void game() {
          char arr[H][L] = { 0 };
          char ret;
          board(arr, H, L);
          printfboard(arr, H, L);
          while (1) {
              play(arr, H, L);
              ret = win(arr, H, L);
              if (ret != ' ')
                  break;
              printf("电脑正在下棋请稍等\n");
              Sleep(1000);
              computerplay(arr, H, L);
              ret = win(arr, H, L);
              if (ret != ' ')
                  break;
          }
          if (ret == '*')
              printf("恭喜你获胜了\n");
          else if (ret == '#')
              printf("很遗憾你输了\n");
          else
              printf("势均力敌,再接再厉\n");
      }
      

      这是拼装后的结果

      如果想和室友对战的小伙伴,将computerplay改的和play差不多就行如果想玩五子棋也只需要对修改H L的常量值,以及判定条件,目前可能依然只能用列举来判定

      学到这,如果你依然不会,没关系,直接去我的码云上找代码,当然我希望小伙伴们都能写出属于自己的三子棋,这个三子棋也并不完美,电脑下棋肯定是呆呆的,可以尝试一下ai下棋

      总结

      声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。