【c语言】三子棋(保姆级教程+内含源码)

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
可观测可视化 Grafana 版,10个用户账号 1个月
可观测监控 Prometheus 版,每月50GB免费额度
简介: 使用c语言写的超级详细的三子棋,简单容易上手,大家可以边理解,边跟着跟着敲

 我们要写一个简单的三子棋小游戏,我使用的是vs2022编译器,我们首先要创建一个头文件和两个源文件image.gif编辑

像这样的,测试放的是main函数,函数放的的主函数是需要的函数,头文件是函数的声明

我会一步一步的将三子棋怎么写的代码一步一步的写下来,在最后我将整个的代码发在最后

然后我们要确定我们的写的三子棋是什么样的图形界面

image.gif编辑

我门要打印的棋盘大概是这样的,

第一步我们先写一个main()函数

int main()
{
  mune();//菜单
  int input = 0;//创建一个变量让我们可以输入
  do//先用一个do-while循环直接运行
  {
    printf("请选择是否参加:>");
    scanf("%d", &input);
    switch (input)//在do-while循环里面我们用一个switch,让我们可以选择,
    {
    case 1:
      printf("三子棋\n");//我们先在这里验证一下整个逻辑是否可以
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("输入错误,请重新输入\n");
      break;
    }
  } while (input);//遇到如果输入的值是0,则循环不执行,直接退出,所以我们要创建一个菜单提示玩家可以选择
  return 0;
}

image.gif

mune()//菜单
{
  printf("******************************\n");
  printf("******1.play    0.exit  ******\n");
  printf("******************************\n");
}

image.gif

然后我们验证的的是这样的image.gif编辑

我们的逻辑验证成功

然后将printf(“三子棋\n”);改成game()函数来完成我们接下来的打印棋盘等函数的第一步我们要创建一个数组来储存我们要打印的字符,然后要在测试里面下一个函数

这是写在测试里面的

void game()
{
  //创建存放数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  ChuBoard(board, ROW, COL);
}

image.gif

接下来是声明里面

#pragma once
#include <stdio.h>
#define ROW 3//在声明里面设立全局变量可以让我们以后改代码的时候更容易
#define COL 3
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col);

image.gif

接着我们就要写初始化棋盘的函数部分了

#define _CRT_SECURE_NO_WARNINGS
#include "声明.h"
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col)
{
  int i = 0;//我们要二层循环来经行遍历
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      board[i][j] = ' ';//将棋盘初始化
    }
  }
}

image.gif

将棋盘初始化完成后我们就要开始打印棋盘了,在测试game()函数中加入一个打印棋盘的函数

void game()
{
  //创建存放数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  ChuBoard(board, ROW, COL);
  //打印棋盘
  DaBoard(board, ROW, COL);
}

image.gif

接着就是对打印棋盘函数的声明

#pragma once
#include <stdio.h>
#define ROW 3//在声明里面设立全局变量可以让我们以后改代码的时候更容易
#define COL 3
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DaBoard(char board[ROW][COL], int row, i

image.gif

接着就是函数部分的代码

//打印棋盘
//我们要打印的棋盘就在棋盘,对棋盘没有印象的可以看一下上面
void DaBoard(char board[ROW][COL], int row, int col)
{
  int i = 0;
  //打印数据
  //利用两次循环将
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      printf(" %c ", board[i][j]);//这里的是空格%c空格这样是因为可以让打印出来的棋盘和上面看到的一样
      if (j < col - 1)//设置一个if判断语句是因为我们只需要打印两竖线
      {
        printf("|");
      }
    }
    printf("\n");//打印一个换行符,方便我们接下来的的打印分割线
    //打印分割线
    if (i < row - 1)//因为我们只需要打印两行分隔线,所以我们要设计一个条件
    {
      int j = 0;
      for (j = 0; j < col; j++)//我们要进行一个循环来我们打印一行内的分割线
      {
        printf("---");//一行打印三次
        if (j < col - 1)
        {
          printf("|");//设置一个if判断语句是因为我们只需要打印两竖线
        }
      }
    }
    printf("\n");//打印一个换行
  } 
}

image.gif

这个时候我们可以验证一下是否是我们想要的棋盘

我们运行一下结果是这样的image.gif编辑

