【木棉花】:手表游戏——黑白翻棋 之 学习笔记(前篇) 原创 精华

木棉花潘颖琳
发布于 2021-9-11 01:44
浏览
3收藏

前言

去年我们木棉花组织发过一篇文章“HarmonyOS手表游戏——黑白翻棋”,本文是我对该文章的一个学习笔记,随着IDE的升级,一些代码也需要作修改。以下是我的学习笔记及部分代码的修改O(∩_∩)O
源代码请移步至→原文章地址

概述

正文内容只展示部分代码,完整代码可以下载附件(附件1是源代码的代码更新)。效果图如下:

【木棉花】:手表游戏——黑白翻棋 之 学习笔记(前篇)-鸿蒙开发者社区 【木棉花】:手表游戏——黑白翻棋 之 学习笔记(前篇)-鸿蒙开发者社区

正文

1.创建一个空白的工程

DevEco Studio下载安装成功后,打开DevEco Studio,点击左上角的File,点击New,再选择New Project,选择Empty Ability(JS),然后点击Next,给项目命名WatchGame_BW,选择设备类型Wearable,最后点击Finish。

【木棉花】:手表游戏——黑白翻棋 之 学习笔记(前篇)-鸿蒙开发者社区

2.界面布局

通过效果图可见,初始布局分三个部分,由上至下分别是文本框、棋盘(画布组件)、按钮;游戏成功的布局有四个部分:文本框、棋盘(画布组件)、游戏成功界面、按钮。(完整代码及解释可以去看原文章)
这里记几个小要点:
1.当前步数显示的是一个动态的值,不是一个固定的值,这里以动态变量currentSteps来显示数据
2.游戏成功的文本框是显示在画布组件之上的(覆盖),而不是在画布组件的下方。该实现可通过添加一个堆叠容器stack,将游戏成功的文本组件放在画布组件之后
3.“游戏成功”的显示在初始时不会显示,所以要设置属性show,对应设一个布尔型变量isShow,并令isShow的初始值为假,游戏成功时其值为真,当为真时就可以显示了

<div class="container">
    <text class="steps">
        当前步数:{{currentSteps}}
    </text>
    <stack class="stack">
        <canvas class="canvas" ref="canvas"></canvas>
            <div class="subcontainer" show="{{isShow}}">
                <text class="gameover">
                    游戏成功
                </text>
            </div>
    </stack>
    <input type="button" value="重新开始" class="bit" onclick="restartGame"/>
</div>

相应的组件大小颜色等属性设置在entry>src>main>js>default>pages.index>index.css文件里通过class设定的名称来去设置,代码如下:

.container {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width:240px;
    height:240px;
}
.steps {
    font-size: 10px;
    text-align:center;
    width:100px;
    height:18px;
    letter-spacing:0px;
    margin-top:5px;
}
.canvas{
    width:160px;
    height:160px;
    background-color: #BBADA0;
}
.bit {
    width: 75px;
    height: 15px;
    background-color: #AD9D8F;
    font-size: 10px;
    margin-top: 5px;
}

.stack{
    width: 160px;
    height: 160px;
    margin-top: 5px;
}

.subcontainer{
    left: 25px;
    top: 47.5px;
    width: 110px;
    height: 65px;
    justify-content: center;
    align-content: center;
    background-color: #E9C2A6;
}

.gameover{
    font-size: 19px;
    color:black;
}

代码更新部分:组件大小的数据全部都在原文章源代码的基础上减半再作微调,即原文章的数据不适用,以上代码是我调整修改后的

3.实现色块的翻转

要先在运动手表上生成一个7*7的棋盘,并且点击棋盘中任一色块,其上下左右四个色块也会跟着一起变色(在边缘的色块则只会改变其中若干个色块的颜色)
原文章的实现方法是给这49个色块分别添加一个按钮,并分别添加点击事件。
布局方面如上所述,色块(按钮)是显示在棋盘(画布)之上,而游戏成功界面是显示在色块(按钮)及画布之上,因此stack里的顺序应该是canvas、button、gameover;且按钮的相关大小间距的数据也要如上“代码更新部分”一样作修改,代码(修改的部分)如下:

