『牛角书』鸿蒙小游戏

news/2024/11/8 6:16:49/

黑白棋游戏

实现过程

一、 绘制棋盘

       首先我们使用css绘制棋盘,绘制一个14*14的正方形格子棋盘,但是需要注意,因为我们落子是落在四个格子之间的交界点上的,而不是落在格子里的,所以怎办呢?我们可以先绘制一个15*15的辅助正方形格子,然后再在其中间绘制一个14*14,这样落棋在15*15的格子里,而在14*14的格子里就可以看到落棋是在交界点里。

  1. 首先绘制一个15*15的正方形格子。

 2. 然后再在其中间绘制一个14*14的正方形格子,这样的话,棋子就绘制在15*15的格子里,而在   14*14的棋盘里就显示是在格子交界点上了。

  1. 最后把15*15的边距去掉,就得到一个正常的14*14的棋盘了,怎样是不是很漂亮。

      其实不需要这么麻烦的,直接绘制一个14*14的格子就可以了,可以使用css的::before和::after选择器来绘制格子线条。一开始也想用这么这样处理的,但是发现好像还没集成这两个选择器进来

二、实现落棋功能

首先在data声明一个arr为15*15的空数组,也就是长度为225的空数组。数组值只能更新为:

  • 1:存放黑棋
  • -1:存放白棋
  1. 在标签里定义两个class来绘制黑棋和白棋
<divclass="li{{item == '1' ? 'black' : ''}} {{item == '-1' ? 'white': ''}}"for="{{(index,item) in arr}}"tid="item"οnclick="play(index)"
></div>
  1. 在点击play落棋时,传入当前落棋的位置
play(e){// 针对数组内的数据修改,请使用splice方法生效数据绑定变更this.arr.splice(e,1,'1'); 
}

上面代码传入1,则点击显示黑棋

到这里还不行,需要做交换走棋,黑棋走完,到白棋走,并且走过的位置不允许再走棋。

在data定义holder为当前持棋者:

  • 1:存放黑棋,默认持黑棋先走
  • -1:存放白棋
