C语言三子棋游戏实现(基础版)

简介: C语言三子棋游戏实现(基础版)

前言:

三子棋是一种常见的民间传统游戏,游戏为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线视为胜利,其背后的逻辑并不难,接下来跟着C用C语言把三子棋写出来,跟电脑对对线可好?

初学C语言的小伙伴放心食用~~~


注意:为了方便,我将代码做了分块,他们分别是:

test.c :main函数所在项,用于整体的运行;

game.c : 实现游戏逻辑的项;

game.h : 声明函数的项.


目录

❤️1.整体框架

🧡2.游戏逻辑

2.1数据的储存

2.2初始化棋盘

2.3打印棋盘

2.4下棋

2.4.1玩家下棋

2.4.2电脑下棋

2.5判断结局

2.5.1判断输赢

2.5.2平局

2.5.3继续

💛3.最终成果展示



1.整体框架


微信图片_20230414214241.png

基本框架类似于往期猜数字游戏

进入程序,输入1开始猜数字,输入0退出游戏,此处可用switch-case执行分支;

要使游戏至少能进行一次,可以使用do  while循环;

这样可以先写出整体框架

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{
  printf("********************\n");
  printf("*      1.play      *\n");
  printf("*      0.exit      *\n");
  printf("********************\n");
}
int main()
{
  int input = 0;//input要在do-while体系外
  do
  {
    menu();
    printf("请选择:");
    scanf("%d", &input);
    switch (input)//1-真 0-假 可作判断条件
    {
    case 1:
      //game();
      printf("三子棋\n");
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  } while (input);//1-真 0-假 可作判断条件
  return 0;
}

运行:

微信图片_20230414214357.png

整体框架完。


 

2.游戏逻辑


2.1数据的储存


要实现如下的棋盘

微信图片_20230414214453.png

要储存数据,需要一个3*3的数组;

void game()
{
  char board[3][3];
}


2.2初始化棋盘


我们发现初始状态下棋盘内都是空格,这就需要初始化,即把数组中的每个元素改为空格

void init_board(char board[3][3], 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] = ' ';
    }
  }
}


2.3打印棋盘


前面已经初始化了棋盘,再看一眼我们想要的棋盘

微信图片_20230414214637.png

对,接下来要做的就是把那些杠杠(棋盘的边)打印出来:

微信图片_20230414214711.png

我们把行中的数据+竖杠记为 1 ,分割行记为 212 的组合记为 3 

仔细观察可以发现,这些杠杠其实就是两个 3 加一个不带 2 3 组成的;


void print_board(char board[3][3], int row, int col)
{
  int i = 0;
  for (i = 0; i < row; i++)
  {
    printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);
    if(i<row-1)
      printf("---|---|---\n");
  }
}

运行:

微信图片_20230414214809.png

怎么样,是不是得到了完美的棋盘?



2.4下棋


下棋  其实就是把棋子( *  # )放到初始化后的数组里面.


2.4.1玩家下棋


要输入的是:要下的棋所在空格的坐标

注意:1.坐标不能越界

          2.不能用已占用的坐标

          3.玩家眼中的坐标和程序员眼中的坐标

第一点:

可以用 if 语句,条件就是 x 和 y 都在 1~3 之间;

第二点:

用 if 语句,判断原来的坐标是否位空格;

第三点:

微信图片_20230414215039.png

实现方法其实很简单:

输入的坐标是 (x,y)

实际更改的坐标是(x-1,y-1)

此部分代码如下:

void player_move(char board[3][3], int row, int col)
{
  printf("玩家下棋\n");
  while (1)
  {
    printf("请输入坐标:");
    int x = 0;
    int y = 0;
    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("该坐标已被占用,请重新输入\n");
      }
    }
    else
    {
      printf("坐标非法,请重新输入\n");
    }
  }
}


2.4.2电脑下棋


电脑随机生成坐标,只要未被占用就下棋;

随机数的生成不再赘述,详见往期猜数字游戏

其余跟玩家下棋类似;

