上一次, 我们介绍了在Microbit上编写最简单的贪吃蛇游戏(Microbit 游戏编程: 不会吃胖的贪食蛇 (自带人工智能)), 不过只是个原形, 因为那只蛇并不会长胖, 有网友说更像是一个男孩爱上一个女孩疯狂的爱情故事.
这一次, 我们将对游戏的关键部分进行修改, 不过考虑到整个 Microbit 的屏幕才25个像素点, 我们加个限制让蛇在长度为10的时候停止生长, 这样的话, 只要你玩得好, 游戏能一直进行下去.
贪吃蛇的身体
由于蛇的身体不再是单个game.LedSprite对象, 我们将需要将蛇的身体块存储在数组中. 我们可以定义一个initSnake函数, 该函数需要传进一组蛇身体坐标并创建相应的精灵数组.
1 2 3 4 5 6 7 | function initSnake(arr: Array<number>) { let result = []; for (let i = 0; i + 1 < arr.length; i += 2) { result.push(game.createSprite(arr[i], arr[i + 1])); } return result; }; |
function initSnake(arr: Array<number>) { let result = []; for (let i = 0; i + 1 < arr.length; i += 2) { result.push(game.createSprite(arr[i], arr[i + 1])); } return result; };
游戏初始化蛇的身体
1 2 3 4 5 6 | let direction = 1; // initial direction is down let dxOffset = [[1, 0], [0, 1], [-1, 0], [0, -1]]; let snake = initSnake([px, py, px + 1, py]); //当蛇长到10像素时, 它停止增长 //避免填充LED const maxLength = 10; |
let direction = 1; // initial direction is down let dxOffset = [[1, 0], [0, 1], [-1, 0], [0, -1]]; let snake = initSnake([px, py, px + 1, py]); //当蛇长到10像素时, 它停止增长 //避免填充LED const maxLength = 10;
碰撞检测
蛇的下一个像素点必须不是蛇的身体, 否则蛇就会立刻狗带.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 检查(x, y)是否为蛇体的坐标之一. function isOnSnake(x: number, y: number): boolean { for (let body of snake) { if (body.x() == x && body.y() == y) { return true; } } return false; } function validPixelCoordinate(nx: number, ny: number): boolean { return (nx >= 0 && nx <= 4 && ny >= 0 && ny <= 4) && (!isOnSnake(nx, ny)); } |
// 检查(x, y)是否为蛇体的坐标之一. function isOnSnake(x: number, y: number): boolean { for (let body of snake) { if (body.x() == x && body.y() == y) { return true; } } return false; } function validPixelCoordinate(nx: number, ny: number): boolean { return (nx >= 0 && nx <= 4 && ny >= 0 && ny <= 4) && (!isOnSnake(nx, ny)); }
同样, 我们需要调整苹果生成函数, 确保新苹果不位于贪吃蛇的身体之一上.
1 2 3 4 5 6 7 8 9 | function placeNextApple() { let x, y; do { x = Math.randomRange(0, 4); y = Math.randomRange(0, 4); } while (isOnSnake(x, y)); apple.goTo(x, y); apple.setBrightness(100); } |
function placeNextApple() { let x, y; do { x = Math.randomRange(0, 4); y = Math.randomRange(0, 4); } while (isOnSnake(x, y)); apple.goTo(x, y); apple.setBrightness(100); }
重置游戏
重置游戏resetGame函数的一项更改是在重新初始化新的主体之前, 删除贪吃蛇的身体. 删除精灵将使该精灵对象从内存中删除, 删除后的精灵对象既不会与其他精灵对象进行交互, 也不会显示在LED屏幕上.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function resetGame() { game.setScore(0); score = 0; direction = 0; px = 0; py = 0; // 释放蛇的身体和占用的内存 for (let s of snake) { s.delete(); } snake = initSnake([px, py, px + 1, py]); placeNextApple(); game.resume(); } |
function resetGame() { game.setScore(0); score = 0; direction = 0; px = 0; py = 0; // 释放蛇的身体和占用的内存 for (let s of snake) { s.delete(); } snake = initSnake([px, py, px + 1, py]); placeNextApple(); game.resume(); }
蛇向前爬行
当蛇移动时, 我们可以使用Javascript的数组unshift方法将新的像素坐标推到数组的最前面. 然后, 我们需要通过pop()方法删除最后一个元素.
1 2 3 4 5 6 7 8 9 10 11 | function moveForward() { let dx = dxOffset[direction]; px += dx[0]; py += dx[1]; if (!validPixelCoordinate(px, py)) { gameOver(); } snake.unshift(game.createSprite(px, py)); let last = snake.pop(); last.delete(); } |
function moveForward() { let dx = dxOffset[direction]; px += dx[0]; py += dx[1]; if (!validPixelCoordinate(px, py)) { gameOver(); } snake.unshift(game.createSprite(px, py)); let last = snake.pop(); last.delete(); }
贪吃蛇吃了胖 胖了吃
这部分可以在主游戏循环中处理. 当检测到蛇头和苹果之间发生碰撞时, 我们可以将新像素推到身体的尾部(复制一个尾巴).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | basic.forever(function () { if (game.isGameOver()) { return; } let delay = Math.max(100, 1000 - score * 50); basic.pause(delay); //letComputerPlay(); moveForward(); if (snake[0].isTouching(apple)) { // 吃到了苹果 // 在大于 maxLength 后就不长了 if (snake.length < maxLength) { // 复制一个尾巴 snake.push(snake[snake.length - 1]); } score++; placeNextApple(); } }) |
basic.forever(function () { if (game.isGameOver()) { return; } let delay = Math.max(100, 1000 - score * 50); basic.pause(delay); //letComputerPlay(); moveForward(); if (snake[0].isTouching(apple)) { // 吃到了苹果 // 在大于 maxLength 后就不长了 if (snake.length < maxLength) { // 复制一个尾巴 snake.push(snake[snake.length - 1]); } score++; placeNextApple(); } })
Microbit 完整的贪吃蛇游戏
完整的源代码和Microbit在这里: https://makecode.microbit.org/_2qyYchHfsDDC
上次的游戏智能AI并不需要修改, 但由于采用的是贪心算法, 所以有可能会陷入死局 导致贪吃蛇无路可走 游戏结束.
带有贪心算法智能游戏 AI的代码和模拟器: https://makecode.microbit.org/_9T89xWaMkRV4
Microbit采用贪心策略玩贪吃蛇的视频:
想立马玩贪吃蛇游戏?
英文: Microbit Programming: Snake Game with Growing Body with Greedy AI
loading...
上一篇: 用 Javascript 做一个贪食蛇的游戏
下一篇: 圣诞节 Boxing Day 剑桥华人音乐聚会