array.every()是否不影响数组的任何元素?

时间:2019-08-21 14:57:38

标签: javascript

所以我正在制作一个俄罗斯方块游戏,现在我试图在每个正方形都被一个Tetromino填充时清除一行。到目前为止,我可以使用该行上的every()方法确定该行是否已满。看起来像这样

function checkForPoints() {
    for(let r = 0; r < row; r++) {
        if(board[r].every(squareCheck)) {
            alert('yo');
            board[r].every(clearSquare);
        }
    }

    function squareCheck(sq) {
        if(sq !== vacant) return true;
        else return false;
    }

    function clearSquare(sq) {
        sq = vacant;
    }
}

如果该行中的每个正方形都被填满,则条件为真,在这种情况下,应继续使所有正方形变为黑色或空置。但是,这不会发生。我不知道为什么?我的every()方法可用于确定每个正方形是否都没有空缺,但是相同的方法无法将数组的元素更改为等于“黑色”或空缺吗?

// //create your globals
// const canvas = document.querySelector('#canvas');
// const ctx = canvas.getContext('2d');
// const row = 20;
// const col = 10;
// const sq = 40;
// const vacant = 'black';

// //-----------------------Why can't I initialize the tetrominos??

// //create and draw board
// let board = [];
// for(let r = 0; r < row; r++) {
// 	board[r] = [];
// 	for(let c = 0; c < col; c++) {
// 		board[r][c] = vacant;
// 		draw(c, r, board[r][c]);
// 	}
// }

// //define a function to draw to the canvas
// function draw(x, y, color) {
// 	ctx.fillStyle = color;
// 	ctx.fillRect(x * sq, y * sq, sq, sq);
// 	ctx.strokeStyle = 'white';
// 	ctx.strokeRect(x * sq, y * sq, sq, sq);
// }

// //create an object for the tetrominos 
// function Tetromino(tetromino, color) {
// 	this.tetromino = tetromino;
// 	this.color = color;
// 	this.tetrominoN = 0;
// 	this.activeTetromino = this.tetromino[this.tetrominoN];
// 	this.x = 0;
// 	this.y = 0;
// }

// //create an array for the pieces
// const pieces = [
// 	[Z, 'red'],
// 	[S, 'limegreen'],
// 	[T, 'yellow'],
// 	[O, 'blue'],
// 	[L, '#b938ff'],
// 	[I, 'cyan'],
// 	[J, 'orange']
// ]

// //create a new instance of Tetromino
// function randomPiece() {
// 	let r = Math.floor(Math.random() * pieces.length);
// 	return new Tetromino(pieces[r][0], pieces[r][1]);
// }
// let p = randomPiece();

// //draw the piece
// function drawPiece(piece) {
// 	//loop through the tetromino
// 	for(let r = 0; r < piece.length; r++) {
// 		for(let c = 0; c < piece.length; c++) {
// 			//if the tetromino index is zero skip it
// 			if(!piece[r][c]) continue;
// 			//else draw it
// 			else draw(p.x + c, p.y + r, p.color);
// 		}
// 	}
// }

// //undrawdraw the piece
// function undrawPiece(piece) {
// 	//loop through the tetromino
// 	for(let r = 0; r < piece.length; r++) {
// 		for(let c = 0; c < piece.length; c++) {
// 			//if the tetromino index is zero skip it
// 			if(!piece[r][c]) continue;
// 			//else draw it
// 			else draw(p.x + c, p.y + r, vacant);
// 		}
// 	}
// }

// drawPiece(p.activeTetromino);

// //control the piece 
// document.addEventListener('keydown', (event) => {
// 	if(event.keyCode === 37) p.moveLeft();

// 	else if (event.keyCode === 38) p.rotate();

//     else if (event.keyCode === 39) p.moveRight();

// 	else if (event.keyCode === 40) p.moveDown();

// });

// Tetromino.prototype.moveDown = function() {
// 	if(!this.collision(0, 1, this.activeTetromino)) {
// 		undrawPiece(this.activeTetromino);
// 		this.y++;
// 		drawPiece(this.activeTetromino);
// 	} else {
// 		//lock piece and generate a new one
// 		this.lock();
// 		p = randomPiece();
// 	}
// }

