前言
今天来还原初中时期记忆中的推箱子游戏,主要是让 Trae 用代码实现这个游戏的核心功能,
你是否还记得曾经初中时期在课余时间沉迷推箱子,今天就看看 Trae 是怎么实现。
游戏的核心逻辑
先把这个核心逻辑发给 Trae,看看他完成的是不是你想要的经典的推箱子游戏。
- 游戏开始时,玩家会看到一个由方格组成的网格,其中一些方格上有箱子,部分方格是目标位置。
- 玩家通过控制角色推动箱子,当所有箱子都被推到目标位置时,游戏胜利。
- 玩家一次只能推动一个箱子,不能斜推。
- 玩家在推动箱子时,若前方有障碍物或箱子挡住,则无法推动。
- 玩家需要在有限的步数内或规定时间内,将所有箱子推到目标位置,才算通关。
启动页面,发现推箱子的小人不见了,也无法进行操作,只能让Trae修复一下这个致命的bug
将控制台的报错发给Trae,把CSS类名中包含空格字符,DOMTokenList.add()方法不接受包含空格的类名处理掉即可完美的运行

Trae 代码解读
通过设定网格的行列数、箱子和目标位置的分布,来初始化游戏的布局,生成一个二维数组来表示游戏面板,通过 for 循环来填充网格,合理摆放箱子、目标位置和障碍物。
ini
for (let i = 0; i < rows; i++) {
const row = [];
for (let j = 0; j < cols; j++) {
row.push({
hasBox: false,
isTarget: false,
isObstacle: false,
isPlayer: false
});
}
grid.push(row);
}
// 放置箱子
for (let i = 0; i < boxCount; i++) {
const row = Math.floor(Math.random() * rows);
const col = Math.floor(Math.random() * cols);
if (!grid[row][col].isTarget && !grid[row][col].isObstacle) {
grid[row][col].hasBox = true;
}
}
// 放置目标位置
for (let i = 0; i < targetCount; i++) {
const row = Math.floor(Math.random() * rows);
const col = Math.floor(Math.random() * cols);
if (!grid[row][col].hasBox && !grid[row][col].isObstacle) {
grid[row][col].isTarget = true;
}
}
// 放置障碍物
for (let i = 0; i < obstacleCount; i++) {
const row = Math.floor(Math.random() * rows);
const col = Math.floor(Math.random() * cols);
if (!grid[row][col].hasBox && !grid[row][col].isTarget) {
grid[row][col].isObstacle = true;
}
}
// 放置玩家
let playerPlaced = false;
while (!playerPlaced) {
const row = Math.floor(Math.random() * rows);
const col = Math.floor(Math.random() * cols);
if (!grid[row][col].hasBox && !grid[row][col].isObstacle) {
grid[row][col].isPlayer = true;
playerPlaced = true;
}
}
通过事件监听实现玩家控制角色移动来推动箱子,并判断游戏是否胜利。
ini
board.addEventListener('keydown', (e) => {
let newRow = playerRow;
let newCol = playerCol;
switch (e.key) {
case 'ArrowUp':
newRow--;
break;
case 'ArrowDown':
newRow++;
break;
case 'ArrowLeft':
newCol--;
break;
case 'ArrowRight':
newCol++;
break;
}
// 检查移动是否合法
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && !grid[newRow][newCol].isObstacle) {
// 如果当前位置有箱子
if (grid[newRow][newCol].hasBox) {
// 检查箱子前方是否有空位
let boxNewRow = newRow;
let boxNewCol = newCol;
switch (e.key) {
case 'ArrowUp':
boxNewRow--;
break;
case 'ArrowDown':
boxNewRow++;
break;
case 'ArrowLeft':
boxNewCol--;
break;
case 'ArrowRight':
boxNewCol++;
break;
}
if (boxNewRow >= 0 && boxNewRow < rows && boxNewCol >= 0 && boxNewCol < cols && !grid[boxNewRow][boxNewCol].hasBox && !grid[boxNewRow][boxNewCol].isObstacle) {
// 移动箱子
grid[boxNewRow][boxNewCol].hasBox = true;
grid[newRow][newCol].hasBox = false;
// 移动玩家
grid[playerRow][playerCol].isPlayer = false;
grid[newRow][newCol].isPlayer = true;
playerRow = newRow;
playerCol = newCol;
checkGameStatus();
}
} else {
// 移动玩家
grid[playerRow][playerCol].isPlayer = false;
grid[newRow][newCol].isPlayer = true;
playerRow = newRow;
playerCol = newCol;
checkGameStatus();
}
}
});
最后是来自 Trae 自己对这款推箱子的总结,主要是游戏功能和设计,还有考虑到游戏体验,有撤销上一步的操作,非常的人性化。
Trae 在生成时,考虑的情况,主要是箱子、目标位置、障碍物、步数限制、计时器、难度选择等因素。

总结
1、这个游戏的核心功能,主要是靠玩家来推动箱子,Trae 非常人性化的支持多种操作方式,来让高级玩家有更好的游戏体验。

2、考虑到游戏玩家可能没玩过,Trae 也是帮我们设计了三个游戏难度以及游戏关卡,不会让新手玩家没有体验感直接进入到地狱难度/高难度关卡,可以一步步的体验到游戏的关卡难度。
