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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【C语言】 -- 三子棋(代码+解析)2

4.4 电脑下棋

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

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

这里也是存在一些问题,解决办法如下:


1.如何实现电脑随机输入一个坐标?


答:我们利用srand()函数来实现随机数字,但是srand()函数需要一个随机值,这里的随机值就是利用时间戳,因为时间在时刻改变着,不同的时间经过srand处理过后就得到了我们需要的随机值。因为要用时间戳,所以需要调用time函数,代码实现:

#include <time.h>

srand()函数的使用:

srand((unsigned int)time(NULL));

2.如何处理电脑随机坐标的合法性?

答:在使用srand()函数处理的随机值不再经过处理可能会出现大于棋盘的格数,所以我们需要再对srand()函数处理的随机值再进行处理,代码实现:

x = rand() % row;//0~2
y = rand() % col;//0~2

对srand传过来的随机值进行取模处理,我们的棋盘是3*3的,所以取模后得到的随机值是在0~2范围里。


3.如果出现坐标被占用的情况怎么处理?


答:我们使用while循环,如果给出的坐标位置判断不是空格,就说明是被占用,经过循环最后给出合法的坐标,实现落子后就会触发break跳出循环。

4.5 判断输赢

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

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[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[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][0];//如果连成,返回这个符号就是代表哪一玩家胜利
  //判断是否平局
  if (1 == IsFull(board, row, col))
  {
    return 'Q';
  }
  return 'C';
}

判断输赢的代码逻辑是根据游戏规则来写,行、列、对角线三子连成就认定哪一方胜出,若棋盘下满都没出现三子连成认定为平局。分别用这些符号表示:


4.5.1 三行连成

代码实现:

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];
  }

4.5.2 三列连成

代码实现:

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];
  }

4.5.3 两对角线连成

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][0];

4.5.4 平局判断

如果棋盘被下满还是没有分出胜负便是平局。

如何判断是否棋盘被下满呢?

答:我们遍历棋盘的每一个格子,如果没有一个是空格了,就返回数字 1 ,否则返回数字 0 。

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

int IsFull(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] == ' ')
        return 0;
    }
  }
  return 1;
}

IsFull()函数仅仅实现棋盘格是否被占满。在IsWin()函数中判断返回值是否是 1 ,如果是就是平局,我们这里只对棋盘格被占满判断,只需要判断返回值 1 ,如果是0便是没有占满,不用考虑,继续下棋就行。

代码实现:

if (1 == IsFull(board, row, col))
  {
    return 'Q';
  }

判断 1 == IsFull(),就返回字符'Q'。(规定 Q 是平局)

5、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");
}

逻辑顺序:创建一个数组 -- 初始化棋盘 -- 打印棋盘 -- 玩家下棋 -- 打印棋盘 -- 判断输赢(赢/输/平局:本局结束;没结果:继续) -- 电脑下棋 -- 打印棋盘 -- 判断输赢 (赢/输/平局:本局结束;没结果:继续)

逻辑顺序图示:


6、整体效果展示


完整代码在代码仓库,入口在这:


https://gitee.com/xiaobai-is-working-hard-jy/c-language-jy/tree/master/game_%E4%B8%89%E5%AD%90%E6%A3%8B/game_%E4%B8%89%E5%AD%90%E6%A3%8B


相关文章
|
20天前
|
存储 安全 Java
系统安全架构的深度解析与实践:Java代码实现
【11月更文挑战第1天】系统安全架构是保护信息系统免受各种威胁和攻击的关键。作为系统架构师,设计一套完善的系统安全架构不仅需要对各种安全威胁有深入理解,还需要熟练掌握各种安全技术和工具。
57 10
|
19天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
27 1
|
1月前
|
机器学习/深度学习 人工智能 算法
揭开深度学习与传统机器学习的神秘面纱:从理论差异到实战代码详解两者间的选择与应用策略全面解析
【10月更文挑战第10天】本文探讨了深度学习与传统机器学习的区别,通过图像识别和语音处理等领域的应用案例,展示了深度学习在自动特征学习和处理大规模数据方面的优势。文中还提供了一个Python代码示例,使用TensorFlow构建多层感知器(MLP)并与Scikit-learn中的逻辑回归模型进行对比,进一步说明了两者的不同特点。
63 2
|
1月前
|
存储 搜索推荐 C语言
深入C语言指针,使代码更加灵活(二)
深入C语言指针,使代码更加灵活(二)
|
1月前
|
存储 程序员 编译器
深入C语言指针,使代码更加灵活(一)
深入C语言指针,使代码更加灵活(一)
|
1月前
|
C语言
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
|
1月前
|
存储 搜索推荐 数据库
运用LangChain赋能企业规章制度制定:深入解析Retrieval-Augmented Generation(RAG)技术如何革新内部管理文件起草流程,实现高效合规与个性化定制的完美结合——实战指南与代码示例全面呈现
【10月更文挑战第3天】构建公司规章制度时,需融合业务实际与管理理论,制定合规且促发展的规则体系。尤其在数字化转型背景下,利用LangChain框架中的RAG技术,可提升规章制定效率与质量。通过Chroma向量数据库存储规章制度文本,并使用OpenAI Embeddings处理文本向量化,将现有文档转换后插入数据库。基于此,构建RAG生成器,根据输入问题检索信息并生成规章制度草案,加快更新速度并确保内容准确,灵活应对法律与业务变化,提高管理效率。此方法结合了先进的人工智能技术,展现了未来规章制度制定的新方向。
34 3
|
1月前
|
SQL 监控 关系型数据库
SQL错误代码1303解析与处理方法
在SQL编程和数据库管理中,遇到错误代码是常有的事,其中错误代码1303在不同数据库系统中可能代表不同的含义
|
1月前
|
SQL 安全 关系型数据库
SQL错误代码1303解析与解决方案:深入理解并应对权限问题
在数据库管理和开发过程中,遇到错误代码是常见的事情,每个错误代码都代表着一种特定的问题
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
33 3

推荐镜像

更多