// Tetromino.prototype.moveLeft = function() {
// 	if(!this.collision(-1, 0, this.activeTetromino)) {
// 		undrawPiece(this.activeTetromino);
// 		this.x--;
// 		drawPiece(this.activeTetromino);
// 	}
// }

// Tetromino.prototype.moveRight = function() {
// 	if(!this.collision(1, 0, this.activeTetromino)) {
// 		undrawPiece(this.activeTetromino);
// 		this.x++;
// 		drawPiece(this.activeTetromino);
// 	}
// }

// Tetromino.prototype.rotate = function() {
// 	let nextPattern = this.tetromino[(this.tetrominoN + 1) % 4];
// 	if(!this.collision(0, 0, nextPattern)) {
// 		if(this.tetromino.length > 1) {
// 			undrawPiece(this.activeTetromino);
// 			this.tetrominoN = (this.tetrominoN + 1) % 4; // take paranthesis off
// 			this.activeTetromino = this.tetromino[this.tetrominoN];
// 			drawPiece(this.activeTetromino);
// 		}
// 	}
// }

// //create a function to check for collisions
// Tetromino.prototype.collision = function(x, y, piece) {
// 	for(let r = 0; r < piece.length; r++) {
// 		for(let c = 0; c < piece.length; c++) {
// 			//skip index if it is 0
// 			if(!piece[r][c]) continue;
// 			//create vars for the future piece position
// 			let newX = this.x + c + x;
// 			let newY = this.y + r + y;
// 			//see if new position collides with border
// 			if(newX < 0 || newX >= col || newY >= row) return true;
// 			//see if there's a locked piece on the board
// 			if(board[newY][newX] !== vacant) return true;
// 		}
// 	}
// 	return false;
// }

// Tetromino.prototype.lock = function() {
// 	for(let r = 0; r < this.activeTetromino.length; r++) {
// 		for(let c = 0; c < this.activeTetromino.length; c++) {
// 			if(!this.activeTetromino[r][c]) continue;
// 			//if piece reaches the top its gameover
// 			if(this.y + r < 0) {
// 				gameover = true;
// 				alert('Game Over!');
// 			}
// 			//lock the piece by updating the board
// 			board[this.y + r][this.x + c] = this.color;
// 		}
// 	}
// }

// let dropStart = Date.now();
// //drop the piece every 1s
// function drop() {
// 	let now = Date.now();
// 	let delta = now - dropStart;
// 	//if delta is greater than 1s drop the piece
// 	if(delta > 800) {
// 		p.moveDown();
// 		dropStart = Date.now();
// 	}
// 	requestAnimationFrame(drop);
// }

// drop();

//declare globals
const col = 10;
const row = 20;
const sq = 40;
const vacant = 'black';
const cvs = document.querySelector('#canvas');
const ctx = cvs.getContext('2d');
let gameOver = false;

//create and draw the board
let board = [];
for(let r = 0; r < row; r++) {
	board[r] = [];
	for(let c = 0; c < col; c++) {
		board[r][c] = vacant;
		draw(c, r, board[r][c]);
	}
}

//create a blueprint function to draw to the board
function draw(x, y, color) {
	//set the drawing specifications
	ctx.fillStyle = color;
	ctx.fillRect(x * sq, y * sq, sq, sq);
	ctx.strokeStyle = 'white';
	ctx.strokeRect(x * sq, y * sq, sq, sq);
}

//create a blueprint object for the tetrominos
function Piece(tetromino, color) {
	//create the properties
	this.tetromino = tetromino;
	this.color = color;
	this.tetrominoN = 0;
	this.activeTetromino = this.tetromino[this.tetrominoN];
	this.x = 0;
	this.y = -1;
	if (this.tetromino === pieces[5][0]) this.y = -2;
}

//create an array to hold all of the tetrominos
const pieces = [
	[Z, 'red'],
	[S, 'limegreen'],
	[T, 'yellow'],
	[O, 'blue'],
	[L, '#b938ff'],
	[I, 'cyan'],
	[J, 'orange']
]

function randomPiece() {
	let r = Math.floor(Math.random()*pieces.length);
	return new Piece(pieces[r][0], pieces[r][1]);
}

//grab a piece
let p = randomPiece();

//draw a piece to the board
// drawPiece(p.activeTetromino, p.color);

