C语言 三子棋以及推广到n x n(上)

简介: C语言 三子棋以及推广到n x n

前言

🎈大家好,我是何小侠🎈

🌀大家可以叫我**小何或者小侠🌀**

🔴我是一名普通的博客写作者🔴

💐希望能通过写博客加深自己对于学习内容的理解💐

🌸也能帮助更多人理解和学习🌸

🍃我的主页:何小侠的主页🍃



    这篇博客我们一起来学习如何用C语言所学知识来实现三子棋,另外我们还将推广到更大的棋盘。希望能帮助大家理解和学习

    🍊

    引子🍊

    三子棋这个游戏大家都应该不陌生,大家应该在学校和小伙伴们玩过,这里就不介绍规则了,给大家介绍一下三子棋的历史(也可能是野史)。

    关于《三子棋》的起源,年代之远古已经不可考究。但是严肃地讲,三子棋很可能是历史上最早使用类似“三消”原则作为棋理的棋种。古有记载,所谓三消,即以三为理,遇三则消失。

    据说,明朝史上最会玩的正德皇帝–朱厚照经常会有一些出人意料的想法和举动,比如在宫中模拟开酒店、店铺和怡红院荒诞行为,甚至还经常偷跑出宫去玩。为了安抚这位不省心的皇帝,老臣李东阳曾将三子棋推荐给皇帝,奈何这个棋皇上玩了几次就没兴趣了,因为它有一个极大的BUG:熟悉规则的双方,理论上可以达到100%的平局。

    于是古人在三连为赢的基础上逐渐升级难度并改进玩法,创造出更多种类的游戏。比如说五子棋,其实就是根据三子棋演变而来,甚至是如今流行的各种版本的消消乐其实也是在三连消的基础规则上演变而来的。


      游戏模块介绍🍊

      这是我们第一次接触模块化编程,下面我们解释一下模块化编程的好处
      • 首先我们先介绍一下什么是模块化编程:
        我们在写一个项目的时候,需要将这个项目分成用多个.c的源文件或者.h的头文件来实现,每个.c文件就相当于一个模块,比如计算器的实现,我们将加减乘除分成4个.c文件来实现,而.h文件则是用来放声明。
        -模块化的实际应用:
        比较传统的编程模式,即将所有文件全部集中于main函数,或者全部集中在一个.c文件。我们可以试想如果你写了一个很长的代码有1万行,当你想修改5500行的代码。在这个过程中,你会觉得很繁琐,冗杂,因为你的代码没有一个清晰的分类,把所有功能集中在一起不仅不利于你自己的观看,别人看起来也没有兴趣。而且在我们以后的工作中或者多人一起开发项目的时候,每个人只要分工明确,各种完成自己的模块就行,将你的.c和.h文件与其他人的一结合,这个项目就初步完成了,后续再经过调试等过程,就完成了整个工程。
      • 模块化编程的优点极大的提高代码的可阅读性、可维护性、可移植性并且它使得整个项目分工明确,条理清晰

      游戏思路🍊

      这张图片就是我们的整体思路,接下来我们会逐步实现。

      main

      void test()
      {
        int input = 0;
        srand((unsigned int)time(NULL));
        do
        {
          menu();
          printf("请输入\n");
          scanf("%d", &input);
          switch (input)
          {
          case 1:
            printf("三子棋\n"); 
            game();
            break;
          case 0:
            printf("退出游戏\n");
            break;
          default:
            printf("输入错误,请重新输入\n");
            break;
          }
        } while (input);
      }
      int main()
      {
        test();
        return 0;
      }

      还是是我们经典的do-while+Switch的结构srand和time函数如果看到这里不懂可以去看看我之前的关于猜数字游戏的博客 link这个链接里面是有srand rand 以及time函数的讲解的。

      menu

      void menu()
      {
        printf("*********************\n");
        printf("***  1.play     *****\n");
        printf("***  0.eixt     *****\n");
        printf("*********************\n");
      }

      二维数组定义和初始化

      char board[ROW][COL];
      void intiboard(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++)
          {
            board[i][j] = ' ';
          }
        }
      }

      这里的ROW COL 是我们在头文件中用#define定义的,因为我们要玩三子棋所以我们设置为3,3。之后我们会拓展一下,例如,在5x5的棋盘里面玩三子棋。

      打印棋盘

      实际上我们打印棋盘有两种写法,一种是只适合3x3棋盘的,一种是可以随我们设定的ROW,COL随之改变的。我们先介绍第一种只适合3x3的

      这是我们要打印的棋盘,我们仔细观察一下行,然后想一下该如何写代码。

      通过观察我们知道第一行就是 这个两个竖线 | | ,第二行就是—|—|—
      ,然后第三行第五行都与第一行一样,第4行与第2行一样。这是我们初步的分析。但是我们知道我们要在这个棋盘上面下棋 × ○这样的符号 ,所以第一行其实实际上是space%cspace,为什么不只是一个%c呢?大家可以尝试在自己的电脑上对比一下 - 和 space,这两个实际上都占有一个字符。
      然后我们尝试一下用代码写出一个棋盘。如果有问题可以与下面的代码作比较

      void printboard(char board[ROW][COL], 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");
        }
      }

      上面就是我们没有优化的打印棋盘的代码,我们简单讲解一下,因为

      %c | %c | %c 要打印三行就可以直接用for循环打印,但是—|—|—只需要打印两行就要控制一下,,i < row是三次,用 i < row -1就是两次。

      我们在最开始就说过这个打印代码是不符合3x3以上棋盘的,所以我们要在词基础上加以改进。下面展示一下10x10情况下这个代码的打印情况让大家知道确实不能进行推广。

      我们看到行确实没有出错但是我们更需要在列上下功夫。

      下面我们再加深讨论,请看图。

      我们将列进行拆分。
      我们看蓝花这一行,发现space%cspace打印三次而 | 只打印两次。
      我们看红花这一行,发现—打印三次 | 也只打印两次。

      通过分析我们就能够就用代码实现,大家可以先动手实践一下。

      下面的代码。

      void printboard(char board[ROW][COL], int row, int col)
      {
        int j = 0;
        int i = 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");
          for (j = 0; j < col; j++)
          {
            if (i < row - 1)
            {
              printf("---");
              if (j < col - 1)
                printf("|");
            }
          }
          printf("\n");
        } 
      }

      我们还是和最初版本一样用 j < col -1来控制只出现两次的线条。用三个for循环,最外层控制有多少行,里面的两个for循环用来控制每行的列的打印。


      目录
      相关文章
      |
      5月前
      |
      C语言
      【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
      【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
      28 1
      |
      6月前
      |
      C语言
      万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
      我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
      62 1
      |
      6月前
      |
      算法 C语言 C++
      万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
      三子棋游戏设计的核心是对二维数组的把握和运用。
      72 1
      |
      5月前
      |
      存储 C语言
      三子棋(C语言版)
      三子棋(C语言版)
      |
      6月前
      |
      编译器 C语言
      【C语言入门小游戏】三子棋
      【C语言入门小游戏】三子棋
      52 0
      【C语言入门小游戏】三子棋
      |
      5月前
      |
      程序员 C语言 索引
      【️C语言-游戏设置】---三子棋(N满)
      【️C语言-游戏设置】---三子棋(N满)
      |
      6月前
      |
      人工智能 算法 数据可视化
      C语言”三子棋“升级版(模式选择+”模拟智能“下棋)
      C语言”三子棋“升级版(模式选择+”模拟智能“下棋)
      |
      6月前
      |
      存储 C语言
      C语言实现三子棋
      C语言实现三子棋
      34 0
      |
      6月前
      |
      C语言
      C语言实现三子棋
      C语言实现三子棋
      33 0
      |
      6月前
      |
      C语言
      C语言:三子棋的实现。
      C语言:三子棋的实现。
      34 0