在 ChatGPT 成功帮助解决 Excel 操作之后,继续探索边界,请它出手写一个小游戏。常见的益智小游戏,无非以下几种:

  1. 贪食蛇
  2. 扫雷
  3. 俄罗斯方块
  4. 汉诺塔

考验一下 ChatGPT 的极限。

首先我在网页版 ChatGPT 上,请它写一个贪食蛇的游戏。

问:

请用 JavaScript 写一款简单的贪食蛇游戏。

第一次,ChatGPT 试图将所有代码写进单一 HTML 文件,很快就超时了。

问:

超时了,请分模块编写,先写 HTML 及 CSS 结构,从外部引用 JavaScript,JavaScript 命名为 main.js。

答:

好的,以下是分模块编写的贪食蛇游戏的 HTML 和 CSS 结构,以及外部引用的 main.js 文件。

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>贪食蛇游戏</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <canvas id="canvas"></canvas>
  <script src="main.js"></script>
</body>
</html>

style.css

canvas {
  border: 1px solid #ccc;
}

接下来写 main.js,编写至 gameOver 方法,再次超时。

答:

// 获取canvas元素和绘图上下文
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// 定义常量和变量
var GRID_SIZE = 10;
var WIDTH = canvas.width / GRID_SIZE;
var HEIGHT = canvas.height / GRID_SIZE;
var snake = {
  body: [{x: 3, y: 1}, {x: 2, y: 1}, {x: 1, y: 1}],
  direction: 'right'
};
var food = {x: 10, y: 10};
var score = 0;

// 绘制网格
function drawGrid() {
  ctx.beginPath();
  ctx.strokeStyle = '#ddd';
  for (var x = 0; x <= canvas.width; x += GRID_SIZE) {
    ctx.moveTo(x, 0);
    ctx.lineTo(x, canvas.height);
  }
  for (var y = 0; y <= canvas.height; y += GRID_SIZE) {
    ctx.moveTo(0, y);
    ctx.lineTo(canvas.width, y);
  }
  ctx.stroke();
}

// 绘制蛇
function drawSnake() {
  ctx.fillStyle = 'green';
  for (var i = 0; i < snake.body.length; i++) {
    var cell = snake.body[i];
    ctx.fillRect(cell.x * GRID_SIZE, cell.y * GRID_SIZE, GRID_SIZE, GRID_SIZE);
  }
}

// 绘制食物
function drawFood() {
  ctx.fillStyle = 'red';
  ctx.fillRect(food.x * GRID_SIZE, food.y * GRID_SIZE, GRID_SIZE, GRID_SIZE);
}

// 更新蛇的位置
function updateSnake() {
  var head = {x: snake.body[0].x, y: snake.body[0].y};
  switch (snake.direction) {
    case 'up': head.y--; break;
    case 'down': head.y++; break;
    case 'left': head.x--; break;
    case 'right': head.x++; break;
  }
  snake.body.unshift(head);
  if (head.x === food.x && head.y === food.y) {
    food.x = Math.floor(Math.random() * WIDTH);
    food.y = Math.floor(Math.random() * HEIGHT);
    score++;
  } else {
    snake.body.pop();
  }
}

// 检查游戏是否结束
function checkGameOver() {
  var head = snake.body[0];
  if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
    gameOver();
  }
  for (var i = 1; i < snake.body.length; i++) {
    if (head.x === snake.body[i].x && head.y === snake.body[i].y) {
      gameOver();
    }
  }
}

// 游戏结束
function gameOver() {
  alert('游戏结束

问:

还是超时,写继续写 游戏结束 的代码。

答:

抱歉,我不小心把代码截断了。以下是游戏结束部分的代码:

// 游戏结束
function gameOver() {
  alert('游戏结束,得分:' + score);
  clearInterval(intervalId);
}

// 处理按键事件
function handleKeydown(event) {
  switch (event.keyCode) {
    case 37: // 左箭头
      if (snake.direction !== 'right') {
        snake.direction = 'left';
      }
      break;
    case 38: // 上箭头
      if (snake.direction !== 'down') {
        snake.direction = 'up';
      }
      break;
    case 39: // 右箭头
      if (snake.direction !== 'left') {
        snake.direction = 'right';
      }
      break;
    case 40: // 下箭头
      if (snake.direction !== 'up') {
        snake.direction = 'down';
      }
      break;
  }
}

// 主循环
var intervalId = setInterval(function() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawGrid();
  updateSnake();
  drawSnake();
  drawFood();
  checkGameOver();
}, 100);

// 处理按键事件
document.addEventListener('keydown', handleKeydown);

很了不起,以上代码组装起来,可以正常运行:

https://chenzixin.com/ivy/bit/snake/

但有以下缺陷:

  1. 页面加载即开始运行,没有 startGame 方法;
  2. 游戏结束,用 alert 弹出得分,不够友好;

第一个问题,我现在还没有能力改进,第二问题简单:

模拟一个控制台:

<textarea id="console"></textarea> <br>
<input type="button" id="retry" value="Retry">

重写 gameOver 方法:

function gameOver() {
    document.querySelector("#console").innerHTML = 'Game over, the Score: ' + score;
    clearInterval(intervalId);
}

刷新页面,重启游戏:

function restart(){
    location.reload();
}
document.querySelector("#retry").addEventListener('click', restart);

很好了,看看你能得多少分?我玩了几局,得分都在 10 以下,手和脑的速度,都退化了。

能看画面调大吗?看了下代码,并没有显式定义 canvas 的宽和高,我想到去 CSS 中修改:

canvas {
  width: 600px;
  height: 300px; 
  border: 1px solid #ccc;
}

但发现格子变大,画面变形,查了下资料才知道,canvas 的默认宽高,就是 300*150,修改 CSS,只是改变了画布的大小,画纸还是默认值,引擎会放大画纸以适应画布。因此,只能通过 JavaScript 修改:

canvas.width = 600; // default: 300
canvas.height = 300; // default: 150

知识又增加了。

最后修改:2023 年 04 月 13 日
如果觉得我的文章对你有用,请随意赞赏