前端实现贪吃蛇小游戏的详细代码和解释。
首先,我们需要在 HTML 中添加一个画布元素,用于绘制游戏界面:
<canvas id="canvas" width="400" height="400">canvas>
然后,在 JavaScript 中,我们需要定义一些变量来表示游戏状态和参数:
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
const cellSize = 20
const width = canvas.width / cellSize
const height = canvas.height / cellSize
let snake = [{ x: 10, y: 10 }]
let direction = 'right'
let food = generateFood()
let score = 0
let gameOver = false
其中,canvas
和 ctx
分别表示画布元素和画布上下文。cellSize
表示每个格子的大小,width
和 height
分别表示画布的宽度和高度。snake
表示蛇的身体,direction
表示蛇的移动方向,food
表示食物的位置。score
表示得分,gameOver
表示游戏是否结束。
接着,我们需要定义一些函数来实现游戏逻辑。首先是 generateFood
函数,用于生成随机食物的位置:
function generateFood () {
let food = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
}
while (snake.some(cell => cell.x === food.x && cell.y === food.y)) {
food = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
}
}
return food
}
该函数首先随机生成一个食物的位置,然后检查该位置是否与蛇的身体重叠,如果是则重新生成位置,直到找到一个不与蛇重叠的位置。
接下来是 drawCell
函数,用于绘制一个格子:
function drawCell (x, y, color) {
ctx.fillStyle = color
ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize)
ctx.strokeStyle = 'white'
ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize)
}
该函数接受三个参数,分别表示格子的横坐标、纵坐标和颜色。它使用 fillRect
和 strokeRect
方法绘制格子的填充和边框。
接下来是 drawSnake
函数,用于绘制蛇的身体:
function drawSnake () {
snake.forEach(cell => {
drawCell(cell.x, cell.y, 'green')
})
}
该函数使用 forEach
方法遍历蛇的身体,然后调用 drawCell
函数绘制每个格子。
接下来是 drawFood
函数,用于绘制食物:
function drawFood () {
drawCell(food.x, food.y, 'red')
}
该函数调用 drawCell
函数绘制食物格子。
接下来是 update
函数,用于更新游戏状态:
function update () {
const head = { x: snake[0].x, y: snake[0].y }
switch (direction) {
case 'up':
head.y--
break
case 'down':
head.y++
break
case 'left':
head.x--
break
case 'right':
head.x++
break
}
if (head.x < 0 || head.x >= width || head.y < 0 || head.y >= height || snake.some(cell => cell.x === head.x && cell.y === head.y)) {
gameOver = true
return
}
snake.unshift(head)
if (head.x === food.x && head.y === food.y) {
score++
food = generateFood()
} else {
snake.pop()
}
}
该函数首先复制蛇头的位置,然后根据当前的移动方向更新蛇头的位置。如果蛇头超出了画布边界或者与蛇的身体重叠,则游戏结束。否则,将蛇头插入到蛇的身体的头部,然后检查是否吃到了食物。如果吃到了食物,则将得分加一,并生成新的食物。否则,将蛇的尾部删除。
最后是 draw
函数,用于绘制游戏界面:
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height)
drawSnake()
drawFood()
ctx.fillStyle = 'white'
ctx.fillText(`Score: ${score}`, 10, canvas.height - 10)
}
该函数首先使用 clearRect
方法清空画布,然后调用 drawSnake
和 drawFood
函数绘制蛇和食物,最后使用 fillText
方法绘制得分。
最后是游戏循环,使用 setInterval
方法每隔一段时间调用一次 update
和 draw
函数:
setInterval(() => {
if (!gameOver) {
update()
draw()
}
}, 100)
至此,贪吃蛇小游戏的前端实现就完成了。完整代码如下:
好的,下面是完整代码和详细解释:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>贪吃蛇小游戏title>
<style>
canvas {
border: 1px solid black;
}
style>
head>
<body>
<canvas id="canvas" width="400" height="400">canvas>
<script>
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
const cellSize = 20
const width = canvas.width / cellSize
const height = canvas.height / cellSize
let snake = [{ x: 10, y: 10 }]
let direction = 'right'
let food = generateFood()
let score = 0
let gameOver = false
function generateFood () {
let food = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
}
while (snake.some(cell => cell.x === food.x && cell.y === food.y)) {
food = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
}
}
return food
}
function drawCell (x, y, color) {
ctx.fillStyle = color
ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize)
ctx.strokeStyle = 'white'
ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize)
}
function drawSnake () {
snake.forEach(cell => {
drawCell(cell.x, cell.y, 'green')
})
}
function drawFood () {
drawCell(food.x, food.y, 'red')
}
function update () {
const head = { x: snake[0].x, y: snake[0].y }
switch (direction) {
case 'up':
head.y--
break
case 'down':
head.y++
break
case 'left':
head.x--
break
case 'right':
head.x++
break
}
if (head.x < 0 || head.x >= width || head.y < 0 || head.y >= height || snake.some(cell => cell.x === head.x && cell.y === head.y)) {
gameOver = true
return
}
snake.unshift(head)
if (head.x === food.x && head.y === food.y) {
score++
food = generateFood()
} else {
snake.pop()
}
}
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height)
drawSnake()
drawFood()
ctx.fillStyle = 'white'
ctx.fillText(`Score: ${score}`, 10, canvas.height - 10)
}
setInterval(() => {
if (!gameOver) {
update()
draw()
}
}, 100)
document.addEventListener('keydown', event => {
switch (event.key) {
case 'ArrowUp':
if (direction !== 'down') {
direction = 'up'
}
break
case 'ArrowDown':
if (direction !== 'up') {
direction = 'down'
}
break
case 'ArrowLeft':
if (direction !== 'right') {
direction = 'left'
}
break
case 'ArrowRight':
if (direction !== 'left') {
direction = 'right'
}
break
}
})
script>
body>
html>
首先定义了一些常量,包括格子的大小、画布的宽度和高度等等。
然后定义了几个变量,包括蛇的初始位置、移动方向、食物的位置、得分和游戏是否结束等等。
接下来是 generateFood
函数,用于生成随机的食物位置:
function generateFood () {
let food = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
}
while (snake.some(cell => cell.x === food.x && cell.y === food.y)) {
food = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
}
}
return food
}
该函数首先生成一个随机的食物位置,然后检查该位置是否与蛇的身体重叠。如果重叠,则重新生成随机位置,直到找到一个不与蛇的身体重叠的位置。
接下来是 drawCell
函数,用于绘制单个格子:
function drawCell (x, y, color) {
ctx.fillStyle = color
ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize)
ctx.strokeStyle = 'white'
ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize)
}
该函数接受三个参数,分别表示格子的横坐标、纵坐标和颜色。它使用 fillRect
和 strokeRect
方法绘制格子的填充和边框。
接下来是 drawSnake
函数,用于绘制蛇的身体:
function drawSnake () {
snake.forEach(cell => {
drawCell(cell.x, cell.y, 'green')
})
}
该函数使用 forEach
方法遍历蛇的身体,然后调用 drawCell
函数绘制每个格子。
接下来是 drawFood
函数,用于绘制食物:
function drawFood () {
drawCell(food.x, food.y, 'red')
}
该函数调用 drawCell
函数绘制食物格子。
接下来是 update
函数,用于更新游戏状态:
function update () {
const head = { x: snake[0].x, y: snake[0].y }
switch (direction) {
case 'up':
head.y--
break
case 'down':
head.y++
break
case 'left':
head.x--
break
case 'right':
head.x++
break
}
if (head.x < 0 || head.x >= width || head.y < 0 || head.y >= height || snake.some(cell => cell.x === head.x && cell.y === head.y)) {
gameOver = true
return
}
snake.unshift(head)
if (head.x === food.x && head.y === food.y) {
score++
food = generateFood()
} else {
snake.pop()
}
}
该函数首先创建一个新的头部位置,根据当前移动方向更新头部位置。然后检查头部是否超出边界或与蛇的身体重叠。如果是,则游戏结束。否则,将新的头部位置插入到蛇的身体前面。如果头部位置与食物位置重叠,则得分加一,生成新的食物位置,否则将蛇的尾部弹出,使其移动。
最后是 draw
函数,用于绘制游戏界面:
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height)
drawSnake()
drawFood()
ctx.fillStyle = 'white'
ctx.fillText(`Score: ${score}`, 10, canvas.height - 10)
}
该函数首先使用 clearRect
方法清空画布,然后分别调用 drawSnake
和 drawFood
函数绘制蛇和食物。最后使用 fillText
方法绘制得分。
最后是游戏主循环,使用 setInterval
方法每隔一定时间更新游戏状态并绘制游戏界面。并且监听键盘事件,根据按键更新移动方向。
setInterval(() => {
if (!gameOver) {
update()
draw()
}
}, 100)
document.addEventListener('keydown', event => {
switch (event.key) {
case 'ArrowUp':
if (direction !== 'down') {
direction = 'up'
}
break
case 'ArrowDown':
if (direction !== 'up') {
direction = 'down'
}
break
case 'ArrowLeft':
if (direction !== 'right') {
direction = 'left'
}
break
case 'ArrowRight':
if (direction !== 'left') {
direction = 'right'
}
break
}
})
这就是贪吃蛇游戏的全部代码。