网站开发包括什么,网站标识描述可以填关键词吗,北京vi设计公司哪,永久免费的云电脑推箱子游戏#xff08;Sokoban#xff09;的实现。游戏由多个单元格组成#xff0c;每个单元格可以是透明的、墙或可移动的区域。游戏使用Cell类定义单元格的状态#xff0c;如类型#xff08;透明、墙、可移动区域#xff09;、圆角大小及坐标偏移。而MyPosition类则用于…
推箱子游戏Sokoban的实现。游戏由多个单元格组成每个单元格可以是透明的、墙或可移动的区域。游戏使用Cell类定义单元格的状态如类型透明、墙、可移动区域、圆角大小及坐标偏移。而MyPosition类则用于表示位置信息并提供设置位置的方法。
游戏主体结构Sokoban定义了游戏的基本元素包括网格单元格的状态、胜利位置、箱子的位置以及玩家的位置等并提供了初始化游戏状态的方法。游戏中还包含有动画效果当玩家尝试移动时会检查目标位置是否允许移动并根据情况决定是否需要移动箱子。此外游戏支持触摸输入并在完成一次移动后检查是否所有箱子都在目标位置上如果是则游戏胜利并显示一个对话框展示游戏用时。
【算法分析】
1. 移动玩家和箱子算法分析
算法思路根据玩家的滑动方向计算新的位置坐标然后检查新位置的合法性包括是否超出边界、是否是墙等情况。如果新位置是箱子则需要进一步判断箱子后面的位置是否为空以确定是否可以推动箱子。
实现逻辑通过定义方向对象和计算新位置坐标的方式简化了移动操作的逻辑。在移动过程中需要考虑动画效果的控制以提升用户体验。
movePlayer(direction: string) {const directions: object Object({right: Object({ dx: 0, dy: 1}),left: Object({ dx:0 , dy:-1 }),down: Object({ dx: 1, dy: 0 }),up: Object({ dx: -1, dy: 0 })});const dx: number directions[direction][dx]; //{ dx, dy }const dy: number directions[direction][dy]; //{ dx, dy }const newX: number this.playerPosition.x dx;const newY: number this.playerPosition.y dy;// 检查新位置是否合法// 箱子移动逻辑...// 动画效果控制...
}
2. 胜利条件判断算法分析
算法思路遍历所有箱子的位置检查每个箱子是否在一个胜利位置上如果所有箱子都在胜利位置上则判定游戏胜利。
实现逻辑通过嵌套循环和数组方法实现了对胜利条件的判断。这种算法适合用于检查游戏胜利条件是否满足的场景。
isVictoryConditionMet(): boolean {return this.cratePositions.every(crate {return this.victoryPositions.some(victory crate.x victory.x crate.y victory.y);});
}
3. 动画控制算法分析
算法思路利用动画函数实现移动过程中的动画效果包括移动过程的持续时间和结束后的处理逻辑。
实现逻辑通过嵌套调用动画函数实现了移动过程中的动画效果控制。这种方式可以使移动过程更加流畅和生动。
animateToImmediately({duration: 150,onFinish: () {animateToImmediately({duration: 0,onFinish: () {// 动画结束后的处理...}}, () {// 动画过程中的处理...});}
}, () {// 动画效果控制...
});
4. 触摸操作和手势识别算法分析
算法思路监听触摸事件和手势事件识别玩家的滑动方向然后调用相应的移动函数处理玩家和箱子的移动。
实现逻辑通过手势识别和事件监听实现了玩家在屏幕上滑动操作的识别和响应。这种方式可以使玩家通过触摸操作来控制游戏的进行。
gesture(SwipeGesture({ direction: SwipeDirection.All }).onAction((_event: GestureEvent) {// 手势识别和处理逻辑...})
)
【完整代码】
import { promptAction } from kit.ArkUI // 导入ArkUI工具包中的提示操作模块
ObservedV2 // 观察者模式装饰器
class Cell { // 定义游戏中的单元格类Trace // 跟踪装饰器标记属性以被跟踪type: number 0; // 单元格类型0透明1墙2可移动区域Trace topLeft: number 0; // 左上角圆角大小Trace topRight: number 0; // 右上角圆角大小Trace bottomLeft: number 0; // 左下角圆角大小Trace bottomRight: number 0; // 右下角圆角大小Trace x: number 0; // 单元格的X坐标偏移量Trace y: number 0; // 单元格的Y坐标偏移量constructor(cellType: number) { // 构造函数this.type cellType; // 初始化单元格类型}
}
ObservedV2 // 观察者模式装饰器
class MyPosition { // 定义位置类Trace // 跟踪装饰器标记属性以被跟踪x: number 0; // X坐标Trace y: number 0; // Y坐标setPosition(x: number, y: number) { // 设置位置的方法this.x x; // 更新X坐标this.y y; // 更新Y坐标}
}
Entry // 入口装饰器
Component // 组件装饰器
struct Sokoban { // 定义游戏主结构cellWidth: number 100; // 单元格宽度State grid: Cell[][] [ // 游戏网格状态[new Cell(0), new Cell(1), new Cell(1), new Cell(1), new Cell(1), new Cell(1)],[new Cell(1), new Cell(1), new Cell(2), new Cell(2), new Cell(2), new Cell(1)],[new Cell(1), new Cell(2), new Cell(2), new Cell(2), new Cell(1), new Cell(1)],[new Cell(1), new Cell(2), new Cell(2), new Cell(2), new Cell(2), new Cell(1)],[new Cell(1), new Cell(1), new Cell(2), new Cell(2), new Cell(2), new Cell(1)],[new Cell(0), new Cell(1), new Cell(1), new Cell(1), new Cell(1), new Cell(1)],];State victoryPositions: MyPosition[] [new MyPosition(), new MyPosition()]; // 胜利位置数组State cratePositions: MyPosition[] [new MyPosition(), new MyPosition()]; // 箱子位置数组playerPosition: MyPosition new MyPosition(); // 玩家位置State screenStartX: number 0; // 触摸开始时的屏幕X坐标State screenStartY: number 0; // 触摸开始时的屏幕Y坐标State lastScreenX: number 0; // 触摸结束时的屏幕X坐标State lastScreenY: number 0; // 触摸结束时的屏幕Y坐标State startTime: number 0; // 游戏开始时间isAnimationRunning: boolean false // 动画是否正在运行aboutToAppear(): void { // 游戏加载前的准备工作// 初始化某些单元格的圆角大小...this.grid[0][1].topLeft 25;this.grid[0][5].topRight 25;this.grid[1][0].topLeft 25;this.grid[4][0].bottomLeft 25;this.grid[5][1].bottomLeft 25;this.grid[5][5].bottomRight 25;this.grid[1][1].bottomRight 10;this.grid[4][1].topRight 10;this.grid[2][4].topLeft 10;this.grid[2][4].bottomLeft 10;this.initializeGame(); // 初始化游戏}initializeGame() { // 初始化游戏状态this.startTime Date.now(); // 设置游戏开始时间为当前时间// 设置胜利位置和箱子位置...this.startTime Date.now(); // 设置游戏开始时间为当前时间this.victoryPositions[0].setPosition(1, 3);this.victoryPositions[1].setPosition(1, 4);this.cratePositions[0].setPosition(2, 2);this.cratePositions[1].setPosition(2, 3);this.playerPosition.setPosition(1, 2);}isVictoryPositionVisible(x: number, y: number): boolean { // 判断位置是否为胜利位置return this.victoryPositions.some(position position.x x position.y y); // 返回是否有胜利位置与给定位置匹配}isCratePositionVisible(x: number, y: number): boolean { // 判断位置是否为箱子位置return this.cratePositions.some(position position.x x position.y y); // 返回是否有箱子位置与给定位置匹配}isPlayerPositionVisible(x: number, y: number): boolean { // 判断位置是否为玩家位置return this.playerPosition.x x this.playerPosition.y y; // 返回玩家位置是否与给定位置相同}movePlayer(direction: string) {const directions: object Object({right: Object({ dx: 0, dy: 1}),left: Object({ dx:0 , dy:-1 }),down: Object({ dx: 1, dy: 0 }),up: Object({ dx: -1, dy: 0 })});const dx: number directions[direction][dx]; //{ dx, dy }const dy: number directions[direction][dy]; //{ dx, dy }const newX: number this.playerPosition.x dx;const newY: number this.playerPosition.y dy;const targetCell this.grid[newX][newY];// 检查新位置是否超出边界if (!targetCell) {return;}// 如果新位置是墙则不能移动if (targetCell.type 1) {return;}let crateIndex -1;if (this.isCratePositionVisible(newX, newY)) {const crateBehindCell this.grid[newX dx][newY dy];if (!crateBehindCell || crateBehindCell.type ! 2) {return;}crateIndex this.cratePositions.findIndex(crate crate.x newX crate.y newY);if (crateIndex -1 || this.isCratePositionVisible(newX dx, newY dy)) {return;}}if (this.isAnimationRunning) {return}this.isAnimationRunning trueanimateToImmediately({duration: 150,onFinish: () {animateToImmediately({duration: 0,onFinish: () {this.isAnimationRunning false}}, () {if (crateIndex ! -1) {this.grid[this.cratePositions[crateIndex].x][this.cratePositions[crateIndex].y].x 0;this.grid[this.cratePositions[crateIndex].x][this.cratePositions[crateIndex].y].y 0;this.cratePositions[crateIndex].x dx;this.cratePositions[crateIndex].y dy;}this.grid[this.playerPosition.x][this.playerPosition.y].x 0this.grid[this.playerPosition.x][this.playerPosition.y].y 0this.playerPosition.setPosition(newX, newY);// 检查是否获胜const isAllCrateOnTarget this.cratePositions.every(crate {return this.victoryPositions.some(victory crate.x victory.x crate.y victory.y);});if (isAllCrateOnTarget) {console.log(恭喜你你赢了);// 可以在这里添加胜利处理逻辑promptAction.showDialog({// 显示对话框title: 游戏胜利, // 对话框标题message: 恭喜你用时 ((Date.now() - this.startTime) / 1000).toFixed(3) 秒, // 对话框消息buttons: [{ text: 重新开始, color: #ffa500 }] // 对话框按钮}).then(() { // 对话框关闭后执行this.initializeGame(); // 重新开始游戏});}})}}, () {this.grid[this.playerPosition.x][this.playerPosition.y].x dy * this.cellWidth;this.grid[this.playerPosition.x][this.playerPosition.y].y dx * this.cellWidth;if (crateIndex ! -1) {this.grid[this.cratePositions[crateIndex].x][this.cratePositions[crateIndex].y].x dy * this.cellWidth;this.grid[this.cratePositions[crateIndex].x][this.cratePositions[crateIndex].y].y dx * this.cellWidth;}console.info(dx:${dx},dy:${dy})})}build() {Column({ space: 20 }) {//游戏区Stack() {//非零区加瓷砖Column() {ForEach(this.grid, (row: [], rowIndex: number) {Row() {ForEach(row, (item: Cell, colIndex: number) {Stack() {Text().width(${this.cellWidth}lpx).height(${this.cellWidth}lpx).backgroundColor(item.type 0 ? Color.Transparent :((rowIndex colIndex) % 2 0 ? #cfb381 : #e1ca9f)).borderRadius({topLeft: item.topLeft 10 ? item.topLeft : 0,topRight: item.topRight 10 ? item.topRight : 0,bottomLeft: item.bottomLeft 10 ? item.bottomLeft : 0,bottomRight: item.bottomRight 10 ? item.bottomRight : 0})//如果和是胜利坐标显示叉号Stack() {Text().width(${this.cellWidth / 2}lpx).height(${this.cellWidth / 8}lpx).backgroundColor(Color.White)Text().width(${this.cellWidth / 8}lpx).height(${this.cellWidth / 2}lpx).backgroundColor(Color.White)}.rotate({ angle: 45 }).visibility(this.isVictoryPositionVisible(rowIndex, colIndex) ? Visibility.Visible : Visibility.None)}})}})}Column() {ForEach(this.grid, (row: [], rowIndex: number) {Row() {ForEach(row, (item: Cell, colIndex: number) {//是否显示箱子Stack() {Text().width(${this.cellWidth}lpx).height(${this.cellWidth}lpx).backgroundColor(item.type 1 ? #412c0f : Color.Transparent).borderRadius({topLeft: item.topLeft,topRight: item.topRight,bottomLeft: item.bottomLeft,bottomRight: item.bottomRight})Text(箱).fontColor(Color.White).textAlign(TextAlign.Center).fontSize(${this.cellWidth / 2}lpx).width(${this.cellWidth - 5}lpx).height(${this.cellWidth - 5}lpx).backgroundColor(#cb8321)//#995d12 #cb8321.borderRadius(10).visibility(this.isCratePositionVisible(rowIndex, colIndex) ? Visibility.Visible : Visibility.None)Text(我).fontColor(Color.White).textAlign(TextAlign.Center).fontSize(${this.cellWidth / 2}lpx).width(${this.cellWidth - 5}lpx).height(${this.cellWidth - 5}lpx).backgroundColor(#007dfe)//#995d12 #cb8321.borderRadius(10).visibility(this.isPlayerPositionVisible(rowIndex, colIndex) ? Visibility.Visible : Visibility.None)}.width(${this.cellWidth}lpx).height(${this.cellWidth}lpx).translate({ x: ${item.x}lpx, y: ${item.y}lpx })})}})}}Button(重新开始).clickEffect({ level: ClickEffectLevel.MIDDLE }).onClick(() {this.initializeGame();});}.width(100%).height(100%).backgroundColor(#fdb300).padding({ top: 20 }).onTouch((e) {if (e.type TouchType.Down e.touches.length 0) { // 触摸开始记录初始位置this.screenStartX e.touches[0].x;this.screenStartY e.touches[0].y;} else if (e.type TouchType.Up e.changedTouches.length 0) { // 当手指抬起时更新最后的位置this.lastScreenX e.changedTouches[0].x;this.lastScreenY e.changedTouches[0].y;}}).gesture(SwipeGesture({ direction: SwipeDirection.All })// 支持方向中 all可以是上下左右.onAction((_event: GestureEvent) {const swipeX this.lastScreenX - this.screenStartX;const swipeY this.lastScreenY - this.screenStartY;// 清除开始位置记录准备下一次滑动判断this.screenStartX 0;this.screenStartY 0;if (Math.abs(swipeX) Math.abs(swipeY)) {if (swipeX 0) {// 向右滑动this.movePlayer(right);} else {// 向左滑动this.movePlayer(left);}} else {if (swipeY 0) {// 向下滑动this.movePlayer(down);} else {// 向上滑动this.movePlayer(up);}}}))}
} 文章转载自: http://www.morning.wtnyg.cn.gov.cn.wtnyg.cn http://www.morning.cczrw.cn.gov.cn.cczrw.cn http://www.morning.hjbrd.cn.gov.cn.hjbrd.cn http://www.morning.tbcfj.cn.gov.cn.tbcfj.cn http://www.morning.rmxk.cn.gov.cn.rmxk.cn http://www.morning.lnmby.cn.gov.cn.lnmby.cn http://www.morning.kqrql.cn.gov.cn.kqrql.cn http://www.morning.mdfxn.cn.gov.cn.mdfxn.cn http://www.morning.qnhpq.cn.gov.cn.qnhpq.cn http://www.morning.wphfl.cn.gov.cn.wphfl.cn http://www.morning.wtdyq.cn.gov.cn.wtdyq.cn http://www.morning.tmcmj.cn.gov.cn.tmcmj.cn http://www.morning.errnull.com.gov.cn.errnull.com http://www.morning.kwqwp.cn.gov.cn.kwqwp.cn http://www.morning.rblqk.cn.gov.cn.rblqk.cn http://www.morning.xnnpy.cn.gov.cn.xnnpy.cn http://www.morning.rzdpd.cn.gov.cn.rzdpd.cn http://www.morning.zdnrb.cn.gov.cn.zdnrb.cn http://www.morning.zkbxx.cn.gov.cn.zkbxx.cn http://www.morning.pypqf.cn.gov.cn.pypqf.cn http://www.morning.hclqy.cn.gov.cn.hclqy.cn http://www.morning.rlsd.cn.gov.cn.rlsd.cn http://www.morning.rqsnl.cn.gov.cn.rqsnl.cn http://www.morning.bscsp.cn.gov.cn.bscsp.cn http://www.morning.dbfwq.cn.gov.cn.dbfwq.cn http://www.morning.mhnxs.cn.gov.cn.mhnxs.cn http://www.morning.bqdpy.cn.gov.cn.bqdpy.cn http://www.morning.rrbhy.cn.gov.cn.rrbhy.cn http://www.morning.xgjhy.cn.gov.cn.xgjhy.cn http://www.morning.trsdm.cn.gov.cn.trsdm.cn http://www.morning.kxnjg.cn.gov.cn.kxnjg.cn http://www.morning.yodajy.cn.gov.cn.yodajy.cn http://www.morning.rfyff.cn.gov.cn.rfyff.cn http://www.morning.gjmll.cn.gov.cn.gjmll.cn http://www.morning.ymqfx.cn.gov.cn.ymqfx.cn http://www.morning.qfnrx.cn.gov.cn.qfnrx.cn http://www.morning.guanszz.com.gov.cn.guanszz.com http://www.morning.nkwgy.cn.gov.cn.nkwgy.cn http://www.morning.kpbn.cn.gov.cn.kpbn.cn http://www.morning.mzhhr.cn.gov.cn.mzhhr.cn http://www.morning.wnqbf.cn.gov.cn.wnqbf.cn http://www.morning.npgwb.cn.gov.cn.npgwb.cn http://www.morning.qrwnj.cn.gov.cn.qrwnj.cn http://www.morning.lzrpy.cn.gov.cn.lzrpy.cn http://www.morning.lwbhw.cn.gov.cn.lwbhw.cn http://www.morning.drspc.cn.gov.cn.drspc.cn http://www.morning.srky.cn.gov.cn.srky.cn http://www.morning.pjbhk.cn.gov.cn.pjbhk.cn http://www.morning.xglgm.cn.gov.cn.xglgm.cn http://www.morning.sblgt.cn.gov.cn.sblgt.cn http://www.morning.qfmcm.cn.gov.cn.qfmcm.cn http://www.morning.wslr.cn.gov.cn.wslr.cn http://www.morning.zcsyz.cn.gov.cn.zcsyz.cn http://www.morning.jtsdk.cn.gov.cn.jtsdk.cn http://www.morning.yuanshenglan.com.gov.cn.yuanshenglan.com http://www.morning.tpkxs.cn.gov.cn.tpkxs.cn http://www.morning.cltrx.cn.gov.cn.cltrx.cn http://www.morning.zdhxm.com.gov.cn.zdhxm.com http://www.morning.skdrp.cn.gov.cn.skdrp.cn http://www.morning.cfjyr.cn.gov.cn.cfjyr.cn http://www.morning.dbxss.cn.gov.cn.dbxss.cn http://www.morning.cczrw.cn.gov.cn.cczrw.cn http://www.morning.tkzrh.cn.gov.cn.tkzrh.cn http://www.morning.klyyd.cn.gov.cn.klyyd.cn http://www.morning.tnrdz.cn.gov.cn.tnrdz.cn http://www.morning.xldpm.cn.gov.cn.xldpm.cn http://www.morning.snxbf.cn.gov.cn.snxbf.cn http://www.morning.brlgf.cn.gov.cn.brlgf.cn http://www.morning.ydrml.cn.gov.cn.ydrml.cn http://www.morning.xdttq.cn.gov.cn.xdttq.cn http://www.morning.htjwz.cn.gov.cn.htjwz.cn http://www.morning.shuangxizhongxin.cn.gov.cn.shuangxizhongxin.cn http://www.morning.lcbt.cn.gov.cn.lcbt.cn http://www.morning.qmbtn.cn.gov.cn.qmbtn.cn http://www.morning.rmyt.cn.gov.cn.rmyt.cn http://www.morning.zrdqz.cn.gov.cn.zrdqz.cn http://www.morning.zynjt.cn.gov.cn.zynjt.cn http://www.morning.qsy38.cn.gov.cn.qsy38.cn http://www.morning.ctxt.cn.gov.cn.ctxt.cn http://www.morning.tjpmf.cn.gov.cn.tjpmf.cn