HarmonyOS – 基于ArkUI(JS)实现黑白翻棋小游戏
前言
本人经过一段HarmonyOS的学习,运用所学的知识,制作了一个黑白翻棋的游戏,来检验自己的学习成果。本文详细讲述了黑白翻棋的编写思路,内含详细解释,有兴趣的小伙伴可以自己动手来制作一个属于自己的黑白翻棋小游戏。
效果展示
实现功能
实现黑白翻棋的功能,屏幕上存在7*7个方格,每个方格随机刷新成黑色或者白色,点击一个方格,其自身和上下左右四个方格都会变成相反的颜色,棋盘上方的当前步数则会相应依次增加。当所有的方格都变成白色时,游戏胜利。
实现步骤
1、hml部分
<div class="container" >
<text class="steps">
当前步数:{{currentSteps}}
</text>
<canvas class="canvas" ref="canvas" ></canvas>
<input type="button" value="重新开始" class="bit" />
</div>
2、css部分
.container {
flex-direction: column;
justify-content: center;
align-items: center;
width:450px;
height:450px;
}
.steps {
font-size: 18px;
text-align:center;
width:300px;
height:20px;
letter-spacing:0px;
margin-top:10px;
}
.canvas{
width:320px;
height:320px;
background-color: #BBADA0;
}
.bit{
width:150px;
height:30px;
background-color:#AD9D8F;
font-size:24px;
margin-top:10px;
}
3、js部分
在文件开头定义一个全局变量context,在onShow把2d绘画工具绑定给context,创建currentSteps,表示步数,初始值为0。设置定时器是为了保证context永远可以赋值得到,如果没有问题的话,可以去掉。
var context;
export default {
data: {
currentSteps: 0,
}
onShow() {
setTimeout(() => {
context = this.$refs.canvas.getContext('2d');
this.drawGrids();
}, 200)
},
}
用0表示白色,1代表黑色,这样我们就能定义一个用0和1表示键,颜色表示值的字典COLORS,并且定义全局常量边长SIDELEN为40,间距MARGIN为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=40;
const MARGIN=5;
const COLORS = {
"0": "#FFFFFF",
"1": "#000000"
}
创建一个drawGrids()函数,先将grids的值利用toString()函数全部转化为字符串,fillStyle表示画图的背景颜色,引用字典即可,fillRect表示画矩形的大小。
onShow(){
this.drawGrids();
},
drawGrids(){
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);
}
}
}
初始框架搭建完成,接下来实现随机生成色块。
为了使点击任意一个色块时能得到其对应的二维数组的下标,我们在每个小方格上添加一个按钮和一个点击事件,依次给这些按钮设定一个类名和点击按钮所调用的函数然后为了使按钮显示在棋盘格子的上方,需要添加一个栈stack(stack为堆叠容器,能让input按钮显示在画布的上方)类名设定为stack,使画布先进栈,按钮后进栈。
<div class="container" >
<text class="steps">
当前步数:{{currentSteps}}
</text>
<stack class="stack">
<canvas class="canvas" ref="canvas" ></canvas>
<div style="flex-direction: row; flex-wrap: wrap;">
<input for="{{dataGrids}}" type="button" class="grid-item" onclick="getgrid({{$idx}})"/>
</div>
</stack>
<input type="button" value="重新开始" class="bit" />
</div>
给每个小方格设置坐标,让每个小方格悬浮在画布上。
设第x个小方格的坐标是(y,z)y代表二维数组的第一个数,z代表二维数组的第二个数,比如第17个方格在数组中用[2,1]来表示,我们需要依照这个规则,编写49个这样的样式。
创造一个函数change,使当前传入的横竖坐标的方块的颜色改变。
change(x,y){
if(this.isShow==false){
if(grids[x][y] == 0){
grids[x][y] = 1;
}else{
grids[x][y] = 0;
}
}
}
创造一个函数changeOneGrids用来改变当前点击方格的上下左右的颜色(调用了change函数),当isShow为flase时点击事件才能让步数增加,达到了游戏结束,isShow为true时,点击不再增加步数的效果。
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);
}
this.drawGrids();
if(this.isShow==false){
this.currentSteps+=1;;
}
}
给每个按钮都写上相应的函数,把相应的坐标传进去。
getgrid(index) {
console.log('getgrid:' + index)
this.changeOneGrids(parseInt(index / 7), index % 7);
}
最后我们需要实现随机生成棋盘的功能,let一个数组array,把当前grids二维数组的下标放入array,然后用Math.random()函数和Math.floor(x)函数生成一个随机数,再调用changeOneGrids()函数把其本身和上下左右的方块都取相反颜色。
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);
}
}
实现游戏成功页面
首先我们得在栈stack组件中增加一个游戏成功的容器div类名为subcontainer,以isShow控制该容器是否进栈,增加文本组件text,类名gameover,并赋值“游戏成功”。
<div class="subcontainer" show="{{isShow}}">
<text class="gameover">
游戏成功
</text>
</div>
给重新开始按钮增加一个点击事件click,调用函数restartGame。
<input type="button" value="重新开始" class="bit" onclick="restartGame"/>
首先给isShow赋值false,将开头的全局变量grids赋值删除,增加一个函数给grids赋值,并调用函数initGrids()。
var grids;
data: {
currentSteps: 0,
isShow: false
}
onInit() {
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]];
this.initGrids();
for (let i = 0;i < 49; i++) {
this.dataGrids.push(i)
}
}
增加一个函数gameover(),当棋盘所有色块颜色为白色时返回true,否则返回false,即当二维数组的值全为0时返回true,否则返回false。
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(x,y)中添加当函数gameover()为true时,将isShow赋值为true,使游戏成功界面显示在最上方,并使所有二维数组grids值赋值为6,字典中增加一个6对应白色,这样就能达到当游戏成功时再点击色块并不会发生任何变化,当函数gameover()为false时,步数增加1。
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);
}
this.drawGrids();
if(this.isShow==false){
this.currentSteps+=1;;
}
if(this.gameover()){
this.isShow=true;
}
}
最后一步,编写重新开始按钮对应的函数restartGame(),点击重新开始按钮时,二维数组当前步数,isShow全部初始化。
restartGame(){
this.onInit();
this.drawGrids();
this.isShow = false;
this.currentSteps = 0;
}
总结
以上就是我本次文章的全部内容了,这也是我学习HarmonyOS之后所做的第一个小游戏,借鉴了一些前辈的经验,后续我还会不断改进,推出更多的系列小游戏。欢迎大家一起研究讨论,希望本次内容能够对大家有所帮助。