.bitgrid1{
    left:2.5px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent

}
.bitgrid2{
    left:25px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent
}
.bitgrid3{
    left:47.5px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent
}
.bitgrid4{
    left:70px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent

}
.bitgrid5{
    left:92.5px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent
}
.bitgrid6{
    left:115px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent
}
.bitgrid7{
    left:137.5px;
    top:2.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent
}
.bitgrid8{
    left:2.5px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid9{
    left:25px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid10{
    left:47.5px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid11{
    left:70px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;

}
.bitgrid12{
    left:92.5px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid13{
    left:115px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid14{
    left:137.5px;
    top:25px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid15{
    left:2.5px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid16{
    left:25px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid17{
    left:47.5px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid18{
    left:70px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;

}
.bitgrid19{
    left:92.5px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid20{
    left:115px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid21{
    left:137.5px;
    top:47.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid22{
    left:2.5px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid23{
    left:25px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid24{
    left:47.5px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid25{
    left:70px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;

}
.bitgrid26{
    left:92.5px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid27{
    left:115px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid28{
    left:137.5px;
    top:70px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid29{
    left:2.5px;
    top: 92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid30{
    left:25px;
    top:92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid31{
    left:47.5px;
    top:92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid32{
    left:70px;
    top:92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;

}
.bitgrid33{
    left:92.5px;
    top:92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid34{
    left:115px;
    top:92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid35{
    left:137.5px;
    top:92.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid36{
    left:2.5px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid37{
    left:25px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid38{
    left:47.5px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid39{
    left:70px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;

}
.bitgrid40{
    left:92.5px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid41{
    left:115px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid42{
    left:137.5px;
    top:115px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid43{
    left:2.5px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid44{
    left:25px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid45{
    left:47.5px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid46{
    left:70px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;

}
.bitgrid47{
    left:92.5px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid48{
    left:115px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}
.bitgrid49{
    left:137.5px;
    top:137.5px;
    width:20px;
    height:20px;
    border-color:transparent;
    background-color:transparent;
}

然后在index.js文件里用一个7*7的数组表示色块,其中0表示白色,1代表黑色,这样我们就能定义一个用0和1表示键,颜色表示值的字典COLORS,并且定义全局常量边长SIDELEN为20,间距MARGIN为2.5,定义一个全局变量的二维数组grids,其中的值全为0

var grids=[[0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0]];

const SIDELEN=20;
const MARGIN=2.5;
const COLORS = {
    "0": "#FFFFFF",
    "1": "#000000"
}

设置色块的点击事件
要点:点击时对应获取该方块的位置(例如该方块时第3行第4个,则坐标为(2,3)),并将该坐标传给函数changeOneGrids,去判断该方块上下左右是否有方块,并调用函数change变换其数组的值——若0则变为1,若1则变为0

change(x,y){
        if(this.isShow==false){
            if(grids[x][y] == 0){
                grids[x][y] = 1;
            }else{
                grids[x][y] = 0;
            }
        }
    },
changeOneGrids(x,y){
        if(x>-1 && y>-1 && x<7 && y<7){
            this.change(x,y);
        }
        if(x+1>-1 && y>-1 && x+1<7 && y<7){
            this.change(x+1,y);
        }
        if(x-1>-1 && y>-1 && x-1<7 && y<7){
            this.change(x-1,y);
        }
        if(x>-1 && y+1>-1 && x<7 && y+1<7){
            this.change(x,y+1);
        }
        if(x>-1 && y-1>-1 && x<7 && y-1<7){
            this.change(x,y-1);
        }
}

最后调用函数drawgrids去“上色”

drawGrids(){
        context=this.$refs.canvas.getContext('2d');
        for (let row = 0 ;row < 7 ;row++){
            for (let column = 0; column < 7;column++){
                let gridStr = grids[row][column].toString();

                context.fillStyle = COLORS[gridStr];
                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;
                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;
                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);
            }
        }
    },

4.实现题目的随机生成

随机生成一个色块被打乱的7x7的棋盘,这里是在原来全白的棋盘上随机生成20个黑色块。
要点:把二维数组的下标放进一个列表中,Math.random()函数是随机[0,1)内的小数,Math.floor(x)为得出小于或等于x的最大整数,每次随机生成一个数后,读取刚才的列表对应的下标,即获得一个在7x7内的随机的坐标,调用函数changeOneGrids(x,y)

initGrids(){
        let array = [];
        for (let row = 0; row < 7; row++) {
            for (let column = 0; column < 7; column++) {
                if (grids[row][column] == 0) {
                    array.push([row, column])
                }
            }
        }
        for (let i = 0; i < 20; i++){
            let randomIndex = Math.floor(Math.random() * array.length);
            let row = array[randomIndex][0];
            let column = array[randomIndex][1];
            this.changeOneGrids(row,column);
        }
    }

5.游戏结束

当该7x7数组的值全为1时游戏成功,此时isShow的值为真,色块的点击事件就不起效(change函数里加个对isShow的真假判断)

gameover(){
        for (let row = 0 ;row < 7 ;row++){
            for (let column = 0; column < 7;column++){
                if (grids[row][column]==1){
                    return false;
                }
            }
        }
        return true;
    }

然后在changeOneGrids函数里调用gameover函数;同时,随着每一次点击,都会调用changeOneGrids函数,所以步数的增加可以直接在每次changeOneGrids函数被调用时累加

 if(this.isShow==false){
            this.currentSteps+=1;;
        }
        if(this.gameover()){
            this.isShow=true;
        }

6.重新开始

最后编写重新按钮对应的函数restartGame(),作用是是二维数组、isShow和当前步数全部置为初始化界面

   restartGame(){
        this.initGrids();
        this.drawGrids();
        this.isShow = false;
        this.currentSteps = 0;
    }

修改的说明

1.画布组件的getContext不支持在onInit和onReady中进行调用,因此我改在drawGrids中调用,然后再在onShow中调用drawGrids
2.随机生成打乱的色块时,会调用changeOneGrids函数,此时会增加步数20

data: {
        currentSteps: -20,
    }​

3.同1,色块的随机生成函数initGrids也放在onShow中调用


结语

以上是我的初步学习笔记啦,我修改过的源代码会上传到附件,更多详细的注解步骤可去看原文章。该学习笔记还有后续哦,后续是对其中一些功能实现采用另一种算法来实现,代码会在该篇的基础上再作修改,并且还会对相关知识注解作一个小分享,敬请期待(●ˇ∀ˇ●)

更多资料请关注我们的项目 : Awesome-Harmony_木棉花

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
WatchGame_BW(1).rar 2.76M 41次下载
已于2021-9-11 01:52:06修改
9
收藏 3
回复
举报
7条回复
按时间正序
/
按时间倒序
xu佳(新号)
xu佳(新号)

居然是沙发位。

1点钟妹子还发帖,熬夜可不好哦

回复
2021-9-11 09:09:27
木棉花潘颖琳
木棉花潘颖琳 回复了 xu佳(新号)
居然是沙发位。 1点钟妹子还发帖,熬夜可不好哦

(被发现了)好的好的,哈哈O(∩_∩)O

回复
2021-9-11 09:21:16
Anzia
Anzia

不错的文章,就是用手表下这个可能有点费劲hhh

回复
2021-9-12 18:24:56
爱吃土豆丝的打工人
爱吃土豆丝的打工人

可能 这个游戏玩起来有点费眼睛 哈哈哈哈

回复
2021-9-13 15:21:50
Whyalone
Whyalone

曾经想用JS实现翻转棋,最终还是放弃了,对翻转棋里面的实现的游戏算法有点好奇

回复
2021-9-13 15:55:33
木棉花潘颖琳
木棉花潘颖琳 回复了 Anzia
不错的文章,就是用手表下这个可能有点费劲hhh

后期来个进阶手机版的,哈哈O(∩_∩)O

回复
2021-9-13 20:16:22
纲哥杂谈
纲哥杂谈

为什么不在鸿蒙服务中心上上架,让我们一起玩玩?

回复
2021-9-15 14:21:27
回复
    相关推荐