作者:82王先生
前言
拼数字小游戏其实是借鉴了很多前辈写的案例,然后自己去动手写了一下。主要是学习使用OpenHarmony开发相关知识,包括一些API需要自己去踩踩坑才行,小游戏其中还有很多不足之处,后面有时间了会尝试做成闯关的类型,包括统计分数做一个排行榜等其他功能。
效果展示
简单演示一下,因为是4*4的,想拼成可能要花费一些时间。

排列成功后的效果是这样的!

实现原理
- 创建一个4*4的表格方阵,将一个空白方格和1到15的数字随意打乱在方阵中,使其随机分布。表格上方放一个定时器,用来记录游戏进行的时间,单位为秒,表格下方放一个“开始游戏”的按钮,点击后开始游戏。
- 单击控制鼠标,在表格方阵上向上、下、左、右随意一个方向进行移动,计时器开始计时,空白方格周围对应位置的方格会随着鼠标移动的方向,向对应的方向移动一格。
- 在进行多次的移动后,所有的数字按照顺序排列完成后,会弹出“你真滴棒!”的提示游戏完成的界面。
使用到的官方API
getContext
getContext(type: ‘2d’, options: ContextAttrOptions): CanvasRendering2dContext
获取canvas绘图上下文 – 不支持在onInit和onReady中进行调用
-
参数
参数名 |
参数类型 |
必填 |
描述 |
type |
string |
是 |
设置为’2d’,返回值为2D绘制对象,该对象可用于在画布组件上绘制矩形、文本、图片等。 |
options |
ContextAttrOptions |
否 |
当前仅支持配置是否开启抗锯齿功能,默认为关闭。 |
表1 ContextAttrOptions
参数名 |
类型 |
说明 |
antialias |
boolean |
是否开启抗锯齿功能,默认为false。 |
-
返回值
fillRect
fillRect(x: number, y: number, width:number, height: number): void
填充一个矩形。
-
参数
参数 |
类型 |
描述 |
x |
number |
指定矩形左上角点的x坐标。 |
y |
number |
指定矩形左上角点的y坐标。 |
width |
number |
指定矩形的宽度。 |
height |
number |
指定矩形的高度。 |
fillText
fillText(text: string, x: number, y: number): void
绘制填充类文本。
-
参数
参数 |
类型 |
描述 |
text |
string |
需要绘制的文本内容。 |
x |
number |
需要绘制的文本的左下角x坐标。 |
y |
number |
需要绘制的文本的左下角y坐标。 |
代码实现
1. html代码
2. css代码
3. js代码
var grids;
var context;
var timer;
const sideLen = 70;
const margin = 5;
export default {
data: {
currentTime: '0.0',
isShow: false,
},
onInit() {
grids = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]];
},
isInitGrids() {
let array = ["left", "up", "right", "down"];
for (let i = 0; i < 100; i++) {
let randomIndex = Math.floor(Math.random() * 4);
let direction = array[randomIndex];
this.changeGrids(direction);
}
},
onReady() {
this.isInitGrids();
},
onShow() {
context = this.$refs.canvas.getContext('2d');
this.drawGrids();
},
drawGrids() {
for (let row = 0; row < 4; row++) {
for (let column = 0; column < 4; column++) {
let gridStr = grids[row][column].toString();
context.fillStyle = "#87CEEB";
let leftTopX = column * (margin + sideLen) + margin;
let leftTopY = row * (margin + sideLen) + margin;
context.fillRect(leftTopX, leftTopY, sideLen, sideLen);
context.textBaseline = 'top'
context.font = "30px";
if (gridStr != "0") {
context.fillStyle = "#000000";
let offsetX = (4 - gridStr.length) * (sideLen / 8);
let offsetY = (sideLen - 30) / 2;
context.fillText(gridStr, leftTopX + offsetX, leftTopY + offsetY);
}
}
}
},
runIt() {
this.currentTime = (Math.floor(parseFloat(this.currentTime) * 10 + 1) / 10).toString();
if (parseFloat(this.currentTime) % 1 == 0) {
this.currentTime = this.currentTime + ".0";
}
},
onSwipeGrids(e) {
this.changeGrids(e.direction);
this.drawGrids();
if (this.gameOver()) {
clearInterval(timer);
this.isShow = true;
}
},
gameOver() {
let oriGrids = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]];
for (let row = 0; row < 4; row++) {
for (let column = 0; column < 4; column++) {
if (grids[row][column] != oriGrids[row][column]) {
return false;
}
}
}
return true;
},
changeGrids(direction) {
let x;
let y;
for (let row = 0; row < 4; row++) {
for (let column = 0; column < 4; column++) {
if (grids[row][column] == 0) {
x = row;
y = column;
break;
}
}
}
let temp;
if (this.isShow == false) {
if (direction == 'up' && (x + 1) < 4) {
temp = grids[x + 1][y];
grids[x + 1][y] = grids[x][y];
grids[x][y] = temp;
} else if (direction == 'down' && (x - 1) > -1) {
temp = grids[x - 1][y];
grids[x - 1][y] = grids[x][y];
grids[x][y] = temp;
} else if (direction == 'left' && (y + 1) < 4) {
temp = grids[x][y + 1];
grids[x][y + 1] = grids[x][y];
grids[x][y] = temp;
} else if (direction == 'right' && (y - 1) > -1) {
temp = grids[x][y - 1];
grids[x][y - 1] = grids[x][y];
grids[x][y] = temp;
}
}
},
startGame() {
timer = setInterval(this.runIt, 100);
this.isInitGrids();
this.currentTime = "0.0";
this.isShow = false;
this.onShow();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
总结
H5中使用的样式或者方法有些是在OpenHarmony开发过程中无法使用的,要进行FA开发需要多读OpenHarmony的文档,后续的开发中也需要多踩坑,多总结,多练习!有不好的地方欢迎指正!每天进步一点点。
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
哦豁,新的小游戏,666
只留一个空位有点像是基础版的华容道了,4*4的大小正好,5*5感觉确实太折磨人了。
真强呀
mc王先生----一个被前端事业耽搁的喊麦音乐高手