证明我们的代码是没有问题的,我们就可以接着继续写下面的代码了

我们现在写玩家下棋

game()函数里面这样写

void game()
{
  //创建存放数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  ChuBoard(board, ROW, COL);
  //打印棋盘
  DaBoard(board, ROW, COL);
  //玩家下棋
  WanMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
  //打印棋盘
  DaBoard(board, ROW, COL);
}

image.gif

在去声明一下

#include <stdio.h>
#define ROW 3//在声明里面设立全局变量可以让我们以后改代码的时候更容易
#define COL 3
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DaBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void WanMove(char board[ROW][COL], int row, int col);

image.gif

接下来就是写玩家下棋的函数内容了

void WanMove(char board[ROW][COL], int row, int col)
{
  //首先先创建两个变量
  int x = 0;//x=0是因为我们要将x初始化为0
  int y = 0;
  printf("玩家请输入\n");
  while (1)//我们要使用while循环来让我们进行我们的答错可以重新下棋的机制
  {
    printf("请输入坐标\n");
    scanf("%d %d", &x, &y);
    //要考虑输入的坐标的合法性的问题
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if (board[x-1][y-1] == ' ')//当输入的坐标空间上是没有存放字符的时候玩家就可以下棋
      {
        board[x-1][y-1] = '*';//我们让玩家下棋使用*
        break;//跳出循环进行下一步
      }
      else//当我们选择的坐标被占用的时候我们要提示他重新输入
      {
        printf("该坐标被占用,请重新输入");
      }
    }
    else//判断该坐标是否合法
    {
      printf("该坐标非法,请重新输入\n");
    }
  }
}

image.gif

我们验证一下,结果是这样的

image.gif编辑

说明我们的玩家下棋是成功的

接下来就是写电脑下棋,在game()函数中是这样写的

void game()
{
  //创建存放数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  ChuBoard(board, ROW, COL);
  while (1)//我们要写一个循环然后让玩家和电脑可以循环下棋
  {
    //打印棋盘
    DaBoard(board, ROW, COL);
    //玩家下棋
    WanMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
    //打印棋盘
    DaBoard(board, ROW, COL);
    DianMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
    //打印棋盘
    DaBoard(board, ROW, COL);
  }
}
int main()
{
  srand((unsigned int)time(NULL));//生成时间的空指针
  int input = 0;//创建一个变量让我们可以输入
  do//先用一个do-while循环直接运行
  {
    mune();//菜单
    printf("请选择是否参加:>");
    scanf("%d", &input);
    switch (input)//在do-while循环里面我们用一个switch,让我们可以选择,
    {
    case 1:
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("输入错误,请重新输入\n");
      break;
    }
  } while (input);//遇到如果输入的值是0,则循环不执行,直接退出,所以我们要创建一个菜单提示玩家可以选择
  return 0;
}

image.gif

声明

#pragma once
#include <stdio.h>//调用printf()函数,是scanf()函数
#define ROW 3//在声明里面设立全局变量可以让我们以后改代码的时候更容易
#define COL 3
#include <stdlib.h>//调用srand()函数
#include <time.h>//生成空指针
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DaBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void WanMove(char board[ROW][COL], int row, int col);
//电脑下棋
void DianMove(char board[ROW][COL], int row, int col);

image.gif

接下来就是写电脑下棋的函数了

//电脑下棋,我这里写的是最简单电脑下棋的函数
//有兴趣的可以使用算法来经行加强电脑赢的概率
void DianMove(char board[ROW][COL], int row, int col)
{
  int x = 0;
  int y = 0;
  printf("电脑下棋:>\n");
  while (1)
  {
    x = rand() % row;//rand()函数生成是一个随机数在32767到0的一个任意整数
    y = rand() % col;//但是我们rand()%row后随机值范围就是0~2
    if (board[x][y] == ' ')
    {
      board[x][y] = '#';
      break;
    }
  }
}

image.gif

测试一下,结果是这样的

image.gif编辑

我们现在开始写判断输赢函数