void computer_move(char board[3][3], int row, int col)
{
  printf("电脑下棋\n");
  while (1)
  {
    int x = rand() % row;
    int y = rand() % col;
    if (board[x][y] == ' ')
    {
      board[x][y] = '#';
      break;
    }
  }
}


2.5判断结局


判断输赢的代码要告诉我:玩家赢了?电脑赢了?平局?游戏继续?

像这种多情况的可以各接收一个返回值作为标识;

玩家赢:返回 * ;

电脑赢:返回 # ;

平局:返回 Q ;

游戏继续:返回 C ;

while (1)
  {
    player_move(board, 3, 3);
    print_board(board, 3, 3);
    //判断
    ret = is_win(board, 3, 3);
    if (ret != 'C')
    {
      break;
    }
    computer_move(board, 3, 3);
    print_board(board, 3, 3);
    //判断
    ret = is_win(board, 3, 3);
    if (ret != 'C')
    {
      break;
    }
    }
    if (ret == '*')
      printf("恭喜你赢了!!!\n");
    if(ret=='#')
      printf("你输了\n");
    if(ret=='Q')
      printf("平局\n");


2.5.1判断输赢


根据规则,赢的情况无非就三种:行,列,对角 三子连珠;


微信图片_20230414215258.png

所以可以直接穷举 :

    //判断行
  int i = 0;
  for (i = 0; i < row; i++)
  {
    if (board[i][0] == board[i][1]&& board[i][1] == board[i][2] && board[i][0] != ' ')
    {
      return board[i][0];
    }
  }
  //判断列
  for (i = 0; i < col; i++)
  {
    if (board[0][i] == board[1][i]&& board[1][i] == board[2][i] && board[0][i] != ' ')
    {
      return board[0][i];
    }
  }
  //判断对角线
  if (board[0][0] == board[1][1]&& board[1][1] == board[2][2] && board[1][1] != ' ')
  {
    return board[1][1];
  }
  if (board[0][2] == board[1][1]&& board[1][1] == board[2][0] && board[1][1] != ' ')
  {
    return board[1][1];
  }


2.5.2平局


当输赢没有返回,且棋盘满了时就是平局;

判断每个位置是否为空格即可;

if (is_full(board, 3, 3) == 1)
  {
  return 'Q';
  } 
int is_full(char board[3][3], 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] == ' ')
        return 0;
    }
  }
  return 1;
}


2.5.3继续


没有玩家或者电脑赢,也没有平局,游戏继续;

末尾返回C即可;



3.最终成果展示


 test.c

