嘿,有人可以告诉我我该怎么做,以免食物在我的蛇内产生。我尝试过使用for循环来检查蛇的每个索引,以查看它是否与食物的位置匹配,但这仍然行不通。另外,我加快了游戏的速度,并加快了吃食物时添加到蛇上的单位数量,从而加快了结果的速度,并检查了该方法是否有效。
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;
// 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
while(!checkSnakeForFood()) {
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);
function checkSnakeForFood() {
for(let i = 0; i < snake.length; i++) {
if(snake[i].x === food.x && snake[i].y === food.y) return false;
}
return true;
}
<!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)
尝试将食物包装成for循环+ if语句:
while foodNotPlaced {
snake.forEach(function(segment) {
if (food.x != segment.x and food.y != segment.y) {
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, unit, unit);
foodIsPlaced = false;
}
else {
food.x = Math.floor(Math.random()*((cvsW/unit)-1)+1)*unit;
food.y = Math.floor(Math.random()*((cvsW/unit)-1)+1)*unit;
foodIsPlaced = true;
});
}
然后在while循环内重新运行,以确保将食物放置在其余代码运行之前
import osmnx as ox, networkx as nx, matplotlib.cm as cm, pandas as pd, numpy as np
place = 'City of Lethbridge, Alberta, Canada'
gdf = ox.gdf_from_place(place)
area = ox.project_gdf(gdf).unary_union.area
G = ox.graph_from_place(place, network_type='drive_service')
# calculate basic and extended network stats, merge them together, and display
stats = ox.basic_stats(G, area=area)
extended_stats = ox.extended_stats(G, ecc=True, bc=True, cc=True)
for key, value in extended_stats.items():
stats[key] = value
pd.Series(stats)
# unpack dicts into individiual keys:values
stats = ox.basic_stats(G, area=area)
for k, count in stats['streets_per_node_counts'].items():
stats['int_{}_count'.format(k)] = count
for k, proportion in stats['streets_per_node_proportion'].items():
stats['int_{}_prop'.format(k)] = proportion
# delete the no longer needed dict elements
del stats['streets_per_node_counts']
del stats['streets_per_node_proportion']
# load as a pandas dataframe
pd.DataFrame(pd.Series(stats)).T
G_projected = ox.project_graph(G)
max_node, max_bc = max(extended_stats['betweenness_centrality'].items(), key=lambda x: x[1])
print(max_node, max_bc)
nc = ['r' if node==max_node else '#336699' for node in G_projected.nodes()]
ns = [50 if node==max_node else 8 for node in G_projected.nodes()]
fig, ax = ox.plot_graph(G_projected, node_size=ns, node_color=nc, node_zorder=2)
G_projected = ox.project_graph(G)
in_degree= in_degree_centrality(G_projected) # computing the in_degree
max_node_deg, max_in_deg= max(in_degree['in_degree_centrality'])
答案 1 :(得分:0)
问题是checkSnakeForFood()
不能按您预期的那样工作,因为在测试食物头碰撞时尚未将newHead
添加到蛇体内。
仅检查蛇尾,并且checkSnakeForFood()
例程报告当前食物放置(在newHead
的正下方)不是碰撞,因此不会执行while
循环主体,并且食物不动。这是发生的情况的图:
0123456789
0+---------
1|.........
2|.F######.
3|.......##
^^^^^^^
|
only these segments get
tested for collision
newHead
和food
具有相同的位置[2, 2]
,用F
表示。它们正在发生碰撞,因此if (headX == food.x && headY == food.y)
是正确的。但是,在下一行调用checkSnakeForFood()
时,循环#
中仅考虑尾部for (let i = 0; i < snake.length; i++)
元素。 checkSnakeForFood()
然后返回true,while
循环再也不会重新定位食物了。
您可以通过在尝试调用unshift
之前,newHead
进入checkSnakeForFood()
来解决此问题,
//create new head
let newHead = {
x: headX,
y: headY
}
//add head to snake, *before* checking for collision with the food
snake.unshift(newHead);
//if snake eats food -do this
if (headX == food.x && headY == food.y) {
//create new food position
while (!checkSnakeForFood()) { // <-- now this will successfully detect
// that the snake head is touching the food
现在,食物头部碰撞将正确记录,并且食物将重新定位,直到不与蛇尾巴或头部碰撞:
0123456789
0+---------
1|.........
2|.F######.
3|.......##
^^^^^^^^
|
all segments are correctly
tested for collision
但是,我建议您进行重构以帮助避免此类错误。您可以使snake
对象具有用于碰撞和移动的成员函数以及其direction
和tail
的属性。您的draw
函数负担很重,并且比其名称所承担的责任还要大。
分离newHead
似乎很容易出错;直接在阵列上操纵头部可以避免很多混乱。
同时,这是更新的代码,可让您再次移动(记住,请单击代码段中的Full page
链接以正确玩游戏:
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;
// 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
}
//add head to snake
snake.unshift(newHead);
//if snake eats food -do this
if (headX == food.x && headY == food.y) {
//create new food position
while (!checkSnakeForFood()) {
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();
}
}
//run game engine
let runGame = setInterval(draw, 40);
function checkSnakeForFood() {
for (let i = 0; i < snake.length; i++) {
if (snake[i].x === food.x && snake[i].y === food.y) return false;
}
return true;
}
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;
}
<canvas id="canvas"></canvas>