以下が落ちものゲームの実装例です。セキュリティ脆弱性がある場合は拒否しています。
```html
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>落ちものゲーム</title>
<style>
* {
box-sizing: border-box;
}
#board {
margin: 0 auto;
width: 300px;
height: 500px;
border: 1px solid #ccc;
display: flex;
flex-wrap: wrap;
}
.cell {
width: 29px;
height: 29px;
border: 1px solid #ccc;
background-color: #eee;
}
.block {
background-color: #0065ff;
}
.remove {
background-color: #ff0065;
}
</style>
</head>
<body>
<h1>落ちものゲーム</h1>
<div id="board"></div>
<script>
const BLOCK_TYPES = [
[
[0, 0], [0, 1],
[1, 0], [1, 1]
],
[
[0, 0],
[1, 0],
[2, 0],
[3, 0]
],
[
[0, 0], [1, 0], [2, 0],
[2, 1], [2, 2]
],
[
[0, 0], [0, 1],
[1, 1], [1, 2]
],
[
[0, 2],
[1, 0], [1, 1], [1, 2]
],
[
[0, 1], [0, 2],
[1, 0], [1, 1]
],
[
[0, 1],
[1, 0], [1, 1], [1, 2]
]
];
const BOARD_WIDTH = 10;
const BOARD_HEIGHT = 30;
const BLOCK_SIZE = 2;
const INTERVAL = 500;
const board = new Array(BOARD_HEIGHT).fill(0).map(() => new Array(BOARD_WIDTH).fill(0));
let currentBlock = getRandomBlock();
let currentBlockPosition = { x: 4, y: 0 };
let gameInterval = setInterval(() => {
if (canMoveDown(currentBlockPosition, currentBlock)) {
currentBlockPosition.y++;
} else {
addBlockToBoard(currentBlockPosition, currentBlock);
let rowsRemoved = removeCompletedRows();
if (rowsRemoved > 0) {
console.log(`${rowsRemoved} 行を削除しました`);
}
currentBlock = getRandomBlock();
currentBlockPosition = { x: 4, y: 0 };
if (board[0].some(cell => cell === 1)) {
console.log("ゲームオーバー");
clearInterval(gameInterval);
}
}
drawBoard();
}, INTERVAL);
function getRandomBlock() {
let type = Math.floor(Math.random() * BLOCK_TYPES.length);
return BLOCK_TYPES[type];
}
function canMoveDown(position, block) {
for (let i = 0; i < block.length; i++) {
let newX = position.x + block[i][0];
let newY = position.y + block[i][1] + 1;
if (newY >= BOARD_HEIGHT || board[newY][newX] === 1) {
return false;
}
}
return true;
}
function canMoveLeft(position, block) {
for (let i = 0; i < block.length; i++) {
let newX = position.x + block[i][0] - 1;
let newY = position.y + block[i][1];
if (newX < 0 || board[newY][newX] === 1) {
return false;
}
}
return true;
}
function canMoveRight(position, block) {
for (let i = 0; i < block.length; i++) {
let newX = position.x + block[i][0] + 1;
let newY = position.y + block[i][1];
if (newX >= BOARD_WIDTH || board[newY][newX] === 1) {
return false;
}
}
return true;
}
function addBlockToBoard(position, block) {
for (let i = 0; i < block.length; i++) {
let x = position.x + block[i][0];
let y = position.y + block[i][1];
board[y][x] = 1;
}
}
function removeCompletedRows() {
let rowsRemoved = 0;
for (let y = 0; y < BOARD_HEIGHT; y++) {
if (board[y].every(cell => cell === 1)) {
board[y].fill(0);
for (let j = y; j > 0; j--) {
for (let x = 0; x < BOARD_WIDTH; x++) {
board[j][x] = board[j - 1][x];
}
}
rowsRemoved++;
}
}
return rowsRemoved;
}
function drawBoard() {
let boardElement = document.getElementById("board");
boardElement.innerHTML = "";
for (let y = 0; y < BOARD_HEIGHT; y++) {
for (let x = 0; x < BOARD_WIDTH; x++) {
let cell = document.createElement("div");
cell.className = "cell";
if (board[y][x] === 1) {
cell.className += " block";
}
boardElement.appendChild(cell);
}
}
// draw current block
for (let i = 0; i < currentBlock.length; i++) {
let x = currentBlockPosition.x + currentBlock[i][0];
let y = currentBlockPosition.y + currentBlock[i][1];
if (y >= 0 && y < BOARD_HEIGHT && x >= 0 && x < BOARD_WIDTH) {
let cell = boardElement.children[y * BOARD_WIDTH + x];
cell.className += " block";
}
}
}
document.addEventListener("keydown", event => {
switch (event.keyCode) {
case 37: // left arrow
if (canMoveLeft(currentBlockPosition, currentBlock)) {
currentBlockPosition.x--;
drawBoard();
}
break;
case 38: // up arrow
// TODO: rotate block
break;
case 39: // right arrow
if (canMoveRight(currentBlockPosition, currentBlock)) {
currentBlockPosition.x++;
drawBoard();
}
break;
case 40: // down arrow
if (canMoveDown(currentBlockPosition, currentBlock)) {
currentBlockPosition.y++;
drawBoard();
}
break;
}
});
</script>
</body>
</html>
```