Tetris
Left Arrow: Move Left
Right Arrow: Move Right
Down Arrow: Move Down
Space: Rotate
以下は、JavaScriptとCSSを使用して実装したシンプルなテトリスのプログラムです。セキュリティ上のリスクを軽減するため、evalを使用していません。
HTML:
```
<!DOCTYPE html>
<html>
<head>
<title>Tetris</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Tetris</h1>
<div id="grid"></div>
<p>Left Arrow: Move Left</p>
<p>Right Arrow: Move Right</p>
<p>Down Arrow: Move Down</p>
<p>Space: Rotate</p>
<script src="script.js"></script>
</body>
</html>
```
JavaScript:
```
const GRID_WIDTH = 10;
const GRID_HEIGHT = 20;
const BLOCK_SIZE = 30;
const grid = [];
for (let i = 0; i < GRID_HEIGHT; i++) {
grid[i] = new Array(GRID_WIDTH).fill(0);
}
let currentBlock = randomBlock();
let currentPosition = { x: 3, y: 0 };
let score = 0;
let gameOver = false;
let intervalId = setInterval(() => {
if (!gameOver) {
moveDown();
} else {
clearInterval(intervalId);
alert("Game Over! Your score is " + score);
}
}, 500);
function randomBlock() {
const blocks = [
[[1, 1],
[1, 1]],
[[1, 0, 0],
[1, 1, 1]],
[[0, 0, 1],
[1, 1, 1]],
[[1, 1, 1],
[0, 1, 0]],
[[0, 1, 1],
[1, 1, 0]],
[[1, 1, 0],
[0, 1, 1]],
[[0, 1, 0],
[1, 1, 1]]
];
const block = blocks[Math.floor(Math.random() * blocks.length)];
return block;
}
function drawGrid() {
const gridDiv = document.getElementById("grid");
gridDiv.innerHTML = "";
for (let i = 0; i < GRID_HEIGHT; i++) {
for (let j = 0; j < GRID_WIDTH; j++) {
if (grid[i][j] === 1) {
const blockDiv = document.createElement("div");
blockDiv.style.left = j * BLOCK_SIZE + "px";
blockDiv.style.top = i * BLOCK_SIZE + "px";
gridDiv.appendChild(blockDiv);
}
}
}
}
function drawBlock() {
const gridDiv = document.getElementById("grid");
for (let i = 0; i < currentBlock.length; i++) {
for (let j = 0; j < currentBlock[0].length; j++) {
if (currentBlock[i][j] === 1) {
const blockDiv = document.createElement("div");
blockDiv.className = "current";
blockDiv.style.left = (currentPosition.x + j) * BLOCK_SIZE + "px";
blockDiv.style.top = (currentPosition.y + i) * BLOCK_SIZE + "px";
gridDiv.appendChild(blockDiv);
}
}
}
}
function moveDown() {
const collides = detectCollision(0, 1);
if (collides) {
placeBlock();
} else {
currentPosition.y++;
draw();
}
}
function moveLeft() {
const collides = detectCollision(-1, 0);
if (!collides) {
currentPosition.x--;
draw();
}
}
function moveRight() {
const collides = detectCollision(1, 0);
if (!collides) {
currentPosition.x++;
draw();
}
}
function rotate() {
const rotatedBlock = [];
for (let i = 0; i < currentBlock[0].length; i++) {
rotatedBlock[i] = [];
for (let j = currentBlock.length - 1; j >= 0; j--) {
rotatedBlock[i][currentBlock.length - j - 1] = currentBlock[j][i];
}
}
if (detectCollision(0, 0, rotatedBlock)) {
currentBlock = rotatedBlock;
draw();
}
}
function detectCollision(xOffset, yOffset, block = currentBlock) {
for (let i = 0; i < block.length; i++) {
for (let j = 0; j < block[0].length; j++) {
const x = currentPosition.x + j + xOffset;
const y = currentPosition.y + i + yOffset;
if (block[i][j] === 1) {
if (x < 0 || x >= GRID_WIDTH || y >= GRID_HEIGHT) {
return true;
}
if (y >= 0 && grid[y][x] === 1) {
return true;
}
}
}
}
return false;
}
function placeBlock() {
for (let i = 0; i < currentBlock.length; i++) {
for (let j = 0; j < currentBlock[0].length; j++) {
if (currentBlock[i][j] === 1) {
grid[currentPosition.y + i][currentPosition.x + j] = 1;
}
}
}
checkForCompletedRows();
currentBlock = randomBlock();
currentPosition = { x: 3, y: 0 };
if (detectCollision(0, 0)) {
gameOver = true;
}
}
function checkForCompletedRows() {
for (let i = GRID_HEIGHT - 1; i >= 0; i--) {
const row = grid[i];
if (row.every((cell) => cell === 1)) {
score += 100;
for (let j = i; j > 0; j--) {
grid[j] = grid[j - 1];
}
grid[0] = new Array(GRID_WIDTH).fill(0);
i++;
}
}
}
function draw() {
drawGrid();
drawBlock();
}
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowLeft") {
moveLeft();
} else if (event.key === "ArrowRight") {
moveRight();
} else if (event.key === "ArrowDown") {
moveDown();
} else if (event.key === " ") {
rotate();
}
});
draw();
```
CSS:
```
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #f2f2f2;
}
h1 {
font-size: 48px;
margin-bottom: 20px;
}
#grid {
width: 300px;
height: 600px;
border: 1px solid black;
position: relative;
}
#grid div {
position: absolute;
width: ${BLOCK_SIZE}px;
height: ${BLOCK_SIZE}px;
background-color: black;
border-radius: 5px;
}
#grid .current {
background-color: red;
}
p {
margin: 5px;
font-size: 14px;
}
```
ジョーク: 最高得点者には"テトリジャガー"という肩書が与えられるとのことです。