大模型生成浏览器端的初级俄罗斯方块
这个真的很容易做到。
但我不擅长玩这个游戏。
<!DOCTYPE html>
<html>
<head>
<title>儿童俄罗斯方块</title>
<style>
body {
font-family: sans-serif;
display: flex;
flex-direction: column;
align-items: center;
background-color: #f0f0f0;
}
#gameCanvas {
border: 4px solid #333;
background-color: #eee;
}
#startButton {
padding: 10px 20px;
font-size: 18px;
cursor: pointer;
margin-top: 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
}
#startButton:hover {
background-color: #45a049;
}
.controls {
margin-top: 10px;
font-size: 16px;
color: #777;
}
</style>
</head>
<body>
<h1>儿童俄罗斯方块</h1>
<canvas id="gameCanvas" width="240" height="400"></canvas>
<button id="startButton">开始游戏</button>
<div class="controls">
使用方向键 <span style="font-weight: bold;">←</span> <span style="font-weight: bold;">→</span> 移动,<span style="font-weight: bold;">↓</span> 加速下落,<span style="font-weight: bold;">↑</span> 旋转。
</div>
<audio id="startGameSound" src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"></audio>
<audio id="lineClearSound" src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/doorbell.mp3"></audio>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startButton = document.getElementById('startButton');
const startGameSound = document.getElementById('startGameSound');
const lineClearSound = document.getElementById('lineClearSound');
const grid = [];
const gridRows = 20;
const gridCols = 12;
const blockSize = 20;
let currentPiece = null;
let gameInterval;
let isGameOver = false;
let gameSpeed = 500; // 初始速度,毫秒
const colors = [
null, 'lightblue', 'yellow', 'orange', 'purple', 'green', 'red', 'blue'
];
const pieces = [
[[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]], // O
[[0,0,0,0],[0,0,2,0],[2,2,2,0],[0,0,0,0]], // T
[[0,0,0,0],[0,3,3,0],[3,3,0,0],[0,0,0,0]], // S
[[0,0,0,0],[3,3,0,0],[0,3,3,0],[0,0,0,0]], // Z
[[0,0,0,0],[0,0,0,4],[4,4,4,4],[0,0,0,0]], // I
[[0,0,0,0],[0,0,5,0],[0,0,5,0],[5,5,0,0]], // L
[[0,0,0,0],[0,6,0,0],[0,6,0,0],[6,6,0,0]] // J
];
function initGrid() {
for (let y = 0; y < gridRows; y++) {
grid[y] = [];
for (let x = 0; x < gridCols; x++) {
grid[y][x] = 0;
}
}
}
function createNewPiece() {
const randomIndex = Math.floor(Math.random() * (pieces.length -1)) + 1; // 排除索引0的null
const piece = pieces[randomIndex];
return {
shape: piece,
colorIndex: randomIndex,
x: Math.floor(gridCols / 2) - Math.ceil(piece[0].length / 2),
y: 0
};
}
function drawBlock(x, y, colorIndex) {
ctx.fillStyle = colors[colorIndex];
ctx.fillRect(x * blockSize, y * blockSize, blockSize, blockSize);
ctx.strokeStyle = '#000';
ctx.strokeRect(x * blockSize, y * blockSize, blockSize, blockSize);
}
function drawGrid() {
for (let y = 0; y < gridRows; y++) {
for (let x = 0; x < gridCols; x++) {
if (grid[y][x] !== 0) {
drawBlock(x, y, grid[y][x]);
}
}
}
}
function drawPiece() {
if (currentPiece) {
for (let y = 0; y < currentPiece.shape.length; y++) {
for (let x = 0; x < currentPiece.shape[y].length; x++) {
if (currentPiece.shape[y][x] !== 0) {
drawBlock(currentPiece.x + x, currentPiece.y + y, currentPiece.colorIndex);
}
}
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGrid();
drawPiece();
}
function collision(piece) {
for (let y = 0; y < piece.shape.length; y++) {
for (let x = 0; x < piece.shape[y].length; x++) {
if (piece.shape[y][x] !== 0) {
const newX = piece.x + x;
const newY = piece.y + y;
if (newY >= gridRows || newX < 0 || newX >= gridCols || (newY >= 0 && grid[newY][newX] !== 0)) {
return true;
}
}
}
}
return false;
}
function mergePiece() {
for (let y = 0; y < currentPiece.shape.length; y++) {
for (let x = 0; x < currentPiece.shape[y].length; x++) {
if (currentPiece.shape[y][x] !== 0) {
grid[currentPiece.y + y][currentPiece.x + x] = currentPiece.colorIndex;
}
}
}
}
function movePieceDown() {
if (!currentPiece) return;
currentPiece.y++;
if (collision(currentPiece)) {
currentPiece.y--;
mergePiece();
currentPiece = createNewPiece();
if (collision(currentPiece)) {
gameOver();
}
clearLines();
}
}
function movePieceLeft() {
if (!currentPiece) return;
currentPiece.x--;
if (collision(currentPiece)) {
currentPiece.x++;
}
}
function movePieceRight() {
if (!currentPiece) return;
currentPiece.x++;
if (collision(currentPiece)) {
currentPiece.x--;
}
}
function rotatePiece() {
if (!currentPiece) return;
const shape = currentPiece.shape;
const rows = shape.length;
const cols = shape[0].length;
const newShape = [];
for (let i = 0; i < cols; i++) {
newShape[i] = [];
for (let j = rows - 1; j >= 0; j--) {
newShape[i][rows - 1 - j] = shape[j][i];
}
}
const originalX = currentPiece.x;
const originalY = currentPiece.y;
currentPiece.shape = newShape;
// 旋转后可能会发生碰撞,需要进行调整
while (collision(currentPiece)) {
currentPiece.x--; // 尝试向左移动
if (collision(currentPiece)) {
currentPiece.x = originalX; // 如果向左移动也不行,尝试向右移动
currentPiece.y--; // 尝试向上移动
if (collision(currentPiece)) {
currentPiece.y = originalY; // 如果向上移动也不行,恢复原始位置和形状
currentPiece.shape = shape;
return;
}
}
}
}
function clearLines() {
let linesCleared = 0;
for (let y = gridRows - 1; y >= 0; y--) {
if (grid[y].every(value => value !== 0)) {
linesCleared++;
for (let i = y; i > 0; i--) {
grid[i] = [...grid[i - 1]];
}
grid[0].fill(0);
if (lineClearSound) {
lineClearSound.play();
}
y++; // 重新检查当前行
}
}
if (linesCleared > 0) {
// 可以添加得分逻辑,这里省略
}
}
function gameLoop() {
if (!isGameOver) {
movePieceDown();
draw();
setTimeout(gameLoop, gameSpeed);
}
}
function gameOver() {
isGameOver = true;
clearInterval(gameInterval);
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, canvas.height / 4, canvas.width, canvas.height / 2);
ctx.fillStyle = 'white';
ctx.font = '24px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('游戏结束!', canvas.width / 2, canvas.height / 2);
startButton.style.display = 'block';
}
function startGame() {
initGrid();
currentPiece = createNewPiece();
isGameOver = false;
gameSpeed = 500; // 重置速度
startButton.style.display = 'none';
if (startGameSound) {
startGameSound.play();
}
gameLoop();
}
document.addEventListener('keydown', (e) => {
if (!currentPiece || isGameOver) return;
if (e.key === 'ArrowLeft') {
movePieceLeft();
draw();
} else if (e.key === 'ArrowRight') {
movePieceRight();
draw();
} else if (e.key === 'ArrowDown') {
movePieceDown();
draw();
// 可以适当加快下落速度,但为了儿童体验,这里保持不变
} else if (e.key === 'ArrowUp') {
rotatePiece();
draw();
}
});
startButton.addEventListener('click', startGame);
// 预加载音效 (可选)
if (startGameSound) {
startGameSound.load();
}
if (lineClearSound) {
lineClearSound.load();
}
// 初始绘制一个空网格
initGrid();
drawGrid();
</script>
</body>
</html>