回复
『江鸟中原』---- 鸿蒙-----简单游戏2048 原创
longlongzs
发布于 2023-12-8 11:03
浏览
0收藏
1.摘要
鸿蒙结课作业:完成一个2048小游戏,在一个4×4的空间中,可以实现上下左右移动,相同块消除形成倍数块,如果没有可移动块,则游戏结束。否则游戏可一直进行。
2.环境搭建
软件要求:DevEco studio 3.1.0
HarmonyOS SDK版本:API version 8
硬件要求:设备类型:华为手机或运行在DevEco Studio上的华为手机设备模拟器。
3.程序设计(代码演示附带运行截图)
(1)游戏框架
在4×4的表格中随机生成2或者4的数块,通过移动数块来完成游戏运行,如果数块沾满16个格游戏则结束。
页面设计 :
@Entry
@Component
struct zs {
@State flatCellArr: number[] = [0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0]
private gameController: GameController = new
GameController()
private colorUtil: ColorUtil = new ColorUtil()
@State @Watch("onGameOver") isGameOver: boolean = false
gameOverDialogController: CustomDialogController = new
CustomDialogController({
builder: GameOverView({
startGame: this.startGame.bind(this)
}),
autoCancel: false
})
@State screenSize: {
x: number,
y: number
} = { x: px2vp(1080), y: px2vp(0) }
onGameOver() {
if (this.isGameOver === true) {
this.gameOverDialogController.open()
}
}
startGame() {
this.flatCellArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
this.gameController.init(this.flatCellArr)
this.flatCellArr = this.gameController.getFlatCellArr()
this.isGameOver = false
}
moveUp() {
this.gameController.moveUp()
this.updateCells()
}
moveDown() {
this.gameController.moveDown()
this.updateCells()
}
moveLeft() {
this.gameController.moveLeft()
this.updateCells()
}
moveRight() {
this.gameController.moveRight()
this.updateCells()
}
updateCells() {
this.flatCellArr = this.gameController.getFlatCellArr()
this.isGameOver = this.gameController.isGameOver
}
aboutToAppear() {
display.getDefaultDisplay((err, data) => {
if (data.height > data.width) {
this.screenSize = { x: px2vp(data.width), y:
px2vp(data.height) }
} else {
this.screenSize = { x: px2vp(750), y:
px2vp(data.width) }
}
})
this.startGame()
}
build() {
Column() {
Column() {
Grid() {
LazyForEach(new GameDataSource(this.flatCellArr), (
item) => {
GridItem() {
Text(`${item === 0 ? '' : item}`)
.fontSize('85px')
.fontColor(item <= 4 ? '#000' : '#fcf8f5')
.fontWeight(FontWeight.Bolder)
.backgroundColor('#f0fff0')
.width('100%')
.height('100%')
.textAlign(TextAlign.Center)
.borderRadius(10)
.backgroundColor(this.colorUtil.getCellBackgroundColor(item))
}
})
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width(this.screenSize.x)
.padding(10)
.backgroundColor('rgba(80,69,46,0.26)')
.height(this.screenSize.x)
.borderRadius(10)
.gesture(GestureGroup(GestureMode.Exclusive,
PanGesture({ direction: PanDirection.Left }).onActionEnd(() => {
this.moveLeft()
}),
PanGesture({ direction: PanDirection.Right }).onActionEnd(() => {
this.moveRight()
}),
PanGesture({ direction: PanDirection.Up }).onActionEnd(() => {
this.moveUp()
}),
PanGesture({ direction: PanDirection.Down }).onActionEnd(() => {
this.moveDown()
})
))
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Start)
.width('100%')
.height('100%')
}
}
@CustomDialog
struct GameOverView {
controller: CustomDialogController
startGame: () => void
build() {
Column() {
Text('游戏结束')
.fontSize(30)
.fontWeight(FontWeight.Medium)
.margin({ top: 10 })
Row() {
Button('重新开始', { type: ButtonType.Normal })
.borderRadius(5)
.margin({ top: 10 })
.width(200)
.onClick(() => {
this.startGame()
this.controller.close()
})
}.justifyContent(FlexAlign.SpaceAround)
.margin({ top: 10, bottom: 10 })
}
.backgroundColor('#f0f0f0')
.borderRadius(25)
}
}
(2)游戏控制
数块控制:export class GameController {
cellArr: number[][] = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
isGameOver: boolean = false
init(cellArr: number[]) {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
this.cellArr[i][j] = cellArr[i * 4+j]
}
}
this.isGameOver = false
this.fillOneEmptyCell()
this.fillOneEmptyCell()
}
fillOneEmptyCell() {
let cellIndex = this.findOneEmptyCell()
if (cellIndex != -1) {
let row = Math.floor(cellIndex / 4)
let col = cellIndex % 4
this.cellArr[row][col] = this.getRandomValue()
}
}
findOneEmptyCell() {
let cells = []
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (!this.cellArr[i][j]) {
cells.push(i * 4 + j)
}
}
}
if (cells.length) {
return cells[this.randomVal(cells.length)]
} else {
return -1
}
}
getRandomValue() {
let rand = this.randomVal(10);
var value = 2;
if (rand >= 8) {
value = 4;
}
return value;
}
randomVal(max: number) {
return Math.floor(Math.random() * max)
}
canMove() {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
let cell = this.cellArr[i][j]
if (cell) {
if (j < 3 && this.cellArr[i][j] == this.cellArr[i][j + 1]) {
return true
}
if (i < 3 && this.cellArr[i][j] == this.cellArr[i + 1][j]) {
return true
}
} else {
return true
}
}
}
return false
}
horizontalMoveCells(toLeft: boolean) {
for (let i = 0; i < 4; i++) {
let newArr = Array(4).fill(0)
for (let j = 0; j < 4; j++) {
newArr[j] = this.cellArr[i][j]
}
let resultArr = this.removeZerosAndAdd(newArr, toLeft)
for (let j = 0; j < 4; j++) {
this.cellArr[i][j] = resultArr[j]
}
}
}
verticalMoveCells(toUp: boolean) {
for (let i = 0; i < 4; i++) {
let newArr = Array(4).fill(0)
for (let j = 0; j < 4; j++) {
newArr[j] = this.cellArr[j][i]
}
let resultArr = this.removeZerosAndAdd(newArr, toUp)
for (let j = 0; j < 4; j++) {
this.cellArr[j][i] = resultArr[j]
}
}
}
removeZerosAndAdd(arr: number[], toHead: boolean) {
let newArr = Array(4).fill(0)
let arrWithoutZero = arr.filter((x) => x !== 0)
if (arrWithoutZero.length == 0) {
return newArr
}
if (toHead) {
for (let i = 0; i < arrWithoutZero.length; i++) {
newArr[i] = arrWithoutZero[i]
}
for (let i = 0; i < newArr.length - 1; i++) {
if (newArr[3 - i] === newArr[2 - i] && newArr[3 - i] !== 0) {
newArr[3 - i] = 0
newArr[2 - i] *= 2
}
}
} else {
for (let i = 0; i < arrWithoutZero.length; i++) {
newArr[newArr.length - i - 1] =
arrWithoutZero[arrWithoutZero.length - i - 1]
}
for (let i = 0; i < newArr.length - 1; i++) {
if (newArr[i] === newArr[i + 1] && newArr[i] !== 0) {
newArr[i] = 0
newArr[i + 1] *= 2
}
}
}
return newArr
}
moveUp() {
this.verticalMoveCells(true)
this.checkGameOverOrContinue()
}
moveDown() {
this.verticalMoveCells(false)
this.checkGameOverOrContinue()
}
moveLeft() {
this.horizontalMoveCells(true)
this.checkGameOverOrContinue()
}
moveRight() {
this.horizontalMoveCells(false)
this.checkGameOverOrContinue()
}
checkGameOverOrContinue() {
if (this.canMove()) {
this.fillOneEmptyCell()
} else {
this.isGameOver = true
}
}
getFlatCellArr() {
var flatCellArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
flatCellArr[i * 4+j] = this.cellArr[i][j]
}
}
return flatCellArr
}
}
(3)区别每个数块和游戏结束页面
数块上色:export class ColorUtil {
public getCellBackgroundColor(cellValue: number) {
switch (cellValue) {
case 2:
return "#EEE4DA";
case 4:
return "#EDE0C8";
case 8:
return "#F26179";
case 16:
return "#F59563";
case 32:
return "#F67C5F";
case 64:
return "#F65E36";
case 128:
return "#EDCF72";
case 256:
return "#EDCC61";
case 512:
return "#90C000";
case 1024:
return "#3365A5";
case 2048:
return "#90C000";
case 4096:
return "#60B0C0";
case 8192:
return "#9030C0";
default:
return "#CDC1B4";
}
}
}
4.整体布局
main目录下分为三个包:
model包
pages包
util包
分别是模型,布局,程序。
5.总结
通过上半学期的学习,也算给鸿蒙课画上一个圆满的句号,能够完成这次作业,少不了老师3个月的指导和学习,网上学习一些课外知识,找了一些课外优秀作品,参考了一些其他博客的优秀作品,突发灵感,选择了这个选题,代码量适中,中间也遇到了一些困难,但是通过参考一些文献也是修改出来。老师也说过,想要深入学习,这三个月也是不够的,这仅仅只是基础,我也会继续努力,刻苦学习编程。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2023-12-8 11:03:38修改
赞
2
收藏
回复
相关推荐