//输赢判断
char ShuYin(char board[ROW][COL], int row, int col)//这里不用void是因为我们要有一个字符返回值
{
  //首先我们要判断有赢有几种情况,还有平局的情况,还有继续
  //行
  int i = 0;
  for (i = 0; i < row; i++)
  {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')//我们判断每一行是否都被同一种字符占用了
    {
      return board[i][1];//如果被占用就返回该行的字符
    }
  }
  //列
  int j= 0;
  for (j = 0; j < row; j++)
  {
    if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')//我们判断每一列是否都被同一种字符占用了
    {
      return board[1][j];//如果被占用就返回该列的字符
    }
  }
  //对角线
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//我们判断对角线是否都被同一种字符占用了
  {
    return board[1][1];//如果被占用就返回该列的字符
  }
  if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')//我们判断对角线是否都被同一种字符占用了
  {
    return board[1][1];//如果被占用就返回该列的字符
  }
  //平局
  if (Ping(board, row,col))//我们再进行一个平局判断函数
  {
    return 'Q';
  }
  //继续
  return 'C';
}

image.gif

声明

#pragma once
#include <stdio.h>//调用printf()函数,是scanf()函数
#define ROW 3//在声明里面设立全局变量可以让我们以后改代码的时候更容易
#define COL 3
#include <stdlib.h>//调用srand()函数
#include <time.h>//生成空指针
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DaBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void WanMove(char board[ROW][COL], int row, int col);
//电脑下棋
void DianMove(char board[ROW][COL], int row, int col);
//输赢判断
//玩家赢  - ‘*’
//电脑赢  - ‘#’
//平局    -  ‘Q’
//继续    - ‘C’
char ShuYin(char board[ROW][COL], int row, int col);

image.gif

geme()函数里面的代码

void game()
{
  char ret = 0;//创建一个判断变量
  //创建存放数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  ChuBoard(board, ROW, COL);
  while (1)
  {
    //玩家下棋
    WanMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
    ret = ShuYin(board, ROW, COL);
    if (ret != 'C')//判断棋盘的是否继续出现了任意一个赢,或者平局的情况,如果出现就跳出循环进行判断输出
    {
      break;
    }
    //打印棋盘
    DaBoard(board, ROW, COL);
    DianMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
    ret = ShuYin(board, ROW, COL);
    if (ret != 'C')//判断棋盘的是否继续出现了任意一个赢,或者平局的情况,如果出现就跳出循环进行判断输出
    {
      break;
    }
    //打印棋盘
    DaBoard(board, ROW, COL);
  }
  if (ret == '*')
  {
    printf("玩家赢了\n");
  }
  else if (ret == '#')
  {
    printf("电脑赢了\n");
  }
  else
  {
    printf("平局\n");
  }
  DaBoard(board, ROW, COL);//判断完输赢我们再一次打印棋盘,让我们知道是怎么赢得
}

image.gif

我们先就只剩下一个平局函数没有写了

平局函数

//平局判断
int Ping(char board[ROW][COL], int row, int col)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)//我们先遍历一下
    {
      if (board[i][j] == ' ')//我们要判断是否棋盘都被占满,如果没有占满就返回0
      {
        return 0;
      }
    }
  }
  return 1;//占满了就返回1,让输赢函数返回‘Q’
}

image.gif

现在我们的程序代码全部写完了

我们运行运行看一下能不能成功

结果是这样的

image.gif编辑

我们成功的写出来一个简单的三子棋小游戏,能坚持到现在的都是好样的

接下来我就把完整的代码发出来

这是测试源文件

