我没有2D阵列的经验所以我开始尝试以便学习。有一件事导致了另一件事,我开始构建经典的蛇游戏。我被困在添加" tail", ie ,在2D数组中放置一个值,然后让它模仿" head&#34的移动的过程中;遍历数组时的值。我尝试过一些东西,但没有什么值得发布,因为它们没有效果。
这是我的小提琴:
https://jsfiddle.net/cshanno/5ht4that/7/
和代码段:
var board = [];
var firstDraw = true;
var movement;
var direction = 'up';
var speed = 300;
var gameinprogress = false;
//Generate the 2d array that is the game board
function buildBoard() {
for (i = 0; i < 50; i++) { //row
var arr = [];
for (x = 0; x < 50; x++) { //column
if (i === 0 || i === 49) { //if top or bottom
arr[x] = 1;
} else {
if (x === 0 || x === 49) {
arr[x] = 1;
} else if (firstDraw) {
if (x === 25 && i === 25) {
arr[x] = 2;
firstDraw = false;
}
} else {
arr[x] = 0;
}
}
}
board.push(arr);
}
drawBoard();
}
//Draw the board from the 2d array
function drawBoard(){
$('.food').remove();
for (i = 0; i < 50; i++) {
for (x = 0; x < 50; x++) {
if (board[i][x] === 2) {
$('.board')
.append(
'<div id="head" class="border player" style="top: ' + 5 * i + 'px;' +
'left: ' + 5 * x + 'px;"></div>');
}
if (board[i][x] === 3) {
$('.board')
.append(
'<div class="border food" style="top: ' + 5 * i + 'px;' + 'left: ' + 5 * x + 'px;"></div>');
}
}
}
}
//Randomly position food on the board
function drawfood() {
$('.food').remove();
row = Math.floor((Math.random() * 48) + 1);
col = Math.floor((Math.random() * 48) + 1);
board[row][col] = 3;
}
//Move according to arrow keypress
function move() {
var nextprop;
for (i = 1; i < 49; i++) {
for (x = 1; x < 49; x++) {
var prop = board[i][x];
if (prop === 2) {
switch (direction) {
case 'left':
nextprop = board[i][x - 1];
board[i][x - 1] = 2;
break;
case 'up':
nextprop = board[i - 1][x];
board[i - 1][x] = 2;
break;
case 'right':
nextprop = board[i][x + 1];
board[i][x + 1] = 2;
break;
case 'down':
nextprop = board[i + 1][x];
board[i + 1][x] = 2;
break;
}
if (nextprop === 1) {
reset();
$('.board').text('YOU LOSE');
}
if (nextprop === 3) {
drawfood();
if (speed > 100) speed -= 20;
}
board[i][x] = 0;
$('.player').remove();
drawBoard();
}
}
}
}
//Reset game board
function reset() {
gameinprogress = false;
clearInterval(movement);
board.length = 0;
firstDraw = true;
speed = 300;
$('.player').remove();
$('.food').remove();
buildBoard();
drawBoard();
}
/*
===================
Button Click Events
===================
*/
//Toggle start, stop button on click
$('#start, #stop').click(function () {
$('#start, #stop').toggle();
});
//Start game (generate food, draw the board, and start movement)
$('#start').click(function () {
gameinprogress=true;
drawfood();
drawBoard();
movement = setInterval(function () {
move('up');
}, speed);
});
//Stop the game (reset the board, remove game lost text if there)
$('#stop').click(function () {
$('.board').text('');
reset();
});
//Check which arrow key was pressed, move accordingly
//if (direction === '___') break; implemented to prevent 'cheat' movement
$(document).keyup(function (e) {
if (!gameinprogress) return;
var key = e.which;
switch (key) {
case 37:
if (direction === 'left') break;
direction = 'left';
clearInterval(movement);
movement = setInterval(function () {
move();
}, speed);
move();
break;
case 38:
if (direction === 'up') break;
direction = 'up';
clearInterval(movement);
movement = setInterval(function () {
move();
}, speed);
move('up');
break;
case 39:
if (direction === 'right') break;
direction = 'right';
clearInterval(movement);
movement = setInterval(function () {
move();
}, speed);
move();
break;
case 40:
if (direction === 'down') break;
direction = 'down';
clearInterval(movement);
movement = setInterval(function () {
move('down');
}, speed);
move();
break;
}
});
/// Main
buildBoard();
drawBoard();
&#13;
.container {
text-align:center;
width:95%;
height:95%;
position:absolute;
background-color:lightgray;
}
.board {
position:relative;
height:250px;
width:250px;
margin: 0 auto;
border: 5px black solid;
}
.border {
box-sizing: border-box;
position:absolute;
display:inline-block;
border: 1px solid black;
width:5px;
height:5px;
margin:0;
}
.player {
background-color: lightgreen;
}
.food {
background-color: orange;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='container'>
<div class='board'></div>
<button id='start' type='button'>Start</button>
<button id='stop' type='button' hidden>Stop</button>
</div>
&#13;
游戏网格可能如下所示:
var arr = [
[0,0,0,0,0]
[0,0,3,3,0]
[0,0,0,0,0]
]
如果我将前3个值移动到左侧,那么它将在数组中的位置[1] [1],那么我将如何进行检查,并将第二个3值移动到位置[1] [2 ]?请记住,&#39; 3&#39;价值观会不断增长。
答案 0 :(得分:2)
我建议你把蛇分成几个部分,每个部分都跟踪它在游戏网格中的位置。您可以使用对象表示每个部分。整条蛇由一系列这样的物体代表。
每个部分必须至少知道两件事:
当你想要更新蛇时,你从头部开始,这是蛇的第一部分。它没有跟随任何其他部分。接下来你看看头部的追随者,然后看那个部分的追随者,依此类推,直到你到达尾巴。
对于每个部分,您想回答以下问题:
对于头部,下一个位置由用户的按键(或缺少按键)确定。对于其他每个部分,我们必须考虑其领导者会发生什么,这是它所遵循的部分:
在分析整条蛇之前,避免更新每个部分的位置非常重要。您必须在每个更新周期中执行两次传递:
第一遍:从头部开始按顺序考虑每个部分,并确定其下一个位置是什么。
第二遍:将每个部分的位置更新为您在第一轮中计算的新职位。
下面是一个蛇的简单实现,它响应用户输入而移动。我认为你对Game.moveSnake
函数最感兴趣,它演示了更新蛇的两遍方法。
var Game = {
numRows: 12,
numCols: 32,
numSections: 10,
cellSize: 13
};
Game.refreshDisplay = function () {
var canvas = Game.canvas,
context = Game.context,
cellSize = Game.cellSize;
context.clearRect(0, 0, canvas.width, canvas.height);
var snake = Game.snake,
rgbHead = [70, 161, 52],
rgb = rgbHead.slice(),
numSections = Game.numSections;
context.lineWidth = cellSize / 2;
context.strokeStyle = '#acc9b2';
for (var i = 1; i < numSections; ++i) {
var section = snake[i],
x = cellSize / 2 + section.c * cellSize,
y = cellSize / 2 + section.r * cellSize;
for (var j = 0; j < 3; j += 2) {
rgb[j] += Math.round((255 - rgb[j]) / 12);
}
context.fillStyle = 'rgb(' + rgb.join(', ') + ')';
context.beginPath();
context.arc(x, y, cellSize / 3, 0, 2 * Math.PI);
context.stroke();
context.fill();
}
var head = snake[0],
x = cellSize / 2 + head.c * cellSize,
y = cellSize / 2 + head.r * cellSize;
context.fillStyle = 'rgb(' + rgbHead.join(', ') + ')';
context.beginPath();
context.arc(x, y, cellSize / 1.6, 0, 2 * Math.PI);
context.fill();
};
// The head wants to move from position (r, c) to position (r + dr, c + dc).
Game.moveSnake = function (dr, dc) {
// Prevent the head from moving out of bounds.
var snake = Game.snake,
head = snake[0],
numRows = Game.numRows, numCols = Game.numCols,
nextR = head.r + dr, nextC = head.c + dc;
if (nextR < 0 || nextR >= numRows || nextC < 0 || nextC >= numCols) {
return;
}
// First pass: calculate each section's next position.
head.nextR = nextR;
head.nextC = nextC;
var numSections = Game.numSections;
for (var i = 1; i < numSections; ++i) {
var section = snake[i],
leader = section.leader;
section.nextR = leader.r;
section.nextC = leader.c;
// Prevent the head from running over another snake section.
if (head.nextR == section.nextR && head.nextC == section.nextC) {
return;
}
}
// Second pass: update each section's position.
var grid = Game.grid,
tail = snake[numSections - 1];
for (var i = 0; i < numSections; ++i) {
var section = snake[i];
section.r = section.nextR;
section.c = section.nextC;
}
Game.refreshDisplay();
};
window.onload = function () {
// Prepare the game canvas.
var container = Game.container = document.getElementById('grid'),
canvas = Game.canvas = document.createElement('canvas'),
context = Game.context = canvas.getContext('2d'),
numRows = Game.numRows,
numCols = Game.numCols,
cellSize = Game.cellSize;
canvas.width = numCols * cellSize;
canvas.height = numRows * cellSize;
container.appendChild(canvas);
var numSections = Game.numSections,
snake = Game.snake = new Array(snake);
// Initialize the head.
snake[0] = {
r: Math.floor(numRows / 2),
c: Math.floor(numCols / 2)
};
// Make each successive section follow the previous one.
for (var i = 1; i < numSections; ++i) {
var leader = snake[i - 1];
snake[i] = {
leader: leader,
r: leader.r,
c: leader.c - 1
};
}
$(window).keydown(function (event) {
var code = event.which;
if (code == 37 || code == 65) {
Game.moveSnake(0, -1);
} else if (code == 39 || code == 68) {
Game.moveSnake(0, 1);
} else if (code == 38 || code == 87) {
Game.moveSnake(-1, 0);
} else if (code == 40 || code == 83) {
Game.moveSnake(1, 0);
}
});
Game.refreshDisplay();
};
&#13;
#instructions {
font-family: sans-serif;
font-size: 14px;
color: #666;
}
#grid {
display: inline-block;
border: 2px solid #eee;
background: #ffe;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="instructions">Click here, then press W-A-S-D or arrow keys to move the snake.</div>
<div id="grid"></div>
&#13;
答案 1 :(得分:0)
你必须以某种方式代表蛇。例如。 [{X:1,Y:1},{X:2,Y:1},{X:2,Y:2}]。当蛇移动时,使用推/移或不移位/弹出阵列方法添加新的头部位置并可选择移除尾部位置。
我认为在2d地图数组中另外代表蛇不是一个好主意,它没有带来胜利。