【C语言】 -- 三子棋(代码+解析)1

简介: 【C语言】 -- 三子棋(代码+解析)1

前言:

该篇文章是用C语言来实现三子棋的,是对之前的知识灵活运用加以巩固,如何合理的分块来写一个工程性的代码,大家仔细看看,哪里要有不对的地方请一定要指出来。


1、游戏规则

我们在玩三子棋的时候,用户先落子再是电脑落子,用户或者电脑玩家在3*3的棋盘上最终落子为行或列是三子连成,或者两个对角线是三子连成的,就认定哪一玩家胜出。如若棋盘下满都没出现三子连成认定为平局。


2、创建文件

我们需要分块来写不同用途的文件,在实现三子棋我们需要分三个文件,分别是:


game.h //头文件(包含所有需要的用到的头文件,define定义的常量,函数声明)


注:我们将2.1,2.2,2.3全部写在此文件中目的在于,game.c和test.c中调用这些内容时,只需要对我们自己写的game.h声明一次便可直接使用里面的内容。


game.c //游戏文件(里面分别写入所要用到功能函数)


test.c //测试文件(代码的整合)

2.1 头文件

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

2.2 用define定义行列

优点:如果我们后期需要改棋盘大小的时候只需要在这里改,一劳永逸,不用在整个程序中修改。

#define ROW 3
#define COL 3

2.3 函数声明

//初始化棋盘
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);
//判断输赢
//玩家赢 -- '*'
//电脑赢 -- '#'
//平局   -- 'Q' 
//继续   -- 'C'
char IsWin(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

3、游戏测试部分

3.1 主函数

这部分先写出玩游戏的逻辑

int main()
{
  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;
}

对主函数内容的分析:

3.1.1 menu()函数(菜单函数)

void menu()
{
  printf("***********************\n");
  printf("\t1.play\n");
  printf("\t0.exit\n");
  printf("***********************\n");
}

效果展示:


3.1.2 switch语句

switch语句实现了用户在选择不同菜单的实现

效果展示:



3.1.3 do while语句

这里使用dowhile语句是实现先运行主函数,然后再进行选择,主函数会根据用户的选择进行实现不同的功能。

3.1.4 game()函数

在玩家选择数字 1 便会调用game()函数,实现以下功能。

void game()
{
  srand((unsigned int)time(NULL));
  //存放数据需要一个3*3的二维数组
  char board[ROW][COL] = { 0 };
  //初始化棋盘
  InitBoard(board, ROW, COL);
  //显示棋盘
  DisplayBoard(board, ROW, COL);
  char ret = 0;
  while (1)
  {
    //玩家下棋 - *
    PlayerMove(board, ROW, COL);
    //打印棋盘
    DisplayBoard(board, ROW, COL);
    //判断输赢
    ret = IsWin(board, ROW, COL);
    if (ret != 'C')
    {
      break;
    }
    //电脑下棋 - #
    ComputerMove(board, ROW, COL);
    //打印棋盘
    DisplayBoard(board, ROW, COL);
    //判断输赢
    if (ret != 'C')
    {
      break;
    }
  }
  if ('*' == ret)
    printf("玩家赢\n");
  else if ('#' == ret)
    printf("电脑赢\n");
  else
    printf("平局\n");
}

game()函数中包含了初始化棋盘函数、显示棋盘函数、玩家下棋函数、电脑下棋函数、判断输赢函数的调用,这些函数在下面我们展开来分析。

game()函数我们在最后进行逻辑的解析。

4、游戏功能实现部分

游戏的实现逻辑

4.1 打印棋盘函数

首先我们需要打印出棋盘,棋盘是 3*3 的样式

头文件里面包含了行、列

定义DisplayBoard()函数打印棋盘,棋盘打印时包含了数据和分割行,代码实现:

void DisplayBoard(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++)
    {
      printf(" %c ",board[i][j]);
      if (j<col-1)
        printf("|");
    }
    printf("\n");
        //分割行
    if (i < row - 1)//---只打印两行
    {
      for (j = 0; j < col; j++)
      {
        printf("---");//每行需要3个---
        if(j<col-1)
          printf("|");
      }
    }
    printf("\n");
  }
}

效果展示:


4.2 初始化棋盘函数

定义InitBoard()函数,代码实现:

void InitBoard(char board[ROW][COL], int row, int col)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)//3行
  {
    for (j = 0; j < col; j++)//3列
    {
      board[i][j] = ' ';
    }
  }
}

将棋盘初始化为空格。

4.3 玩家下棋

定义PlayerMove()函数,代码实现:

void PlayerMove(char board[ROW][COL], int row, int col)
{
  int x = 0;
  int y = 0;
  printf("玩家下棋:>\n");
  while (1)
  {
    printf("请选择你要下棋的坐标:>");
    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");
    }
  }
}

这里存在一个小细节,以及一些问题,相应的解决办法如下:


我们在写代码的时候知道第一个位置的坐标是(0,0),但是在玩家眼里第一个位置的坐标是(1,1),所以玩家输入的数字(x,y)是程序的(x-1,y-1)位置。


1.用户输入的坐标棋盘上没有怎么处理?


答:这里我们使用了if-else语句,如果坐标合法,那么玩家的棋子正常落子;如果坐标非法,程序会提醒"坐标非法,请重现输入坐标"的字样,利用while循环使玩家输入合法的坐标正确落子后在跳出循环。


2.用户输入的坐标已被占用怎么处理?


答:这里还是使用if-else语句,我们在初始化棋盘的时候用空格将每个位置占着,如果这个位置是空格,这个位置便会正常落子*;如果这个位置是非空格符号(本文中只会是*或者#),那么这个位置就是被占用了,程序会提醒"位置已被占用,请重新输入"的字样,利用while循环使玩家输入没有被占用且合法的坐标正确落子后在跳出循环。


相关文章
|
8天前
|
测试技术
函数式编程代码片段(无解析,代码纯享版)
函数式编程代码片段(无解析,代码纯享版)
11 0
|
3天前
|
算法 C语言
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)(下)
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)
9 0
|
3天前
|
C语言
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)(中)
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)
14 0
|
3天前
|
C语言
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)(上)
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)
14 0
|
3天前
|
程序员 编译器 测试技术
C语言初阶⑨(调试)(如何写出好的代码)(模拟实现strcpy和strlen)
C语言初阶⑨(调试)(如何写出好的代码)(模拟实现strcpy和strlen)
11 1
|
3天前
|
机器学习/深度学习 存储 并行计算
深入解析xLSTM:LSTM架构的演进及PyTorch代码实现详解
xLSTM的新闻大家可能前几天都已经看过了,原作者提出更强的xLSTM,可以将LSTM扩展到数十亿参数规模,我们今天就来将其与原始的lstm进行一个详细的对比,然后再使用Pytorch实现一个简单的xLSTM。
18 2
|
7天前
|
C语言
C语言扫雷代码(蹦蹦炸弹)(下)
C语言扫雷代码(蹦蹦炸弹)(下)
6 0
|
8天前
|
机器学习/深度学习 编解码
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析2
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析
18 2
|
8天前
|
机器学习/深度学习 计算机视觉
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析1
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析
17 1
|
C语言
C语言实现简单黑客帝国代码流
#include #include #include #include int main() { int count ; int i , j ; char buffer[50][50] = {0} ; system("color 0A"); sra...
1472 0

推荐镜像

更多