#include"game.h"
void menu()
{
  printf("********************\n");
  printf("*      1.play      *\n");
  printf("*      0.exit      *\n");
  printf("********************\n");
}
void game()
{
  char board[3][3];
  init_board(board, 3, 3);
  print_board(board, 3, 3);
  char ret = 0;
  while (1)
  {
    player_move(board, 3, 3);
    print_board(board, 3, 3);
    //判断
    ret = is_win(board, 3, 3);
    if (ret != 'C')
    {
      break;
    }
    computer_move(board, 3, 3);
    print_board(board, 3, 3);
    //判断
    ret = is_win(board, 3, 3);
    if (ret != 'C')
    {
      break;
    }
    }
    if (ret == '*')
      printf("恭喜你赢了!!!\n");
    else if(ret=='#')
      printf("你输了\n");
    else if(ret=='Q')
      printf("平局\n");
}
int main()
{
  srand((unsigned int)time(NULL));
  int input = 0;
  do
  {
    menu();
    printf("请选择:");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  } while (input);
  return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void init_board(char board[3][3], 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 print_board(char board[3][3], int row, int col)
{
  int i = 0;
  for (i = 0; i < row; i++)
  {
    printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);
    if(i<row-1)
      printf("---|---|---\n");
  }
  int n = 0;
  if(n > 1)
  {
    return;
  }
}
void player_move(char board[3][3], int row, int col)
{
  printf("玩家下棋\n");
  while (1)
  {
    printf("请输入坐标:");
    int x = 0;
    int y = 0;
    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("该坐标已被占用,请重新输入\n");
      }
    }
    else
    {
      printf("坐标非法,请重新输入\n");
    }
  }
}
//电脑下棋
//随机生成坐标,只要没有被占用,就生成棋子
void computer_move(char board[3][3], int row, int col)
{
  printf("电脑下棋\n");
  while (1)
  {
    int x = rand() % row;
    int y = rand() % col;
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if (board[x][y] == ' ')
      {
        board[x][y] = '#';
        break;
      }
    }
  }
}
static int is_full(char board[3][3], 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] == ' ')
        return 0;
    }
  }
  return 1;
}
//判断输赢
char is_win(char board[3][3], int row, int col)
{
  //判断行 
  int i = 0;
  for (i = 0; i < row; i++)
  {
    if (board[i][0] == board[i][1]&& board[i][1] == board[i][2] && board[i][0] != ' ')
    {
      return board[i][0];
    }
  }
  //判断列
  for (i = 0; i < col; i++)   
  {
    if (board[0][i] == board[1][i]&& board[1][i] == board[2][i] && board[0][i] != ' ')
    {
      return board[0][i];
    }
  }
  //判断对角线
  if (board[0][0] == board[1][1]&& board[1][1] == board[2][2] && board[1][1] != ' ')
  {
    return board[1][1];
  }
  if (board[0][2] == board[1][1]&& board[1][1] == board[2][0] && board[1][1] != ' ')
  {
    return board[1][1];
  } 
  //平局
  if (is_full(board, 3, 3) == 1)
  {
    return 'Q';
  }
  //继续
  return 'C';
}

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//声明函数
//初始化棋盘
void init_board(char board[3][3], int row, int col);
//打印棋盘
void print_board(char board[3][3], int row, int col);
//玩家下棋
void player_move(char board[3][3], int row, int col);
//电脑下棋
void computer_move(char board[3][3], int row, int col);
//判断输赢
char is_win(char board[3][3], int row, int col);

如果你觉得这篇文章还不错并且对你有帮助,不妨动动手指点赞收藏加转发,给一个大大的关注

你们的每一次支持都将转化为我前进的动力!!!💗💗💗

目录
相关文章
|
1月前
|
C语言
C语言之斗地主游戏
该代码实现了一个简单的斗地主游戏,包括头文件引入、宏定义、颜色枚举、卡牌类、卡牌类型类、卡牌组合类、玩家类、游戏主类以及辅助函数等,涵盖了从牌的生成、分配、玩家操作到游戏流程控制的完整逻辑。
76 8
|
2月前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
128 0
|
4月前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
47 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
27天前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
45 2
|
5月前
|
存储 C语言 开发者
C语言实战 | Flappy Bird游戏
【7月更文挑战第4天】Flappy Bird是由越南开发者制作的简单却极具挑战性的游戏,玩家需控制小鸟穿越水管障碍。游戏涉及角色初始化、显示和更新。小鸟和水管结构体存储数据,使用变量和数组。初始化小鸟和水管,显示背景、小鸟和水管,更新小鸟位置及碰撞检测。代码示例展示了小鸟和水管的状态管理,当小鸟与管道碰撞或触地时,游戏结束。游戏的成功在于其独特的虐心体验。
86 0
C语言实战 | Flappy Bird游戏
|
1月前
|
C语言 Windows
C语言课设项目之2048游戏源码
C语言课设项目之2048游戏源码,可作为课程设计项目参考,代码有详细的注释,另外编译可运行文件也已经打包,windows电脑双击即可运行效果
34 1
|
2月前
|
编译器 C语言
猜数字游戏实现#C语言
猜数字游戏实现#C语言
99 1
|
2月前
|
存储 C语言
揭秘C语言:泊舟的猜数字游戏
揭秘C语言:泊舟的猜数字游戏
100 2
|
2月前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
2月前
|
算法 编译器 C语言
【C语言】实现猜数字游戏(分支语句与循环语句的运用)
【C语言】实现猜数字游戏(分支语句与循环语句的运用)