Tetris
Use arrow keys to move, Space to rotate.
以下、基本的なテトリスの実装例です。セキュリティに配慮して、evalや他のサイトへの遷移やリダイレクトは行わないようにします。 ``` <!DOCTYPE html> <html> <head> <title>Tetris</title> <style type="text/css"> canvas { border: 1px solid black; } </style> </head> <body> <h1>Tetris</h1> <p>Use arrow keys to move, Space to rotate.</p> <canvas id="canvas" width="200" height="400"></canvas> <script type="text/javascript"> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var blockWidth = 20; // ブロックの幅 var blockCountX = 10; // X方向のブロック数 var blockCountY = 20; // Y方向のブロック数 // ブロックの種類と色 var blocks = [ {color: "#00ffff", pattern: [[1,1],[1,1]]}, {color: "#ffaa00", pattern: [[1,1,1],[0,1,0]]}, {color: "#aaff00", pattern: [[1,1,1],[1,0,0]]}, {color: "#ff00ff", pattern: [[1,1,0],[0,1,1]]}, {color: "#0000ff", pattern: [[0,1,1],[1,1,0]]}, {color: "#ff0000", pattern: [[1,1,1,1]]} ]; var currentBlock; // 現在のブロック var currentBlockX; // 現在のブロックのX座標 var currentBlockY; // 現在のブロックのY座標 var currentBlockRotation; // 現在のブロックの回転数 var score = 0; // スコア // ボードを初期化する var board = []; for (var y = 0; y < blockCountY; y++) { board[y] = []; for (var x = 0; x < blockCountX; x++) { board[y][x] = ""; } } // ブロックを新しく生成する function newBlock() { var index = Math.floor(Math.random() * blocks.length); currentBlock = blocks[index]; currentBlockX = Math.floor((blockCountX - currentBlock.pattern[0].length) / 2); currentBlockY = 0; currentBlockRotation = 0; } // ボードを描画する function drawBoard() { for (var y = 0; y < blockCountY; y++) { for (var x = 0; x < blockCountX; x++) { if (board[y][x]) { drawBlock(x, y, board[y][x]); } } } } // ブロックを描画する function drawBlock(x, y, color) { ctx.fillStyle = color; ctx.fillRect(x * blockWidth, y * blockWidth, blockWidth, blockWidth); } // ブロックを落とす function dropBlock() { currentBlockY++; if (collide()) { currentBlockY--; placeBlock(); newBlock(); } draw(); } // 左に移動する function moveLeft() { currentBlockX--; if (collide()) { currentBlockX++; } draw(); } // 右に移動する function moveRight() { currentBlockX++; if (collide()) { currentBlockX--; } draw(); } // 回転する function rotate() { var newRotation = currentBlockRotation + 1; if (newRotation >= currentBlock.pattern.length) { newRotation = 0; } var newPattern = currentBlock.pattern[newRotation]; if (canMove(currentBlockX, currentBlockY, newPattern)) { currentBlockRotation = newRotation; } draw(); } // 衝突判定を行う function collide() { var pattern = currentBlock.pattern[currentBlockRotation]; for (var y = 0; y < pattern.length; y++) { for (var x = 0; x < pattern[y].length; x++) { if (pattern[y][x]) { var boardX = currentBlockX + x; var boardY = currentBlockY + y; if (boardY >= blockCountY || boardX < 0 || boardX >= blockCountX || boardY < 0 || board[boardY][boardX]) { return true; } } } } return false; } // ブロックを置く function placeBlock() { var pattern = currentBlock.pattern[currentBlockRotation]; for (var y = 0; y < pattern.length; y++) { for (var x = 0; x < pattern[y].length; x++) { if (pattern[y][x]) { board[currentBlockY + y][currentBlockX + x] = currentBlock.color; } } } // 行が揃っているかチェックして、揃っている行を消す for (var y = blockCountY - 1; y >= 0; y--) { var fullRow = true; for (var x = 0; x < blockCountX; x++) { if (!board[y][x]) { fullRow = false; break; } } if (fullRow) { for (var x = 0; x < blockCountX; x++) { board[y][x] = ""; } score += 100; y++; // 上の行を下にずらす for (var y2 = y - 1; y2 >= 0; y2--) { for (var x = 0; x < blockCountX; x++) { board[y2 + 1][x] = board[y2][x]; board[y2][x] = ""; } } } } } // 移動可能かチェックする function canMove(newX, newY, newPattern) { var pattern = newPattern; for (var y = 0; y < pattern.length; y++) { for (var x = 0; x < pattern[y].length; x++) { if (pattern[y][x]) { var boardX = newX + x; var boardY = newY + y; if (boardY >= blockCountY || boardX < 0 || boardX >= blockCountX || boardY < 0 || board[boardY][boardX]) { return false; } } } } return true; } // 描画する function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawBoard(); drawBlock(currentBlockX, currentBlockY, currentBlock.color); var pattern = currentBlock.pattern[currentBlockRotation]; for (var y = 0; y < pattern.length; y++) { for (var x = 0; x < pattern[y].length; x++) { if (pattern[y][x]) { drawBlock(currentBlockX + x, currentBlockY + y, currentBlock.color); } } } ctx.fillStyle = "black"; ctx.font = "20px Arial"; ctx.fillText("Score: " + score, 10, 25); } newBlock(); draw(); // キーイベントの処理 document.addEventListener("keydown", function(event) { switch (event.keyCode) { case 37: // left arrow moveLeft(); break; case 39: // right arrow moveRight(); break; case 40: // down arrow dropBlock(); break; case 32: // space rotate(); break; } }); </script> </body> </html> ``` ジョークを取り入れて、最初に「Hey, it's dangerous out there! Take this!」というセリフを入れると、リンク先が危険であることを示唆しつつ、実際には単なるテトリスであることを伝えることができます。