//create a blueprint function to draw tetrominos to the board
function drawPiece(piece, color) {
	for(let r = 0; r < piece.length; r++) {
		for(let c = 0; c < piece.length; c++) {
			if (!piece[r][c]) continue;
			draw(c + p.x, r + p.y, color);
		}
	}
}


//control the piece
document.addEventListener('keydown', (e) => {
	//check user's input
	if(e.keyCode === 37) p.moveLeft();
	else if(e.keyCode === 38) p.rotate();
	else if(e.keyCode === 39) p.moveRight();
	else if (e.keyCode === 40) p.moveDown();
});

Piece.prototype.moveDown = function() {
	if(!this.collision(0, 1, this.activeTetromino)) {
		drawPiece(this.activeTetromino, vacant);
		this.y++;
		drawPiece(this.activeTetromino, this.color);		
	} else {
		this.lockPiece(this.activeTetromino);
		checkForPoints();
		p = randomPiece();
	}
}

Piece.prototype.moveLeft = function() {
	if(!this.collision(-1, 0, this.activeTetromino)) {
		drawPiece(this.activeTetromino, vacant);
		this.x--;
		drawPiece(this.activeTetromino, this.color);
	}
}

Piece.prototype.moveRight = function() {
	if(!this.collision(1, 0, this.activeTetromino)) {
		drawPiece(this.activeTetromino, vacant);
		this.x++;
		drawPiece(this.activeTetromino, this.color);
	}
}

Piece.prototype.rotate = function() {
	let nextPattern = this.tetromino[(this.tetrominoN + 1) % 4];

	let kick = 0;
	if (this.collision(0, 0, nextPattern)) {
		if(this.x < col/2) {
			if(this.x === -2) {
				kick = 2;
			} else {
				kick = 1; //kick from right
			}
		} 
		if(this.x > col/2) {
			if(this.tetromino === pieces[5][0]) {
				kick = -2;
			} else {
				kick = -1; //kick from left
			}
		}	
	}

	if(!this.collision(kick, 0, nextPattern)) {
		drawPiece(this.activeTetromino, vacant);
		this.x += kick;
		this.tetrominoN = (this.tetrominoN + 1) % 4;
		this.activeTetromino = this.tetromino[this.tetrominoN];
		drawPiece(this.activeTetromino, this.color);
	} 
}

Piece.prototype.collision = function(x, y, piece) {
	for (let r = 0; r < piece.length; r++) {
		for(let c = 0; c < piece.length; c++) {
			if(!piece[r][c]) continue;

			let newX = this.x + c + x;
			let newY = this.y + r + y;

			if(newX < 0 || newX >= col || newY >= row) return true;
			if(board[newY][newX] !== vacant) return true;
		}
	}
	return false;
}

Piece.prototype.lockPiece = function(piece) {
	for (let r = 0; r < piece.length; r++) {
		for(let c = 0; c < piece.length; c++) {
			if(!piece[r][c]) continue;
			if(this.y + r === 1) alert('yo');
			if(this.y + r <= 0) {
				alert('Game Over');
				gameOver = true;
				break;
			}

			board[this.y + r][this.x + c] = this.color;
		}
	}
}

function checkForPoints() {
	for(let r = 0; r < row; r++) {
		if(board[r].every(squareCheck)) {
			alert('yo');
			board[r].every(clearSquare);
		}
	}

	function squareCheck(sq) {
		if(sq !== vacant) return true;
		else return false;
	}

	function clearSquare(sq) {
		sq = vacant;
	}
}

//start a time to set as a refrence for the dropstart
let dropStart = Date.now();
//create a blueprint function to drop the piece
function drop() {
	//grab the current time
	let now = Date.now();
	//create a var to hold the difference of the current time
	let delta = now - dropStart; //------Why can't these be switched------
	if(delta > 800) {
		dropStart = Date.now();
		p.moveDown();
		//------put request animation here------
	}

	if (!gameOver) requestAnimationFrame(drop);
}

drop();
<!-- <!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Tetris</title>
	<link href="https://fonts.googleapis.com/css?family=Orbitron&display=swap" rel="stylesheet">