#define _CRT_SECURE_NO_WARNINGS
#include "声明.h"
mune()//菜单
{
  printf("******************************\n");
  printf("******1.play    0.exit  ******\n");
  printf("******************************\n");
}
void game()
{
  char ret = 0;//创建一个判断变量
  //创建存放数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  ChuBoard(board, ROW, COL);
  while (1)
  {
    //玩家下棋
    WanMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
    ret = ShuYin(board, ROW, COL);
    if (ret != 'C')//判断棋盘的是否继续出现了任意一个赢,或者平局的情况,如果出现就跳出循环进行判断输出
    {
      break;
    }
    //打印棋盘
    DaBoard(board, ROW, COL);
    DianMove(board, ROW, COL);//我们要在玩家下完棋后我们再一次打印一下棋盘的函数,让我们可以看到我们下的棋
    ret = ShuYin(board, ROW, COL);
    if (ret != 'C')//判断棋盘的是否继续出现了任意一个赢,或者平局的情况,如果出现就跳出循环进行判断输出
    {
      break;
    }
    //打印棋盘
    DaBoard(board, ROW, COL);
  }
  if (ret == '*')
  {
    printf("玩家赢了\n");
  }
  else if (ret == '#')
  {
    printf("电脑赢了\n");
  }
  else
  {
    printf("平局\n");
  }
  DaBoard(board, ROW, COL);//判断完输赢我们再一次打印棋盘,让我们知道是怎么赢得
}
int main()
{
  srand((unsigned int)time(NULL));//生成时间的空指针
  int input = 0;//创建一个变量让我们可以输入
  do//先用一个do-while循环直接运行
  {
    mune();//菜单
    printf("请选择是否参加:>");
    scanf("%d", &input);
    switch (input)//在do-while循环里面我们用一个switch,让我们可以选择,
    {
    case 1:
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("输入错误,请重新输入\n");
      break;
    }
  } while (input);//遇到如果输入的值是0,则循环不执行,直接退出,所以我们要创建一个菜单提示玩家可以选择
  return 0;
}

image.gif

这是函数源文件

#define _CRT_SECURE_NO_WARNINGS
#include "声明.h"
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col)
{
  int i = 0;//我们要二层循环来经行遍历
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      board[i][j] = ' ';//将棋盘初始化
    }
  }
}
//打印棋盘
//我们要打印的棋盘就在棋盘,对棋盘没有印象的可以看一下上面
void DaBoard(char board[ROW][COL], int row, int col)
{
  int i = 0;
  //打印数据
  //利用两次循环将
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      printf(" %c ", board[i][j]);//这里的是空格%c空格这样是因为可以让打印出来的棋盘和上面看到的一样
      if (j < col - 1)//设置一个if判断语句是因为我们只需要打印两竖线
      {
        printf("|");
      }
    }
    printf("\n");//打印一个换行符,方便我们接下来的的打印分割线
    //打印分割线
    if (i < row - 1)//因为我们只需要打印两行分隔线,所以我们要设计一个条件
    {
      int j = 0;
      for (j = 0; j < col; j++)//我们要进行一个循环来我们打印一行内的分割线
      {
        printf("---");//一行打印三次
        if (j < col - 1)
        {
          printf("|");//设置一个if判断语句是因为我们只需要打印两竖线
        }
      }
    }
    printf("\n");//打印一个换行
  } 
}
//玩家下棋
void WanMove(char board[ROW][COL], int row, int col)
{
  //首先先创建两个变量
  int x = 0;//x=0是因为我们要将x初始化为0
  int y = 0;
  printf("玩家请输入\n");
  while (1)//我们要使用while循环来让我们进行我们的答错可以重新下棋的机制
  {
    printf("请输入坐标\n");
    scanf("%d %d", &x, &y);
    //要考虑输入的坐标的合法性的问题
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if (board[x-1][y-1] == ' ')//当输入的坐标空间上是没有存放字符的时候玩家就可以下棋
      {
        board[x-1][y-1] = '*';//我们让玩家下棋使用*
        break;//跳出循环进行下一步
      }
      else//当我们选择的坐标被占用的时候我们要提示他重新输入
      {
        printf("该坐标被占用,请重新输入");
      }
    }
    else//判断该坐标是否合法
    {
      printf("该坐标非法,请重新输入\n");
    }
  }
}
//电脑下棋,我这里写的是最简单电脑下棋的函数
//有兴趣的可以使用算法来经行加强电脑赢的概率
void DianMove(char board[ROW][COL], int row, int col)
{
  int x = 0;
  int y = 0;
  printf("电脑下棋:>\n");
  while (1)
  {
    x = rand() % row;//rand()函数生成是一个随机数在32767到0的一个任意整数
    y = rand() % col;//但是我们rand()%row后随机值范围就是0~2
    if (board[x][y] == ' ')
    {
      board[x][y] = '#';
      break;
    }
  }
}
//平局判断
int Ping(char board[ROW][COL], int row, int col)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)//我们先遍历一下
    {
      if (board[i][j] == ' ')//我们要判断是否棋盘都被占满,如果没有占满就返回0
      {
        return 0;
      }
    }
  }
  return 1;//占满了就返回1,让输赢函数返回‘Q’
}
//输赢判断
char ShuYin(char board[ROW][COL], int row, int col)//这里不用void是因为我们要有一个字符返回值
{
  //首先我们要判断有赢有几种情况,还有平局的情况,还有继续
  //行
  int i = 0;
  for (i = 0; i < row; i++)
  {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')//我们判断每一行是否都被同一种字符占用了
    {
      return board[i][1];//如果被占用就返回该行的字符
    }
  }
  //列
  int j= 0;
  for (j = 0; j < row; j++)
  {
    if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')//我们判断每一列是否都被同一种字符占用了
    {
      return board[1][j];//如果被占用就返回该列的字符
    }
  }
  //对角线
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//我们判断对角线是否都被同一种字符占用了
  {
    return board[1][1];//如果被占用就返回该列的字符
  }
  if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')//我们判断对角线是否都被同一种字符占用了
  {
    return board[1][1];//如果被占用就返回该列的字符
  }
  //平局
  if (Ping(board, row,col))//我们再进行一个平局判断函数
  {
    return 'Q';
  }
  //继续
  return 'C';
}

