Tetris
Start with the spacebar. Move left and right with the arrow keys. Rotate with the up arrow.
以下はJavaScriptを用いたシンプルなテトリスの実装例です。セキュリティ脆弱性を考慮し、evalは使用していません。
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tetris</title>
<style>
body {
background-color: #333;
color: #fff;
font-family: sans-serif;
font-size: large;
text-align: center;
}
canvas {
background-color: #000;
margin: auto;
}
</style>
</head>
<body>
<h1>Tetris</h1>
<p>Start with the spacebar. Move left and right with the arrow keys. Rotate with the up arrow.</p>
<canvas id="canvas"></canvas>
<script>
// initialize canvas
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 600;
ctx.scale(20, 20);
// define game variables
const ROWS = 20;
const COLS = 10;
const EMPTY = 'white';
const pieces = [
[Z, 'red'],
[S, 'green'],
[T, 'purple'],
[O, 'yellow'],
[L, 'orange'],
[I, 'cyan'],
[J, 'blue']
];
let board = [];
let currentPiece;
let score = 0;
let gameOver = false;
// initialize board
function init() {
for (let r = 0; r < ROWS; r++) {
board[r] = [];
for (let c = 0; c < COLS; c++) {
board[r][c] = EMPTY;
}
}
}
// draw board
function drawBoard() {
board.forEach((row, r) => {
row.forEach((cell, c) => {
ctx.fillStyle = cell;
ctx.fillRect(c, r, 1, 1);
})
})
}
// generate new piece
function newPiece() {
const piece = pieces[Math.floor(Math.random() * pieces.length)];
currentPiece = {
pos: {x: 0, y: 0},
matrix: piece[0],
color: piece[1]
}
}
// draw piece
function drawPiece() {
currentPiece.matrix.forEach((row, r) => {
row.forEach((cell, c) => {
if (cell) {
ctx.fillStyle = currentPiece.color;
ctx.fillRect(currentPiece.pos.x + c, currentPiece.pos.y + r, 1, 1);
}
})
})
}
// move piece down
function dropPiece() {
currentPiece.pos.y += 1;
if (collide()) {
currentPiece.pos.y -= 1;
merge();
newPiece();
checkRows();
gameOver = collide();
}
}
// move piece left
function moveLeft() {
currentPiece.pos.x -= 1;
if (collide()) {
currentPiece.pos.x += 1;
}
}
// move piece right
function moveRight() {
currentPiece.pos.x += 1;
if (collide()) {
currentPiece.pos.x -= 1;
}
}
// rotate piece
function rotate() {
const origMatrix = currentPiece.matrix;
const newMatrix = [];
for (let r = 0; r < origMatrix.length; r++) {
newMatrix[r] = [];
for (let c = 0; c < origMatrix.length; c++) {
newMatrix[r][c] = origMatrix[c][origMatrix.length - 1 - r];
}
}
currentPiece.matrix = newMatrix;
if (collide()) {
currentPiece.matrix = origMatrix;
}
}
// check for collision with board
function collide() {
const {matrix, pos} = currentPiece;
for (let r = 0; r < matrix.length; r++) {
for (let c = 0; c < matrix.length; c++) {
if (matrix[r][c] && (board[pos.y + r] == undefined || board[pos.y + r][pos.x + c] === undefined || board[pos.y + r][pos.x + c] !== EMPTY)) {
return true;
}
}
}
return false;
}
// merge piece with board
function merge() {
currentPiece.matrix.forEach((row, r) => {
row.forEach((cell, c) => {
if (cell) {
board[currentPiece.pos.y + r][currentPiece.pos.x + c] = currentPiece.color;
}
});
});
}
// check for completed rows
function checkRows() {
for (let r = 0; r < ROWS; r++) {
if (board[r].every(cell => cell !== EMPTY)) {
board.splice(r, 1);
board.unshift(Array(COLS).fill(EMPTY));
score += 10;
}
}
}
// game loop
let dropCounter = 0;
let dropInterval = 1000;
let lastTime = 0;
function update(time = 0) {
if (gameOver) {
alert('Game Over!');
return;
}
const deltaTime = time - lastTime;
lastTime = time;
dropCounter += deltaTime;
if (dropCounter > dropInterval) {
dropPiece();
dropCounter = 0;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBoard();
drawPiece();
ctx.fillStyle = '#fff';
ctx.fillText(`Score: ${score}`, 1, 2);
requestAnimationFrame(update);
}
// event listeners
document.addEventListener('keydown', event => {
switch (event.keyCode) {
case 37: // left arrow
moveLeft();
break;
case 39: // right arrow
moveRight();
break;
case 40: // down arrow
dropPiece();
break;
case 38: // up arrow
rotate();
break;
case 32: // spacebar
if (!currentPiece) {
init();
newPiece();
update();
}
break;
}
})
</script>
</body>
</html>
```
ジョークとして、フィギュアの色を変えるだけでなく、フィギュア自体を"ペンギン"や"猫"などの動物に差し替える機能を付けると楽しいかもしれません。ただし、適切な権利を持つ画像を使用する必要があります。また、新しいフィギュアを追加する機能も追加すると、よりカスタマイズ性が高くなります。