我正在制作Javascipt蛇游戏,想知道我能否逐步详细了解如何确保蛇内不产生食物?我得到了一些答案,但我无法真正理解它们。我知道我需要在某处使用while循环,但是我对该功能一无所知。谢谢:)
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
//set canvas dimension equal to css dimension
canvas.width = 768;
canvas.height = 512;
//now put those dimensions into variables
const cvsW = canvas.width;
const cvsH = canvas.height;
//create snake unit
const unit = 16;
//create snake array
let snake = [{x: cvsW/2, y: cvsH/2}];
//delcare global variable to hold users direction
let direction;
//create food object
let food = {
x : Math.floor(Math.random()*((cvsW/unit)-1)+1)*unit,
y : Math.floor(Math.random()*((cvsH/unit)-1)+1)*unit
}
//read user's direction
document.addEventListener('keydown', changeDirection);
function changeDirection(e) {
//set direction
if (e.keyCode == 37 && direction != 'right') direction = 'left';
else if (e.keyCode == 38 && direction != 'down') direction = 'up';
else if (e.keyCode == 39 && direction != 'left') direction = 'right';
else if (e.keyCode == 40 && direction != 'up') direction = 'down';
}
function draw() {
//refresh canvas
ctx.clearRect(0, 0, cvsW, cvsH);
//draw snake
for(let i = 0; i < snake.length; i++) {
ctx.fillStyle = 'limegreen';
ctx.fillRect(snake[i].x, snake[i].y, unit, unit);
}
//grab head position
let headX = snake[0].x;
let headY = snake[0].y;
//posistion food on board
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, unit, unit);
//send the snake in chosen direction
if(direction == 'left') headX -= unit;
else if(direction == 'up') headY -= unit;
else if(direction == 'right') headX += unit;
else if(direction == 'down') headY += unit;
// //check if snake hit wall
// if(headX < 0 || headY < 0 || headX > (cvsW-unit) || headY > (cvsH-unit)) {
// clearInterval(runGame);
// }
if (headX < 0) headX = cvsW - unit;
else if (headX > cvsW - unit) headX = 0;
else if (headY < 0) headY = cvsH - unit;
else if(headY > cvsH - unit) headY = 0;
// check to see if snake has collided with itself
// for(let i = 0; i < snake.length; i++) {
// if(headX == snake[i].x && headY == snake[i].y) {
// clearInterval(game);
// }
// }
//create new head
let newHead = {x: headX, y: headY}
//if snake eats food -do this
if(headX == food.x && headY == food.y) {
//create new food position
food = {
x : Math.floor(Math.random()*((cvsW/unit)-1)+1)*unit,
y : Math.floor(Math.random()*((cvsH/unit)-1)+1)*unit
}
//add 3 units to the snake
for (let i = 30; i > 0; i--) {
snake.unshift(newHead);
}
}
else {
//remove tail
snake.pop();
}
//add head to snake
snake.unshift(newHead);
}
//run game engine
let runGame = setInterval(draw, 40);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Snake Game</title>
<style>
body {
background-color: #333;
}
canvas {
background-color: #4d4d4d;
margin: auto;
display: block;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 750px;
height: 500px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="script.js"></script>
</body>
</html>
答案 0 :(得分:0)
您可以.map
将蛇的当前坐标转换为字符串currentSnakeX_Ys
(x#_y#
)的数组,然后生成food
x
和y
currentSnakeX_Ys.includes(`${food.x}_${food.y}`)
时:s:
//create new food position
const currentSnakeX_Ys = snake.map(({ x, y }) => `${x}_${y}`);
do {
food = {
x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
}
} while (currentSnakeX_Ys.includes(`${food.x}_${food.y}`));
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
//set canvas dimension equal to css dimension
canvas.width = 768;
canvas.height = 512;
//now put those dimensions into variables
const cvsW = canvas.width;
const cvsH = canvas.height;
//create snake unit
const unit = 16;
//create snake array
let snake = [{
x: cvsW / 2,
y: cvsH / 2
}];
//delcare global variable to hold users direction
let direction;
//create food object
let food = {
x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
}
//read user's direction
document.addEventListener('keydown', changeDirection);
function changeDirection(e) {
//set direction
if (e.keyCode == 37 && direction != 'right') direction = 'left';
else if (e.keyCode == 38 && direction != 'down') direction = 'up';
else if (e.keyCode == 39 && direction != 'left') direction = 'right';
else if (e.keyCode == 40 && direction != 'up') direction = 'down';
}
function draw() {
//refresh canvas
ctx.clearRect(0, 0, cvsW, cvsH);
//draw snake
for (let i = 0; i < snake.length; i++) {
ctx.fillStyle = 'limegreen';
ctx.fillRect(snake[i].x, snake[i].y, unit, unit);
}
//grab head position
let headX = snake[0].x;
let headY = snake[0].y;
//posistion food on board
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, unit, unit);
//send the snake in chosen direction
if (direction == 'left') headX -= unit;
else if (direction == 'up') headY -= unit;
else if (direction == 'right') headX += unit;
else if (direction == 'down') headY += unit;
// //check if snake hit wall
// if(headX < 0 || headY < 0 || headX > (cvsW-unit) || headY > (cvsH-unit)) {
// clearInterval(runGame);
// }
if (headX < 0) headX = cvsW - unit;
else if (headX > cvsW - unit) headX = 0;
else if (headY < 0) headY = cvsH - unit;
else if (headY > cvsH - unit) headY = 0;
// check to see if snake has collided with itself
// for(let i = 0; i < snake.length; i++) {
// if(headX == snake[i].x && headY == snake[i].y) {
// clearInterval(game);
// }
// }
//create new head
let newHead = {
x: headX,
y: headY
}
//if snake eats food -do this
if (headX == food.x && headY == food.y) {
//create new food position
const currentSnakeX_Ys = snake.map(({ x, y }) => `${x}_${y}`);
do {
food = {
x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
}
} while (currentSnakeX_Ys.includes(`${food.x}_${food.y}`));
//add 3 units to the snake
for (let i = 30; i > 0; i--) {
snake.unshift(newHead);
}
} else {
//remove tail
snake.pop();
}
//add head to snake
snake.unshift(newHead);
}
//run game engine
let runGame = setInterval(draw, 40);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Snake Game</title>
<style>
body {
background-color: #333;
}
canvas {
background-color: #4d4d4d;
margin: auto;
display: block;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 750px;
height: 500px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="script.js"></script>
</body>
</html>
(您也可以在每一代食物生成之后遍历snake
,并检查当前的x
和y
是否与食物的x
和{{ 1}},但是预先创建一个字符串数组会使事情变得容易得多,因为您可以仅使用y
测试)
要保持代码干燥,而不是每次需要生成食物时都将其键入,请将以上内容放入函数中,然后调用该函数:
.includes
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
//set canvas dimension equal to css dimension
canvas.width = 768;
canvas.height = 512;
//now put those dimensions into variables
const cvsW = canvas.width;
const cvsH = canvas.height;
//create snake unit
const unit = 16;
//create snake array
let snake = [{
x: cvsW / 2,
y: cvsH / 2
}];
//delcare global variable to hold users direction
let direction;
function makeFood() {
//create new food position
let newFood;
const currentSnakeX_Ys = snake.map(({ x, y }) => `${x}_${y}`);
do {
newFood = {
x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
}
} while (currentSnakeX_Ys.includes(`${newFood.x}_${newFood.y}`));
return newFood;
}
//create food object
let food = makeFood();
//read user's direction
document.addEventListener('keydown', changeDirection);
function changeDirection(e) {
//set direction
if (e.keyCode == 37 && direction != 'right') direction = 'left';
else if (e.keyCode == 38 && direction != 'down') direction = 'up';
else if (e.keyCode == 39 && direction != 'left') direction = 'right';
else if (e.keyCode == 40 && direction != 'up') direction = 'down';
}
function draw() {
//refresh canvas
ctx.clearRect(0, 0, cvsW, cvsH);
//draw snake
for (let i = 0; i < snake.length; i++) {
ctx.fillStyle = 'limegreen';
ctx.fillRect(snake[i].x, snake[i].y, unit, unit);
}
//grab head position
let headX = snake[0].x;
let headY = snake[0].y;
//posistion food on board
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, unit, unit);
//send the snake in chosen direction
if (direction == 'left') headX -= unit;
else if (direction == 'up') headY -= unit;
else if (direction == 'right') headX += unit;
else if (direction == 'down') headY += unit;
// //check if snake hit wall
// if(headX < 0 || headY < 0 || headX > (cvsW-unit) || headY > (cvsH-unit)) {
// clearInterval(runGame);
// }
if (headX < 0) headX = cvsW - unit;
else if (headX > cvsW - unit) headX = 0;
else if (headY < 0) headY = cvsH - unit;
else if (headY > cvsH - unit) headY = 0;
// check to see if snake has collided with itself
// for(let i = 0; i < snake.length; i++) {
// if(headX == snake[i].x && headY == snake[i].y) {
// clearInterval(game);
// }
// }
//create new head
let newHead = {
x: headX,
y: headY
}
//if snake eats food -do this
if (headX == food.x && headY == food.y) {
food = makeFood();
//add 3 units to the snake
for (let i = 30; i > 0; i--) {
snake.unshift(newHead);
}
} else {
//remove tail
snake.pop();
}
//add head to snake
snake.unshift(newHead);
}
//run game engine
let runGame = setInterval(draw, 40);
答案 1 :(得分:0)
声明一个为此类食物生成随机点的函数
function getFood() {
// get a random point
let food = {
x : Math.floor(Math.random()*((cvsW/unit)-1)+1)*unit,
y : Math.floor(Math.random()*((cvsH/unit)-1)+1)*unit
}
// check if this point is in the snake
// loop through each point of the snake
for(let i = 0; i < snake.length; i++) {
// check if the current snake point equals the generated point
if(snake[i].x == point.x && snake[i].y == point.x)
// stop the loop and return getFood() to generate an other point
return getFood()
}
return food
}
,只要您想获得不在蛇内的食物位置,就只需调用getFood()
food = getFood()