【c语言】随意界面大小的n子棋

n子棋(三子棋为例)

  1.         实现效果
  2.         需求分析
  3.         核心讲解
  4.         代码实现

实现效果

4*4界面的三子棋效果


4*2界面三子棋效果


10*10界面五子棋效果


 需求分析

        从以上的效果看,我们需要一个菜单来选择游戏玩法与退出,一个下棋的棋盘和输赢的判断。

        菜单的界面我们可以使用输出打印而菜单内容的选择可以使用选择结构来实现

        棋盘的界面我们可以把它看成一个二维数组而下棋的动作我们可以看成给二维数组赋值的过程。

 核心讲解

        接下来是重点,游戏结果的判断这个可以说是整个游戏的核心接下来我会以3*3的二维数组来举例讲解。

        我现在在玩一个3*3界面的三子棋,假设我在1.1的坐标落了一子我就以它为中心分别往它的8个方向(上 —上右 — 右 — 下右 — 下 — 下左 — 左 — 左上)找它相同的棋子并记录每个方向相同棋子的数量。此时我们来看下面这张图。

        不难发现箭头1(上)加箭头5(下)可以连成一条 | 线,箭头2(上右)加箭头6(下左)可以连成一条 / 线以此类推,我们可以利用这个规律来计算它们的和是否等于规定的棋子数(如现在的三子棋)来判断输赢,但此时有一个问题我们看下图。

        可以看到当我们把棋子落在0.0时有些箭头指向超出了我们规定的页面大小这样就出现bug了如何解决呢?,很简单我们看下图。

         我们给决定大小界面的二维数组的列和行分别加2来给游戏区域加上边框这样就解决箭头超出范围的问题了。但此时我们又出现了一个情况看下图。

         当我们的棋子没落在游戏区域的中心时我们的箭头1 2 3虽然有相同的棋子也记录了但他们并不能连成一条线所以不能相加,但我们可以看到图上面已经有一条 \ 线可以连起来了但我们当前的棋子的位置认不出啊这不是又有问题了吗,解决方案也很简单看下图。

        我们只需要让程序循坏起来在找到周围的棋子后在继续往相同的方向找就行了直到没有相同棋子了在停下。

        比如我们看箭头1 在我们当前棋子坐标的右边有一个相同的棋子我就让我当前的坐标 (1.1)的行加一也就是arr[n][n+1]此时我们的坐标就来到了1.2(注:此时的1.2坐标只继承了向右找棋子与纪录棋子数的功能)此时坐标1.2在向右找就没有相同的棋子了我们就结束,相同的道理我们看箭头2找完后返回的纪录的棋子数相加不就等于规定的棋子数(此时是三子棋)了吗这样不就可以判断胜利了吗,明白这些后我们就可以着手实现了。

代码实现

        为了代码简洁好看我们分模块写代码,先创建3个文件  zhu_ti.c   han_shu.c  han_shu.h

zhu_ti.c用来写游戏主体逻辑,han_shu.h用来函数声明与包含库函数(这里使用的编译器是vs2109)。

         我们先写游戏主体逻辑在拆功能区块单独讲

 我们先讲主函数部分

第93行是用来取时间刻的为后面的电脑玩家的随机下棋做准备,do while循环用来无条件打印一次菜单,后面switch用来做菜单功能的实现,输入1就开始和电脑pk,输入2就看时双人pk,输入0则退出,输入的数以上都不满足就重新输入,最后的while的判断用i是因为当输入0退出游戏的时候i就等于0了条件为假可以顺便do while退出循环,这里就不讲双人pk的实现了因为逻辑与电脑pk是非常相似的就不赘述了,我们输入1选择电脑pk我们进入了you_xi()函数,这里要配合 han_shu.h 看

这里注意 i 求得的数是用来给while判断平局的,i 这里要得到不包括边框的游戏界面大小(可输入的格子数)当 i-- 到0后就证明没有可输入的格子数了就平局了。

在第22行的 if 判断里为什么有arr_xia_qi()函数,在核心讲解那里可以发现我这个判断思路是必须要集成在下棋的,不然没有当前棋子的坐标是无法动态判断的,函数后面为什么有 == ZI 呢,也在核心讲解那里讲过当记录的棋子相加的总数等于规定的棋子数时就证明赢了,然后满足条件后就输出结果并跳出循环。

在36行那里的 else if 的else可以删可以不删我留着是要保险,在玩家下棋那里把棋盘下满后如果不跳过电脑下棋的话会死循环,至于为什么就在后面讲了。

接下来我们来看这些函数的实现了。我们先看打印函数。

这里唯一要注意的是277行的 if (j < hang - 1),这里必须要 -1 不然会出现打印的问题,问题比如下图,还有arr数组的初始化函数没什么可讲的就把整个数组包括边框一起初始化成空格就行了 

 到玩家的输入和判断了

 这里只用注意106行的条件就行了,这里主要是防止赋值到边框这里 x 和 y 不可以是 0 也不可以超过lie和hang -2 的值这里拿上面的图举例,当我设定的行和列是5是可以得到 0.0 到 4.4 的棋盘但我们主要的游戏区域是从 1.1 到 3.3 的其他的都是边框,这时候我们只需要拿行和列的数减去边框的数就可以得出我们的主要游戏区域的坐标了,如我需要一个3*3的游戏界面(主游戏区域)那我设置包边框的整页面大小时就要(3+2)*(3+2)所以我们只需要 -2 就可以得出主要游戏区域的坐标了。

 下面是核心的判断输赢的函数

 

这里只需要知道一条线的组成需要哪两个方向的棋子数相加就行了,这里的y和x的加减变化可以照着下面的图感受一下,这里的递归都是一个方向走到底的,最后返回记录的子数就行了,至于 if 判断里的ZI为什么要 -1 是因为递归返回的数是不包括初始位置的子数的,比如我规定的子数是3那我递归返回的数最多只有2除非加上初始位置的子数则1 + 2才是规定的子数,还有判断里的 >= 要注意如果是 == 是会有bug的在界面大的时候是会出现这样的情况的三子棋为例,如这种情况

0100这时候把1换成0连成线后会大于ZI的所以要注意。

 到电脑的下子函数了

 逻辑和玩家下子一样区别就是坐标是随机的,到这里就完了后面游玩时只需要注意规定页面大小时要在你想要的页面大小的基础上+2就行了。

        一不小心就写了2k字了,第2次写文章也不知道质量咋样qwq,本来想搞个类似文章锚点的但......不会啊qwq如果有类似的文章还请dd我谢谢ヾ(◍°∇°◍)ノ゙

 

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值