play(e){if(this.arr[e] == '1' || this.arr[e] == '-1'){console.log('该处已经有棋了');return false;}// 针对数组内的数据修改,请使用splice方法生效数据绑定变更this.arr.splice(e,1,this.holder);// 交换走棋this.holder = this.holder == '1' ? '-1' : '1';},

三、计算赢棋方式

      我们都知道要赢棋就得同色5颗棋子连成一条线,包括横向,竖向,斜向,斜向左边和斜向右边四种方式。那么我们就要把这几种方式拆分出来一一计算统计。

      通过上面的序号,我们不难发现几个规律。

#### 1. 横向赢棋方式

      横向赢棋方式是五个棋子每两两相差一个数值,所以每相邻棋子就是一个+1和-1的过程。

2. 竖向赢棋方式

       竖向赢棋方式上下连成一排,我们知道一行只有15个格子,每个棋子都相差15数值,所以每相邻棋子之间都是+15和-15的过程。

3. 左斜向赢棋

      左斜方向通过观察不难发现每两两棋子之间相差+14和-14。

4. 右斜向赢棋

      右边斜方向也可以看出每相邻棋子之间相差+16和16。

四、实现赢棋计算

      通过上面一比较,是不是瞬间就觉得其实没那么难了呢,我们只要计算好每次落棋的序号和之前落棋的序号进行一对比,只要满足条件的五个棋子,就赢棋了。

      实现思路: 以黑棋、横向为例子,通过递归算法,通过计算+1 || -1是否都有黑棋的记录,有则记录累计一次,每次计算完成,则去判断当前累计次数是否等于5,如果不是,则还没有赢,如果为5次,则说明赢棋了。

下面是实现代码:

//id: 当前棋子的序号 d: 计算方式,比如横向是 +1 和 -1,arr是累计下来的序号结果。 
compute(id,d,arr){id = parseInt(id);if(this.arr[id + d] && this.arr[id + d] == this.holder){arr.push(id);this.compute(id + d, d, arr);} else{arr.push(id);}},

下面代码是判断是否赢棋的方法

// 判断是否赢了
getResult(arr){if(arr.length > 5){console.log(this.holder + '赢棋'); //this.holder是定义的当前下棋的一方// 累计清0arr.length = 0;} else {// 累计清0arr.length = 0;}
},

    我们在每次点击下棋的时候,都调用一次统计累计次数方法和计算赢棋的方法。

// 横向赢方法
this.compute(e, 1, this.arr1); //arr1是定义好的累计次数多数组
this.compute(e, -1, this.arr1);
this.getResult(this.arr1);

    结合上面计算方式,我们其他的赢棋方式一样可以这样统计来计算。

// 点击下棋方法
play(e){if(this.isEnd) return;if(this.arr[e] == '1' || this.arr[e] == '-1'){console.log('该处已经有棋了');return false;}// 针对数组内的数据修改,请使用splice方法生效数据绑定变更this.arr.splice(e,1,this.holder);// 横向赢方法this.compute(e, 1, this.arr1);this.compute(e, -1, this.arr1);this.getResult(this.arr1);// 竖向赢方法this.compute(e, 15, this.arr1);this.compute(e, -15, this.arr1);this.getResult(this.arr1);//右斜赢方法this.compute(e, 14, this.arr1);this.compute(e, -14, this.arr1);this.getResult(this.arr1);// 左斜赢方法this.compute(e, 16, this.arr1);this.compute(e, -16, this.arr1);this.getResult(this.arr1);//    交换走棋this.holder = this.holder == '1' ? '-1' : '1';

   下面看看效果。

      到这里结束了吗?不,还没结束,这里还存在一些bug问题,比如说我们横向的时候是通过计算两棋子之间是否存在+1和-1的关系,但是如果两个棋子是14,15呢?这时候是已经换行了,显然是不能成立的,但是计算结果这种方式是成立的。所以我们要解决掉这个问题,包括斜向。

五、优化计算方法

      其实无非两种结果,一种就是换行了,+1的时候换行到第一列数值了,-1的时候换行到最后一列数值了,那么我们把第一列和最后一列单独拉出来,进行比较,

  • 是否在+1、-14,+16的数值是否在第一列存在,如果存在就不进行累计。
  • 是否在-1、+14、-16的数值是否在最后一列存在,如果存在就不进行累计。
  • 这里为什么没有+15和-15呢,因为竖向不存在这个问题。

     下面我们来用代码实现。

// id: 为原id+d, d: 为计算方式。
scree(id,d){if((d == 1 && this.colOne.indexOf(id) > -1)|| (d == -1 && this.colEnd.indexOf(id) > -1)|| (d == 14 && this.colEnd.indexOf(id) > -1)|| (d == -14 && this.colOne.indexOf(id) > -1)|| (d == 16 && this.colOne.indexOf(id) > -1)|| (d == -16 && this.colEnd.indexOf(id) > -1)){return false;}return true;
},  

    最后,我们在计算判断的时候加上这个判断条件即可 this.scree(id+d,d)

compute(id,d,arr){id = parseInt(id);if(this.arr[id + d] && this.arr[id + d] == this.holder && this.scree(id+d,d)){arr.push(id);this.compute(id + d, d, arr);} else{arr.push(id);}
},

    最后,我们来看看最终的效果

总结

      该方法是使用div+css+js实现的双人对战游戏,在使用css的时候发现相比web端的属性,还是少了很多,比如绘制棋盘的时候想用::before和::after选择器来绘制,但是发现当前还没有这个属性,还有想绘制一个好看有弧度高光的棋子,想使用内阴影实现,但是目前也还并不支持内阴影。不过相信后续会更新,这样web前端开发上手HarmonyOS JSAPI就容易多了。


http://www.ppmy.cn/news/721841.html

相关文章

第三课 K线图(下)——K线定式及演变

上一课我们谈到看到K线图的基本态度,即明确K线图是市场交易的历史记录,分析时即要有宽阔的视野,又不能忽略细节,正如我们在上一节课的实例分析中看到的,这种宽阔又细致的分析需要耗费很多精力,于是,我们必须总结K线图中经常出现的一些组合,形成定式并分类理解,以便提高…

2020考研数学一大纲之完全解析(二)

一元函数微分学 本节大纲内容考试要求考试内容导数和微分的概念导数的几何意义与物理意义函数的可导性与连续性的关系平面曲线的切线和法线导数和微分的四则运算基本初等函数的导数复合函数、反函数、隐函数以及参数方程所确定的函数的微分法高阶导数一阶微分形式的不变性微分中…

中国大学生数学竞赛(非数学专业类)竞赛大纲

中国大学生数学竞赛&#xff08;非数学专业类&#xff09;竞赛大纲 中国大学生数学竞赛&#xff08;非数学专业类&#xff09;竞赛大纲一、函数、极限、连续二、一元函数微分学三、一元函数积分学四、常微分方程五、向量代数和空间解析几何六、多元函数微分学七、多元函数积分学…

大学图书馆空间再造与服务创新研究

摘要:&#xff3b;目的/意义&#xff3d;论述沈阳师范大学图书馆空间再造的理念与实践&#xff0c;为当前大学图书馆以空间再造突破服务瓶颈、实现成功转型提供借鉴与参考。&#xff3b;方法/过程&#xff3d;以图书馆空间再造及开展的空间服务个案为例&#xff0c;归纳总结出大…

五子棋之极大极小

总述:五子棋问题可以化为一个博弈问题。从开始落子到最后赢,输或和的每一步落子构成了一个解,而解空间就是一个树。解就是这个树中的一条路径,只不过这个解空间的是由电脑和人的共同选择构成的。我们可以使用极大极小值搜索来解决这个博弈问题,假设每一步人和电脑都落子在…

八卦掌桩功-定式八桩及相关资料

桩功俗称站桩&#xff0c;称其为桩&#xff0c;是因为习练者要象木桩一样静止不动&#xff0c;久练之后&#xff0c;就可以脚底生根&#xff0c;象木桩一样扎实稳固。这是一种特殊的内功修炼法&#xff0c;站桩既能养生又能练出功夫&#xff0c;既可修身又可修心&#xff0c;既…

交互设计7大定律

在交互设计领域有很多经过时间检验过的定律及法则来作为设计的指导原理&#xff0c;它能够帮助产品设计者对界面上的各种视觉元素进行合理评估&#xff0c;从而发现一些使用过程中的可用性问题&#xff0c;还可以根据这些法则从界面的维度来改善操作效率和使用满意度。 我们在产…

怎么看曲线有没有斜渐近线_怎样判断一个曲线有无斜渐近线?

2005-10-31 什么是洛必达法则,用它求极限就是求导吗? 我们知道,在求极限时,常会遇到两个无穷小之比的极限或两个无穷大之比的极限。这些极限有的存在,有的不存在。通常称这类极限为"未定式"。利用第一章的方法求未定式的极限通常是困难的,本节介绍一种简单而有效的方…