C语言设计三子棋

简介: C语言设计三子棋

引入

 谈到三子棋,大家应该都不陌生,学生时代我们大多人都爱拿作文本有事没事就跟同桌下两把,只要任意一方三点连成一线,就可以胜利。今天我作为一个计算机方面的博主,将会用C语言实现这个简单的小游戏(人机对战,电脑非智能)。由于三子棋是3*3的棋盘,所以我们主要要用到二维数组的有关知识点,该项目也是主要围绕二维数组来展开的。

基本框架

要实现这个简单的游戏,也需要实现不同的函数与结构,也要将不同部分放在不同源文件里,我们今天将会用(test.c-测试游戏的代码部分)和(game.c-游戏有关函数的实现),还有(game.h-游戏有关函数声明),下面我们来看一下这个游戏的框架。

首先我们先来看一下主函数的基本框架:

int main()
{
  int input = 0;//利用input来记录玩家的选择
  srand((unsigned int)time(NULL));//随机数时间戳设定,后面会用到
  do//设置循环使玩家在推出游戏前可多次选择再次游玩
  {
    menu();//打印一个基本的菜单,这里选择1.play(玩)或 0.exit(退出游戏)
    printf("请选择:>\n");
    scanf("%d", &input);
    switch (input)//根据input进入不同选择
    {
    case 1:
      game();//选1直接进入游戏
      break;
    case 0:
      printf("退出游戏\n");//后面input也为0,在while(input)为假,结束程序
      break;
    default:
      printf("选择错误,请重新选择:>\n");
      break;
    }
  } while (input);
  return 0;
}

下面我们来看一下game.h这个头文件,上面的思维导图也有讲,这里包含的是函数声明等内容,

game.c和test.c都会使用到,非常重要。

//所用库函数的头文件
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3//ROW即行数,定义为3
#define COL 3//COL即列数
 
//所需要函数的函数声明
void menu();
void Initboard(char board[ROW][COL], int row, int col);
void Displayboard(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 Iswin(char board[ROW][COL], int row, int col);

然后我们来看一下这个游戏运行的大致逻辑,由test.c中的game()函数展示。

void game()
{
  char board[ROW][COL] = { 0 };//定义数组board,作为三子棋的主要框架
  Initboard(board,ROW,COL);//初始化二维数组(棋盘)
  Displayboard(board, ROW, COL);//打印棋盘
  char ret = 0;//这里定义字符类型ret,与后面判断输赢平有关
  while (1)//若未分胜负或者棋盘满了,则一直下,满足条件时跳出
  {
/*首先玩家下棋,然后展示一下棋盘,
然后利用Iswin函数判断输赢
(Iswin会返回一个字符,用ret接受,在后面进行判断)*/
    Playermove(board, ROW, COL);//玩家下棋函数
    Displayboard(board, ROW, COL);
    ret = Iswin(board, ROW, COL);
/*电脑下棋,方法同上*/
    Computermove(board, ROW, COL);//电脑下棋函数
    Displayboard(board, ROW, COL);
    ret = Iswin(board, ROW, COL);
//---为了更好地理解,这里先大致讲一下Iswin函数的大致逻辑。
//判断输赢,在玩家后者电脑每一次落子之后进行判断
//玩家赢 则返回'*'
//电脑赢 则返回'#'
//继续   则返回'C'
//平局   则返回'Q'
    if (ret != 'C')
      break;//如果未返回'C',跳出对战,对最终结果进行判断
  }
//最终结果的判断
  if (ret == '*')
  {
    printf("玩家赢\n");
  }
  else if (ret == '#')
  {
    printf("电脑赢\n");
  }
  else if (ret == 'Q')
  {
    printf("平局\n");
  }
}

根据前面的内容,相信你一定了解了三子棋项目的大致逻辑,下面,我将对game()中所使用的所有函数,进行逐一讲解。

具体函数讲解

Initboard(初始化棋盘)函数:分析:棋盘是用来落子的,在程序中就是用来存放数据的,我们能自然而然地想到用二维数组来存放数据.

//参数说明:二维数组board,行数row,列数col。
void Initboard(char board[ROW][COL], int row, int col)
{
    //利用两个for循环对二维数组进行遍历,二维数组存放的数据都初始化为空格
  int i = 0;
  for (i = 0; i < row; i++)
  {
    int j = 0;
    for (j = 0; j < col; j++)
    {
      board[i][j] = ' ';
    }
  }
}
//这样就完成了棋盘的初始化

Display(打印棋盘)函数:分析:这个函数是这个项目的一个难点,磨刀不误砍柴工,首先让我们来看一下这个棋盘长什么样:

 

可以看出,该棋盘是由“ %c | %c | %c ”与“---|---|---”交替连接而成的。我们可以将“ %c | %c | %c ”与“---|---|---”作为一个分割行的部分,当到达最后一行时,再少打印一个“---|---|---”,然后,我们再将“ %c |”和“---|”作为每一个分割列的部分,当到达最后一列时,两个部分都不打印“|”。

下面我们来看一下代码实现:

void Displayboard(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]);
      if (j < COL - 1)
        printf("|");
    }
    printf("\n");
    for (j = 0; j < COL; j++)
    {
      if (i < ROW - 1)
      {
        printf("---");
        if (j < ROW - 1)
          printf("|");
      }
      if (j == COL - 1)
        printf("\n");
    }
  }
}

