『牛角书』鸿蒙小游戏

黑白棋游戏

实现过程

一、 绘制棋盘

       首先我们使用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来绘制黑棋和白棋
<div
	class="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是定义的当前下棋的一方
    // 累计清0
    arr.length = 0;
  } else {
    // 累计清0
    arr.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就容易多了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DC2型牛角座规格CSND是一份详细介绍DC2型牛角座产品规格和技术参数的信息文档。在这份规格中,首先会介绍DC2型牛角座的基本信息,如产品型号、外观特征以及适用的环境和工作条件等。随后,会详细介绍该型号牛角座的技术参数,包括电气性能指标、机械性能指标、环境适应性指标等。其中,电气性能指标包括额定电压、额定电流、接触电阻等;机械性能指标包括负载能力、插拔次数、防护等级等;环境适应性指标则包括工作温度范围、防护等级等。规格中还会详细介绍DC2型牛角座的外观尺寸、安装要求以及使用注意事项,确保使用者了解如何正确安装和使用该产品。此外,规格还可能包含有DC2型牛角座的性能测试数据和典型应用案例,方便用户更好地了解和选择该产品。总之,DC2型牛角座规格CSND是一份详尽的参考资料,通过阅读规格,用户可以全面了解该型号牛角座的技术参数和性能要求,为正确使用和选购提供参考。 ### 回答2: DC2型牛角座是一种常用的连接器,常用于电子设备、电脑主板、通讯设备等领域。它有着较为特殊的形状,两侧呈现出牛角状,因此得名为牛角座。DC2型牛角座的规格是指对该连接器的详细规格进行的记录和说明的文档。 DC2型牛角座的规格通常包含以下内容: 1. 外观尺寸:规格中会列出牛角座的准确尺寸,包括长度、宽度、高度等,以便于设计和制造的时候可以准确匹配。 2. 插针情况:规格会详细说明牛角座的插针数量、排列方式和精确位置,以确保与其他连接器或插槽的兼容性。 3. 电气性能:规格会列出牛角座的电气特性,包括额定电压、额定电流和绝缘电阻等参数,以便于用户了解其安全工作范围。 4. 材料和加工:规格会详细说明牛角座所使用的材料种类、表面处理、耐用性等信息,以确保连接器具备良好的机械性能和抗腐蚀性能。 5. 使用环境:规格还会列出牛角座适用的工作环境和工作温度范围,以指导用户正确使用和安装。 通过阅读DC2型牛角座规格,用户可以了解该连接器的详细技术参数,以便于正确选择和使用。同时,规格还对连接器的设计、制造、安装和维护提供了重要的参考依据,确保其稳定可靠的工作。 ### 回答3: DC2型牛角座是一种新型的规格牛角座是指一种座椅形状,形似牛角的弯曲,因此得名。DC2型牛角座规格主要是针对这种特殊座椅的详细说明和参数清单。 DC2型牛角座规格的内容通常包括以下几方面:首先是牛角座的外观描述,包括座椅的整体形状、尺寸大小、材质以及颜色等。其次是座椅的功能说明,包括靠背调节、座垫调节、扶手功能等。此外,规格还会详细列出座椅的荷载能力、可承受的压力、使用寿命等重要参数。同时,规格还会提供安装和使用方法的指导,确保用户能够正确地使用并安装牛角座。 DC2型牛角座规格对于制造商、销售商和用户都非常重要。对于制造商来说,规格对于生产牛角座起到指导作用,确保产品符合质量和安全标准。对于销售商来说,规格可以提供详细的产品参数和使用方法,方便销售人员向客户做出准确的介绍和推荐。对于用户来说,规格可以帮助他们更好地了解和选择适合自己需求的牛角座,并正确地使用和维护座椅。 总结来说,DC2型牛角座规格是一本非常重要的说明,它提供了牛角座的详细描述和功能参数,为制造商、销售商和用户提供了必要的指导和信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值