【C语言】民间传统游戏——三子棋详细教学

简介: 三子棋(介绍)游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。 🌞

三子棋(介绍)

游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。 🌞

实现效果


2c6d41c6f26b4a728829c02d84b99dd1.png

🧐首先开始执行程序,一张菜单,可以选择0或者1,0退出,1进入游戏

f949d90508d74d8186814feab0758d33.png

如果选择1的话,开始游戏,根据坐标填入数字,直到棋盘满了或者一方先连成一条线获胜为止。

代码实现

1.打印菜单

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

菜单必不可少,让用户进来了解怎么操作

2.main函数

int main()
{
    int input = 0;
    srand((unsigned)time(NULL));   //生成随机数用于人机自动落子
  do 
  {
    menu();    //do-while语句进来先打印菜单栏
    printf("请进行选择(0/1)\n");   //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了
    scanf("%d", &input);   
    switch (input)       //switch语句进行选择,一目了然
    {
    case 1:
      game();  //进入游戏
      break;
    case 0:
      printf("成功退出");
      break;
    default: 
      printf("输入错误,请重新输入");
      break;
    }
  } while (input); //为0中止
}

由于进程序就有菜单弹出所以这里选择do。while语句,再用switch语句进行判断,当玩家输入1,进入游戏,当玩家输入0,退出程序


让我们想想进入游戏后都需要些什么(也就是game()函数都需要什么)❔

首先我们需要一张棋盘,棋盘本质上来说是一个3*3的空间,我们这里选择用二维数组来放下。

 

char board[ROW][COL] = { 0 };

3.初始化棋盘

  • 在刚进游戏的时候,棋盘上是空的,所以我们要把棋盘上所有位置都初始化成空格
void InitBoard(char board[ROW][COL],int row,int col) //形参的名字不能和define定义的相同,不然会报错
{
  for (int i = 0; i < row; i++)     //把棋盘初始化为空格
  {
    for(int j=0;j< col;j++)
    {
      board[i][j] =' ';
    }
  }
    //也可以使用库函数memset
    //memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}

4.打印棋盘

  • 初始化棋盘之后我们就可以开始打印了
void printboard(char board[ROW][COL],int row,int col)//~用于打印棋盘
{
  for (int i = 0; i < row; i++)   
  {
    for (int j = 0; j < col; j++)      //打印一行
    {
      printf(" %c ", board[i][j]);   
      if (j<col - 1)    //打印col-1个|,做到  棋子|棋子|棋子
      {
        printf("|");
      }
    }
    printf("\n");
    if (i < row - 1)  //打印分割线---|---|---
    {
      for (int j = 0; j < col; j++)
      {
        printf("---");      
        if (j < COL - 1)
        {
          printf("|");
        }
      }
      printf("\n");
    }
  }
}

✨✨如果游戏开始只有棋子,那么玩家看到的是一片空,所以我们要打印一个棋盘出来,这里选择用ROW(行)和COL(列)来控制棋盘的长短,如果想打印更大的棋盘就只需改掉define定义的ROW和COL即可。


927950a1553445c6afc8f299c668daab.png

5.玩家落子

  • 打印完棋盘之后玩家进行落子
void playerMove(char board[ROW][COL], int row, int col)//~玩家下子
{
  printf("该你了,请选择坐标(?,?)\n");
  while (1)
  {
    int num1=0;       //玩家输入的行
    int num2=0;       //玩家输入的列
    scanf("%d,%d", &num1, &num2);
    if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0)) //如果超出棋盘范围,结束本次循环重新选择
    {
      printf("请输入正确位置");
      continue;
    }
    if (board[num1-1][num2-1] == ' ') 
    {
      board[num1-1][num2-1] = '*';    //返回1 ,落子成功,跳出循环
      break;
    }
    else   
    {
      printf("请选择空位下子\n");     //返回0 落子失败,重新输入
    }
  }
}

✨✨轮到玩家输入,首先要给个提示,提示玩家落子,如果玩家输入的坐标不对的话,提示重新下子,如果玩家输入的坐标已经有棋子的话,提示重新下子。

6.人机落子

  • 玩家落子之后人机落子
void computerMove(char board[ROW][COL], int row, int col)//~电脑下子
{
  while(1)
  {
    int num1 = rand() % row;     //生成随机数并取模row,保证row范围在棋盘大小内
    int num2 = rand() % col;   //生成随机数并取模COL,保证COL范围在棋盘大小内
    if (board[num1][num2] == ' ') 
    {
      board[num1][num2] = '#';    //如果为空落子成功,如果不为空重新生成随机数
      break;
    }
  }
  printf("人机落子并说道:你输定了小伙子\n");
}