image.gif

最后是声明

#pragma once
#include <stdio.h>//调用printf()函数,是scanf()函数
#define ROW 3//在声明里面设立全局变量可以让我们以后改代码的时候更容易
#define COL 3
#include <stdlib.h>//调用srand()函数
#include <time.h>//生成空指针
//初始化棋盘
void ChuBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DaBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void WanMove(char board[ROW][COL], int row, int col);
//电脑下棋
void DianMove(char board[ROW][COL], int row, int col);
//输赢判断
//玩家赢  - ‘*’
//电脑赢  - ‘#’
//平局    -  ‘Q’
//继续    - ‘C’
char ShuYin(char board[ROW][COL], int row, int col);

image.gif

好了这就是使用c语言写的超详细的三子棋,大家可以按照我的步骤写一下,非常简单,容易,上手,小白学习数组必备,不会的话可以多敲几遍增加自己的理解

写的不好的地方,欢迎大家给我批评,指正,可以的话给我点给赞吧,谢谢大家了

相关文章
|
1月前
|
存储 C语言
【C语言】C语言-宾馆客房管理系统(源码+论文)【独一无二】
【C语言】C语言-宾馆客房管理系统(源码+论文)【独一无二】
【C语言】C语言-宾馆客房管理系统(源码+论文)【独一无二】
|
1月前
|
存储 C语言
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
37 15
|
1月前
|
算法 编译器 C语言
【C语言篇】猜数字游戏(赋源码)
rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的⼤⼩是依赖编译器上实现的,但是⼤部分编译器上是32767。
|
1月前
|
存储 数据可视化 数据安全/隐私保护
【C语言】C语言-成绩管理系统(管理员+教师+学生 源码)【独一无二】
【C语言】C语言-成绩管理系统(管理员+教师+学生 源码)【独一无二】
|
1月前
|
存储 数据可视化 C语言
【C语言】C语言-身份证管理系统(源码+注释)【独一无二】
【C语言】C语言-身份证管理系统(源码+注释)【独一无二】
|
1月前
|
存储 数据可视化 C语言
【C语言】C语言-学生籍贯信息记录系统(源码+论文)【独一无二】
【C语言】C语言-学生籍贯信息记录系统(源码+论文)【独一无二】
|
1月前
|
存储 C语言
【C语言】C语言-学生选修课程系统(源码)【独一无二】
【C语言】C语言-学生选修课程系统(源码)【独一无二】
|
1月前
|
存储 C语言
【C语言】C语言-设备管理系统(源码+数据文件)【独一无二】
【C语言】C语言-设备管理系统(源码+数据文件)【独一无二】
|
1月前
|
存储 数据可视化 Serverless
【C语言】C语言-学籍管理系统(源码+文件存储)【独一无二】
【C语言】C语言-学籍管理系统(源码+文件存储)【独一无二】
|
1月前
|
存储 数据可视化 C语言
【C语言 】C语言 学生选修课程系统(源码+论文)【独一无二】
【C语言 】C语言 学生选修课程系统(源码+论文)【独一无二】