Playermove(玩家落子)函数:分析:这里主要记录玩家的落子,需要等待玩家输入要下的坐标。

这里主要要注意两点:1.玩家不是程序员,他输入的坐标肯定不是数组形式的(数组首元素从1开始),因此要注意输入坐标与数组元素的关系

2.注意坐标的合法性:应该需要有判断,判断坐标是否合法(输入坐标超出数组的实际范围,输入的坐标那里有其他内容),若不合法,则重新输入,所以外层应该还需要嵌套循环

void Playermove(char board[ROW][COL], int row, int col)
{
  printf("玩家下棋\n");
  printf("请输入下的坐标:>");
  int i = 0, j = 0;
  while (1)
  {
    scanf("%d%d", &i, &j);
//输入坐标-1即为数组中对应坐标
    if ((board[i - 1][j - 1] != ' ')||(i - 1>ROW||j - 1>COL))
    {
      printf("输入坐标非法,请重新输入!");
    }
    else
    {
      board[i - 1][j - 1] = '*';//坐标合法,对应坐标落子'*'
      break;
    }
  }
}

Computermove(电脑落子)函数:分析:这里主要记录电脑的落子,需要电脑随机确定下的坐标。

注意:这里的电脑落子坐标需要随机,即需要rand()函数(在主函数中已经定义随机数时间戳,确保了完全随机),而且随机数可以指定范围,因此在落子合法性上不需要判断越界问题。

下面再来看一下代码实现。

void Computermove(char board[ROW][COL], int row, int col)
{
  printf("电脑下棋\n");
  int i = 0;
  int j = 0;
  while (1)
  {
    i = rand() % ROW;//范围为(0-2)
    j = rand() % COL;//范围为(0-2)
    if (board[i][j] == ' ')
    {
      board[i][j] = '#';//输入坐标合法,落子为'#'
      break;
    }
  }
}

Iswin(判断输赢平)函数:分析:这里就运用到了三子棋的规则(三行其一或三列其一或主次对角线连成一线即可)。定义类型为char,上文也说过,该函数返回的字符有决策功能。

下面来看一下代码实现:

//Isfull是一个判断棋盘是否满了的辅助函数
int Isfull(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++)
    {
      if (board[i][j] == ' ')
      {
        return 0;//未满返回0
      }
    }
  }
  return 1;//已满返回一
}
 
char Iswin(char board[ROW][COL], 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[1][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[0][0] != ' ')
    return board[0][0];
    //判断此对角线是否连成一线
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
    return board[0][2];
    //利用Isfull判断棋盘是否满了,满了则平局
  if (Isfull(board, row, col) == 1)
  {
    return 'Q';
  }
  return 'C';
}

以上就是所有函数,下面我们来运行一下试试:

这里作者由于

太菜

输了。

好了,三子棋就分享到这,拜拜。

相关文章
|
7月前
|
C语言
以c语言为基础实现的简易三子棋
以c语言为基础实现的简易三子棋
43 1
|
7月前
|
C语言
c语言简单三子棋
c语言简单三子棋
|
7月前
|
算法 C语言 C++
【C语言实战项目】三子棋游戏
【C语言实战项目】三子棋游戏
62 1
|
7月前
|
C语言
C语言之三子棋小游戏
C语言之三子棋小游戏
|
7月前
|
C语言
用c语言实现三子棋
用c语言实现三子棋
30 0
|
6月前
|
C语言
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
32 1
|
7月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
82 1
|
7月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
96 1
|
7月前
|
编译器 C语言
【C语言入门小游戏】三子棋
【C语言入门小游戏】三子棋
56 0
【C语言入门小游戏】三子棋
|
7月前
|
C语言
【用C语言轻松搞定】三子棋(超详细教程)
【用C语言轻松搞定】三子棋(超详细教程)