7.判断输赢

  • 判断输赢是很重要的一步,不论是玩家落子后或电脑落子后,我们都应该进行判断程序是否应该结束
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束
{
  for (int i = 0; i < ROW; i++)
  {
    if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
    {
      return board[0][i]; //列相等返回所在列的字符,游戏结束
    }
  }
  for (int i = 0; i < COL; i++)
  {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
    {
      return board[i][1];//行相等返回所在行的字符,游戏结束
    }
  }
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
  {
    return board[1][1];//斜线相等返回所在字符,游戏结束
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
  {
    return board[1][1];//斜线相等返回所在字符,游戏结束
  }
  for (int i = 0; i < ROW; i++)
  {
    for (int j = 0; j < COL; j++)
    {
      if (board[i][j] == ' ')
      {
        return;   //如果还有空位,则游戏继续
      }
    }
  }
  return 'q';//运行到这里证明棋盘已经满了,游戏结束
}

8.game函数

  • 最后我们根据这些函数的作用将所有的函数整合到一块,就形成了我们整个游戏程序
void game()
{
  char board[ROW][COL] = { 0 };     //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘
  init(board, ROW, COL);        //此函数用于二维数组初始化
  printboard(board, ROW, COL);      //~用于打印棋盘
  while (1)
  {
    char end = '\0';
    playerMove(board, ROW, COL);  //~玩家下子
    printboard(board, ROW, COL);    //~打印棋盘
    end = ending(board, ROW, COL); //查看是否应该结束
    if (end == '*')     //返回值为*玩家胜利
    {
      printf("Player WIN!!!\n");
      break;
    }
    else if (end == 'q')    //返回值为棋盘满了未分胜负,平局,退出游戏
    {
      printf("敌人太强大了,居然平分秋色\n");
    }
    computerMove(board, ROW, COL);    //~电脑下子
        printboard(board, ROW, COL);    //打印棋盘
    end = ending(board, ROW, COL);  //查看是否应该结束
    if (end == '#')     //返回值为#人机获得胜利
    {
      printf("Computer WIN!!!\n");
      break;
    }
    else if (end == 'q')
    {
      printf("平局\n");     
    }
  }
}

文件分类

🌞🌞为了使代码更有阅读性,我们不建议把所有函数写在一个文件里,所以这里分成三个文件

test.c

  • 这个文件包含程序的主体构思,程序用到的一系列函数我们封装在其他文件夹,这里只需要引入头文件即可
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu() //菜单
{
  printf("****************************\n");
  printf("******    1.  play     *****\n");
  printf("******    0.  exit     *****\n");
  printf("****************************\n");
}
void game()
{
  char board[ROW][COL] = { 0 };     //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘
  initboard(board, ROW, COL);       //此函数用于二维数组初始化
  printboard(board, ROW, COL);      //~用于打印棋盘
  while (1)
  {
    char end = '\0';
    playerMove(board, ROW, COL);  //~玩家下子
    printboard(board, ROW, COL);    //~打印棋盘
    end = ending(board, ROW, COL); //查看是否应该结束
    if (end == '*')
    {
      printf("Player WIN!!!\n");
      break;
    }
    else if (end == 'q')
    {
      printf("敌人太强大了,居然平分秋色\n");
    }
    computerMove(board, ROW, COL);    //~电脑下子
    printboard(board, ROW, COL);    //打印棋盘
    end = ending(board, ROW, COL);  //查看是否应该结束
    if (end == '#')
    {
      printf("Computer WIN!!!\n");
      break;
    }
    else if (end == 'q')
    {
      printf("平局\n");
    }
  }
}
int main()
{
    int input = 0;
    srand((unsigned)time(NULL));   //生成随机数用于人机自动落子
  do 
  {
    menu();    //do-while语句进来先打印菜单栏
    printf("请进行选择(0/1)\n");   //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了
    scanf("%d", &input);   
    switch (input)       //switch语句进行选择,一目了然
    {
    case 1:
      game();  //进入游戏
      break;
    case 0:
      printf("成功退出");
      break;
    default: 
      printf("输入错误,请重新输入");
      break;
    }
  } while (input);
}

game.c

  • 进入游戏后需要的所有函数都封装在这里
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void initboard(char board[ROW][COL],int row,int col)//此函数用于二维数组初始化
{
  memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}
void printboard(char board[ROW][COL],int row,int col)//~用于打印棋盘
{
  for (int i = 0; i < row; i++)
  {
    for (int j = 0; j < col; j++) 
    {
      printf(" %c ", board[i][j]);
      if (j<col - 1)
      {
        printf("|");
      }
    }
    printf("\n");
    if (i < row - 1) 
    {
      for (int j = 0; j < col; j++)
      {
        printf("---");
        if (j < COL - 1)
        {
          printf("|");
        }
      }
      printf("\n");
    }
  }
}
void playerMove(char board[ROW][COL], int row, int col)//~玩家下子
{
  printf("该你了,请选择坐标(?,?)\n");
  while (1)
  {
    int num1=0;
    int num2=0;
    scanf("%d,%d", &num1, &num2);
    if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0))
    {
      printf("请输入正确位置");
      continue;
    }
    if (board[num1-1][num2-1] == ' ')
    {
      board[num1-1][num2-1] = '*';
      break;
    }
    else
    {
      printf("请选择空位下子\n");
    }
  }
}
void computerMove(char board[ROW][COL], int row, int col)//~电脑下子
{
  while(1)
  {
    int num1 = rand() % row;
    int num2 = rand() % col;
    if (board[num1][num2] == ' ')
    {
      board[num1][num2] = '#';
      break;
    }
  }
  printf("你输定了小伙子\n");
}
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束
{
  for (int i = 0; i < ROW; i++)
  {
    if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
    {
      return board[0][i]; //列相等返回所在列的字符,游戏结束
    }
  }
  for (int i = 0; i < COL; i++)
  {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
    {
      return board[i][1];//行相等返回所在行的字符,游戏结束
    }
  }
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
  {
    return board[1][1];//斜线相等返回所在字符,游戏结束
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
  {
    return board[1][1];//斜线相等返回所在字符,游戏结束
  }
  for (int i = 0; i < ROW; i++)
  {
    for (int j = 0; j < COL; j++)
    {
      if (board[i][j] == ' ')
      {
        return;   //如果还有空位,则游戏继续
      }
    }
  }
  return 'q';//运行到这里证明棋盘已经满了
}

game.h

  • 将;主程序所需要的函数全部在头文件中声明,增加代码阅读性
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#define COL  3
#define ROW  3
void printboard(char board[ROW][COL], int row, int col);//~用于打印棋盘
void initboard(char board[ROW][COL], int row, int col);//此函数用于二维数组初始化
void playerMove(char board[ROW][COL], int row, int col);//~玩家下子
void computerMove(char board[ROW][COL], int row, int col);//~电脑下子
char ending(char board[ROW][COL], int row, int col);//查看是否应该结束

撒花

这就是实现三子棋的全部内容了,创作不易,还请各位小伙伴多多点赞关注,以后也会更新各种小游戏还有关于c语言的博客。



4ed92917abb246f691397003d6654cfd.gif

















相关文章
|
24天前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
69 0
|
3月前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
40 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
4月前
|
存储 C语言 开发者
C语言实战 | Flappy Bird游戏
【7月更文挑战第4天】Flappy Bird是由越南开发者制作的简单却极具挑战性的游戏,玩家需控制小鸟穿越水管障碍。游戏涉及角色初始化、显示和更新。小鸟和水管结构体存储数据,使用变量和数组。初始化小鸟和水管,显示背景、小鸟和水管,更新小鸟位置及碰撞检测。代码示例展示了小鸟和水管的状态管理,当小鸟与管道碰撞或触地时,游戏结束。游戏的成功在于其独特的虐心体验。
76 0
C语言实战 | Flappy Bird游戏
|
24天前
|
编译器 C语言
猜数字游戏实现#C语言
猜数字游戏实现#C语言
69 1
|
25天前
|
存储 C语言
揭秘C语言:泊舟的猜数字游戏
揭秘C语言:泊舟的猜数字游戏
|
24天前
|
C语言 C++
保姆式教学C语言——数组
保姆式教学C语言——数组
16 0
保姆式教学C语言——数组
|
1月前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
1月前
|
算法 编译器 C语言
【C语言】实现猜数字游戏(分支语句与循环语句的运用)
【C语言】实现猜数字游戏(分支语句与循环语句的运用)
|
20天前
|
C语言
保姆级教学 - C语言 之 动态内存管理
保姆级教学 - C语言 之 动态内存管理
15 0
|
24天前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
30 0