C语言小项目——井字棋游戏(升级版)

      最后更新:2022-01-26 09:43

      ? 前言

      Wassup guys?

      今天是我们的C语言小项目「井字棋升级版」

      Let’s get it!
      在这里插入图片描述

      文章目录

      • 游戏说明
      • 游戏效果展示
      • 游戏代码
      • 游戏代码详解
        • ? 游戏菜单构建
        • ? 主函数构建
        • ? 三子棋的过程
          • ? 构建棋盘数组
          • ? 初始化棋盘数组
          • ? 打印棋盘
          • ? 玩家下棋
          • ? 电脑下棋
          • ? AI电脑算法升级
          • ? 判断输赢
          • ? 主函数判断输赢
        • ? AI算法思路二

      游戏说明

      井字棋,又名三子棋,英文名叫Tic-Tac-Toe;

      是一种在3x3格子上进行的连珠游戏,和五子棋类似,格线排成井字故得名。

      游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜。

      其游戏过程就像下面这样?
      在这里插入图片描述

      游戏效果展示

      游戏运行结果如下?

      在这里插入图片描述

      游戏代码

      我在 函数 这一篇总结中,讲过函数的声明和定义,所有这里我用三个文件来实现这个三子棋游戏

      友友们可以将以下代码复制到自己的编译器当中运行:

      ◾ game.h

      游戏函数的声明

      ◾ game.c

      游戏函数的实现

      ◾ test.c

      测试游戏

      游戏代码详解

      ? 游戏菜单构建

      打印一个游戏菜单,有两种选择

      1、玩游戏

      0、退出游戏

      代码实现?

      在这里插入图片描述

      ? 主函数构建

      当运行这个游戏的时候,会首先生成一个菜单,让我们选择;

      但是当我玩完一局过后,还想再玩,所以会用到循环

      代码实现?

      在这里插入图片描述

      ? 三子棋的过程

      在game()函数,去实现三子棋的过程

      ? 构建棋盘数组

      三子棋,顾名思义,我们要定义一个3x3的二维数组棋盘

      ? 初始化棋盘数组

      当棋盘数组定义好以后,我们就要初始化棋盘

      可以看到,这个棋盘里面最开始都是空的,所以我们把棋盘定义成空的字符
      在这里插入图片描述

      首先我们要在 game.h头文件里面去声明这个初始化函数

      然后再去 game.c游戏函数里面实现

      在这里插入图片描述

      注意:后面的函数也是一样,要先去头文件里面声明,再到游戏函数里面去实现

      ? 打印棋盘

      我们初始化好棋盘以后,要在屏幕上打印一下

      在这里插入图片描述
      聪明的朋友能猜到这个棋盘是怎么想出来的吗?

      代码实现?

      在这里插入图片描述

      ? 玩家下棋

      接下来就是玩家开始下棋;

      由于是个二维数组,并且数组下标是从0开始的,但是玩家可能不是程序员,所以不知道数组的下标;

      所以这里把下标定义从1开始;

      并且当玩家在棋盘落子以后,我们把棋盘打印出来。

      代码实现?

      在这里插入图片描述

      ? 电脑下棋

      电脑下棋的方法我们选择用时间戳来生成一个随机数,并把随机数的范围控制在0~3以内;

      关于随机数的生成,这里简单说一下
      在这里插入图片描述

      代码实现?

      注意,我们这里调用rand函数,必须在主函数里面设置一下srand函数
      在这里插入图片描述
      在这里插入图片描述

      ? AI电脑算法升级

      如果你运行了这个程序以后,会发现电脑的走法貌似不太聪明的样子;

      因为我们用随机数生成,会造成玩家赢的很轻松;

      那如果电脑有了AI的思想呢?它就知道如何进攻、防守。

      那么来思考一下,你是怎么下三子棋的?

      1、如果我们在三行、三列、对角线上,下了两个棋子后,我们会继续下第三个;

      2、如果对方在三行、三列、对角线上有了相同两个棋子后,我们会堵截,不让它下第三个;

      此时我们就有了思路?

      电脑需要的就是在:出现两个相同的棋子的地方下自己的棋子就好了

      ?代码一

      对ComputerMove函数进行修改;

      电脑下棋需要加一步,获取返回值,如果返回值为0,那么电脑只有乖乖的按照伪随机数来走啦

      ?代码二

      定义一个函数:CheckComputer,作用是电脑检查自己是否会赢;

      1、电脑在坐标(1,1)和坐标(1,2)的格子进行判断,如果(1,1)或者(1,2)的格子都为自己的棋子,那么直接在(1,3)的格子落子?
      在这里插入图片描述
      2、电脑在坐标(1,1)和坐标(1,3)的格子进行判断,如果(1,1)或者(1,3)的格子都为自己的棋子,那么直接在坐标(1,2)的格子落子?
      在这里插入图片描述
      3、电脑在坐标(1,2)和坐标(1,3)的格子进行判断,如果(1,2)或者(1,3)的格子都为自己的棋子,那么直接在坐标(1,1)的格子落子?
      在这里插入图片描述
      此时我们只需要定义一个循环,三行都进行判断即可,同理,三列和对角线也是一样

      三行
      在这里插入图片描述
      三列
      在这里插入图片描述
      左对角线
      在这里插入图片描述
      右对角线
      在这里插入图片描述
      完整代码
      在这里插入图片描述

      ?代码二

      定义一个函数:CheckPlayer,作用是电脑检查玩家是否会赢;

      如果玩家在三行、三列、对角线上有了相同两个棋子后,电脑会堵截,不让玩家下第三个

      1、电脑在坐标(1,1)和坐标(1,2)的格子进行判断,如果(1,1)或者(1,2)的格子都为玩家的棋子,那么直接在(1,3)的格子落子堵截?
      在这里插入图片描述
      2、电脑在坐标(1,1)和坐标(1,3)的格子进行判断,如果(1,1)或者(1,3)的格子都为玩家的棋子,那么直接在(1,2)的格子落子堵截?
      在这里插入图片描述
      3、电脑在坐标(1,2)和坐标(1,3)的格子进行判断,如果(1,2)或者(1,3)的格子都为玩家的棋子,那么直接在(1,1)的格子落子堵截?
      在这里插入图片描述
      此时我们只需要定义一个循环,三行都进行判断即可,同理,三列和对角线也是一样

      三行
      在这里插入图片描述
      三列
      在这里插入图片描述
      左对角线
      在这里插入图片描述
      右对角线
      在这里插入图片描述
      完整代码
      在这里插入图片描述

      ? 判断输赢

      当玩家或者电脑每下一步棋的时候,我们就定义一个函数,判断一下谁赢了;

      当棋盘已经落满棋子的时候,并且谁也没有赢,我们就认定为平局;

      当棋盘还没有落满棋子的时候,并且谁也没有赢,游戏就继续;

      1、玩家赢 —> 返回x

      2、电脑赢 —> 返回o

      3、平局 —> 返回P;

      4、继续 —> 返回C;

      那么怎么来判断输赢呢?

      其实很简单,你看这个棋盘?
      在这里插入图片描述
      当三行或者三列,以及两条对角线都落满相同的棋子时,那就就赢了;

      举个例子?

      如图,当第一行全部落满相同的棋子
      在这里插入图片描述

      那么我们就返回中间红色这个位置的棋盘,并拿去判断;
      在这里插入图片描述
      如果是x号,那么就是玩家胜利;

      如果是o号,那么就是电脑胜利

      代码示例?

      三行判断
      在这里插入图片描述
      三列判断
      在这里插入图片描述
      对角线判断
      在这里插入图片描述
      判断平局
      在这里插入图片描述
      游戏继续
      在这里插入图片描述

      ? 主函数判断输赢

      玩家和电脑下棋的思路可以这样理解?

      当玩家每下一步棋时,就进行输赢判断;

      当电脑每下一步棋时,也进行输赢判断;

      但是玩家走一步,电脑走一步,必须要拿循环来实现;

      那么跳出循环的条件是什么呢?

      上面已经分析了判断输赢的四种情况;

      如果当棋盘已经全部落子了,就表示游戏不能再继续了,所以就可以跳出循环;

      跳出来以后,就把上面判断输赢函数返回的结果来进行比较;

      如果是x,表示玩家赢了;

      如果是o,表示电脑赢了;

      如果是P,表示平局了。

      循环走棋
      在这里插入图片描述
      判断
      在这里插入图片描述

      ? AI算法思路二

      其实上面的AI算法虽然说可以让电脑进行攻击和截堵,但还是有点缺陷,所以再给大家介绍一种。

      这个算法很精妙,可以让玩家永远赢不了电脑,最多也就只能打成平局

      首先第一步始终让电脑先落子,并且电脑落子的地方永远在坐标为(1,1)的格子里面?

      (注:#表示电脑,*表示玩家)
      在这里插入图片描述
      此时玩家落子就有剩余的8个格子可以选择

      那么我们就遍历每一个格子,并推演出让电脑赢的方法(这里给大家演示一种)

      第一步:首先电脑在坐标(1,1)落子;

      第二步:玩家在坐标(1,2)落子;
      在这里插入图片描述
      第三步:电脑在坐标(3,1)落子;

      第四步:玩家在坐标(2,1)落子;
      在这里插入图片描述
      第五步:电脑在坐标(3,3)落子;
      在这里插入图片描述
      第六步:此时玩家不管在棋盘剩余空格的任意位置落子,都已经输了?
      在这里插入图片描述
      是不是很妙?其实五子棋的AI算法也类似,到时候会出一篇结合EasyX的图形化五子棋?

      ?结语

      编程这件事情,你如果不练习,你只是学了语法而已,那是绝对不会写代码的?

      ?我是Edison,你知道的越多,你不知道越多,我们下期见!

      本文由 在线网速测试 整理编辑,转载请注明出处。

          热门文章

          文章分类