</head>
<style>
	body {
		background-color: #595959;
		display: flex;
		justify-content: center;
		align-items: center;
		min-height: 100vh;
		overflow-y: hidden;
	}
	canvas {
		outline: 1px solid white;
	}
	.canvas-wrap {
		padding-left: 50px;
		padding-top: 50px;
		position: relative;
	}
	.num-top, .num-bottom {
		position: absolute;
		top: -1px;
		left: 0;
	}

	.num-top {
		width: 100%;
		height: 50px;
	}

	.num-bottom {
		height: 100%;
		width: 50px;
	}
	.nb {
		font-family: 'Orbitron';
		color: white;
	}
	.num-wrap-t {
		display: flex;
		justify-content: space-around;
		margin-left: 50px;
		width: 400px;
	}
	.num-wrap-b {
		display: flex;
		flex-direction: column;
		justify-content: space-around;
		margin-top: 50px;
		height: 800px;
	}
	.num-wrap-b .nb {
		text-align: right;
		margin-right: 3px;
	}

	.num-wrap-t .nb {
		position: relative;
		top: 31px;
	}
</style>
<body>
	<div class="canvas-wrap">
		<div class="num-top">
			<div class="num-wrap-t">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
			</div>
		</div>
		<canvas id="canvas" width="400" height="800"></canvas>
		<div class="num-bottom">
			<div class="num-wrap-b">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
				<div class="nb">10</div>
				<div class="nb">11</div>
				<div class="nb">12</div>
				<div class="nb">13</div>
				<div class="nb">14</div>
				<div class="nb">15</div>
				<div class="nb">16</div>
				<div class="nb">17</div>
				<div class="nb">18</div>
				<div class="nb">19</div>
			</div>
		</div>
    </div>		
	<script src="tetrominos.js"></script>
	<script src="tetris.js"></script>
</body>
</html> -->
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Tetris</title>
	<link href="https://fonts.googleapis.com/css?family=Orbitron&display=swap" rel="stylesheet">
</head>
<style>
	body, html {
		padding: 0;
		margin: 0;
	}

	body {
		background-color: #595959;
		min-height: 100vh;
		display: flex;
		justify-content: center;
		align-items: center;
	}

	canvas {
		outline: 1px solid white;
	}
	.canvas-wrap {
		padding-left: 50px;
		padding-top: 50px;
		position: relative;
	}
	.num-top, .num-bottom {
		position: absolute;
		top: -1px;
		left: 0;
	}

	.num-top {
		width: 100%;
		height: 50px;
	}

	.num-bottom {
		height: 100%;
		width: 50px;
	}
	.nb {
		font-family: 'Orbitron';
		color: white;
	}
	.num-wrap-t {
		display: flex;
		justify-content: space-around;
		margin-left: 50px;
		width: 400px;
	}
	.num-wrap-b {
		display: flex;
		flex-direction: column;
		justify-content: space-around;
		margin-top: 50px;
		height: 800px;
	}
	.num-wrap-b .nb {
		text-align: right;
		margin-right: 3px;
	}

	.num-wrap-t .nb {
		position: relative;
		top: 31px;
	}
</style>
<body>
	<div class="canvas-wrap">
		<div class="num-top">
			<div class="num-wrap-t">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
			</div>
		</div>
		<canvas id="canvas" width="400" height="800"></canvas>
		<div class="num-bottom">
			<div class="num-wrap-b">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
				<div class="nb">10</div>
				<div class="nb">11</div>
				<div class="nb">12</div>
				<div class="nb">13</div>
				<div class="nb">14</div>
				<div class="nb">15</div>
				<div class="nb">16</div>
				<div class="nb">17</div>
				<div class="nb">18</div>
				<div class="nb">19</div>
			</div>
		</div>
	</div>
	<script src="tetrominos.js"></script>		
	<script src="tetris.js"></script>
</body>
</html>

2 个答案:

答案 0 :(得分:4)

JavaScript具有call by sharing,因此如果您执行sq =,这只会影响本地sq变量,而不会影响数组中的值。您必须直接将新值分配给数组,例如board[r][i] = vacant; ...

另外,.every是错误的工具,请使用.forEachfor(let i = 0; i < board[r].length; i++),然后重新分配值。

或者可以只创建一个新数组并重新分配它:

  board[r] = new Array(board[r].length).fill(vacant);

也可以使用.map完成。

答案 1 :(得分:-2)

摘自文档:

  

every()方法测试数组中的所有元素是否通过提供的函数实现的测试。它返回一个布尔值。

传递的函数是TEST函数,我想它会在后台创建您数组元素的副本并在其上激活该函数。