← back to Model Arena
data/artifacts/04692f72ef1d/gemma3-12b.html
260 lines
<!DOCTYPE html>
<html>
<head>
<title>Tetris</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
#score { position: absolute; top: 10px; left: 10px; color: white; font-family: sans-serif; font-size: 20px; }
</style>
</head>
<body>
<div id="score">Score: 0</div>
<canvas id="tetrisCanvas" width="240" height="400"></canvas>
<script>
const canvas = document.getElementById('tetrisCanvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const gridWidth = 10;
const gridHeight = 20;
const blockSize = 24;
const grid = Array(gridHeight).fill(null).map(() => Array(gridWidth).fill(0));
let currentPiece = null;
let nextPiece = null;
let score = 0;
let speed = 500; // milliseconds
let lastTime = 0;
let gameOver = false;
let paused = false;
const pieces = [
[[1, 1, 1, 1]], // I
[[1, 1], [1, 1]], // O
[[1, 1, 0], [0, 1, 1]], // S
[[0, 1, 1], [1, 1, 0]], // Z
[[1, 1, 1], [0, 0, 1]], // J
[[1, 1, 1], [1, 0, 0]], // L
[[1, 1, 1], [0, 1, 0]] // T
];
function getRandomPiece() {
return pieces[Math.floor(Math.random() * pieces.length)];
}
function drawGrid() {
ctx.fillStyle = '#222';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = '#555';
for (let i = 0; i < gridHeight; i++) {
for (let j = 0; j < gridWidth; j++) {
if (grid[i][j] !== 0) {
ctx.fillStyle = getColor(grid[i][j]);
ctx.fillRect(j * blockSize, i * blockSize, blockSize, blockSize);
}
ctx.strokeRect(j * blockSize, i * blockSize, blockSize, blockSize);
}
}
}
function drawPiece(piece, x, y) {
for (let row = 0; row < piece.length; row++) {
for (let col = 0; col < piece[row].length; col++) {
if (piece[row][col]) {
ctx.fillStyle = getColor(1); // Color for the current piece. Could be dynamic later
ctx.fillRect((x + col) * blockSize, (y + row) * blockSize, blockSize, blockSize);
}
}
}
}
function getColor(value) {
switch (value) {
case 1: return 'blue';
case 2: return 'orange';
case 3: return 'yellow';
case 4: return 'purple';
case 5: return 'green';
case 6: return 'red';
case 7: return 'cyan';
default: return 'black';
}
}
function isValidMove(piece, x, y) {
for (let row = 0; row < piece.length; row++) {
for (let col = 0; col < piece[row].length; col++) {
if (piece[row][col]) {
const gridX = x + col;
const gridY = y + row;
if (gridX < 0 || gridX >= gridWidth || gridY >= gridHeight) {
return false;
}
if (gridY >= 0 && grid[gridY][gridX] !== 0) { // Check only if within bounds
return false;
}
}
}
}
return true;
}
function rotatePiece(piece) {
const rotated = [];
for (let col = 0; col < piece[0].length; col++) {
rotated.push([]);
for (let row = piece.length - 1; row >= 0; row--) {
rotated[col].push(piece[row][col]);
}
}
return rotated;
}
function placePiece(piece, x, y) {
for (let row = 0; row < piece.length; row++) {
for (let col = 0; col < piece[row].length; col++) {
if (piece[row][col]) {
grid[y + row][x + col] = 1; // Assign a color ID
}
}
}
}
function clearLines() {
let linesCleared = 0;
for (let i = gridHeight - 1; i >= 0; i--) {
let full = true;
for (let j = 0; j < gridWidth; j++) {
if (grid[i][j] === 0) {
full = false;
break;
}
}
if (full) {
linesCleared++;
// Shift lines down
for (let k = i; k < gridHeight - 1; k++) {
grid[k] = grid[k + 1].slice();
}
grid[gridHeight - 1] = Array(gridWidth).fill(0);
}
}
score += linesCleared * (Math.pow(2, linesCleared));
scoreDisplay.textContent = `Score: ${score}`;
}
function spawnNextPiece() {
nextPiece = getRandomPiece();
}
function newGame() {
grid.forEach(row => row.fill(0));
score = 0;
speed = 500;
gameOver = false;
paused = false;
currentPiece = getRandomPiece();
nextPiece = getRandomPiece();
scoreDisplay.textContent = `Score: ${score}`;
drawGrid();
drawPiece(currentPiece, gridWidth / 2 - 1, 0);
}
function gameLoop(timestamp) {
if (!gameOver && !paused) {
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
if (deltaTime >= speed) {
moveDown();
}
drawGrid();
if (currentPiece) drawPiece(currentPiece, currentPiece.x, currentPiece.y);
requestAnimationFrame(gameLoop);
} else if (gameOver) {
// Game over screen could be added here. For now, just show the grid.
drawGrid();
scoreDisplay.textContent = `Game Over - Score: ${score}`;
}
}
function moveDown() {
if (!currentPiece || !isValidMove(currentPiece.piece, currentPiece.x, currentPiece.y + 1)) {
placePiece(currentPiece.piece, currentPiece.x, currentPiece.y);
clearLines();
spawnNextPiece();
currentPiece = { piece: nextPiece, x: gridWidth / 2 - 1, y: 0 };
if (!isValidMove(currentPiece.piece, currentPiece.x, currentPiece.y)) {
gameOver = true;
}
} else {
currentPiece.y++;
}
}
function moveLeft() {
if (currentPiece && isValidMove(currentPiece.piece, currentPiece.x - 1, currentPiece.y)) {
currentPiece.x--;
}
}
function moveRight() {
if (currentPiece && isValidMove(currentPiece.piece, currentPiece.x + 1, currentPiece.y)) {
currentPiece.x++;
}
}
function rotate() {
const rotatedPiece = rotatePiece(currentPiece.piece);
if (isValidMove(rotatedPiece, currentPiece.x, currentPiece.y)) {
currentPiece.piece = rotatedPiece;
}
}
document.addEventListener('keydown', function(event) {
if (!gameOver && !paused) {
switch (event.key) {
case 'ArrowLeft': moveLeft(); break;
case 'ArrowRight': moveRight(); break;
case 'ArrowDown': speed = Math.max(100, speed - 50); break; // Speed up
case 'ArrowUp': rotate(); break;
case ' ': pauseGame(); break;
}
} else if (gameOver) {
if (event.key === "Enter") {
newGame();
}
}
});
function pauseGame() {
paused = !paused;
if(paused){
scoreDisplay.textContent = `Paused - Score: ${score}`;
} else {
scoreDisplay.textContent = `Score: ${score}`;
}
}
newGame(); // Start the game
</script>
</body>
</html>