Mystery Game #12
← Back to Games List
// Tetris Game Implementation
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game settings
const blockSize = 30;
const cols = 10;
const rows = 20;
canvas.width = cols * blockSize;
canvas.height = rows * blockSize;
// Colors
const colors = ['#00f0f0', '#0000f0', '#f0a000', '#f0f000', '#00f000', '#a000f0', '#f00000'];
// Shapes
const shapes = [
[[1, 1, 1, 1]], // I
[[1, 1, 1], [0, 1, 0]], // T
[[1, 1, 1], [1, 0, 0]], // L
[[1, 1, 1], [0, 0, 1]], // J
[[1, 1], [1, 1]], // O
[[1, 1, 0], [0, 1, 1]], // Z
[[0, 1, 1], [1, 1, 0]] // S
];
// Game state
let grid = Array(rows).fill().map(() => Array(cols).fill(0));
let score = 0;
let currentShape;
let currentColor;
let currentX;
let currentY;
let gameOver = false;
// Initialize new shape
function newShape() {
const shapeIndex = Math.floor(Math.random() * shapes.length);
currentShape = shapes[shapeIndex];
currentColor = colors[shapeIndex];
currentX = Math.floor((cols - currentShape[0].length) / 2);
currentY = 0;
if (!isValidMove(0, 0)) {
gameOver = true;
}
}
// Check if move is valid
function isValidMove(moveX, moveY) {
for (let y = 0; y < currentShape.length; y++) {
for (let x = 0; x < currentShape[y].length; x++) {
if (currentShape[y][x]) {
const newX = currentX + x + moveX;
const newY = currentY + y + moveY;
if (newX < 0 || newX >= cols || newY >= rows) return false;
if (newY >= 0 && grid[newY][newX]) return false;
}
}
}
return true;
}
// Lock current shape in place
function lockShape() {
for (let y = 0; y < currentShape.length; y++) {
for (let x = 0; x < currentShape[y].length; x++) {
if (currentShape[y][x]) {
if (currentY + y < 0) continue;
grid[currentY + y][currentX + x] = currentColor;
}
}
}
}
// Clear completed lines
function clearLines() {
let linesCleared = 0;
for (let y = rows - 1; y >= 0; y--) {
if (grid[y].every(cell => cell !== 0)) {
grid.splice(y, 1);
grid.unshift(Array(cols).fill(0));
linesCleared++;
y++;
}
}
if (linesCleared > 0) {
score += [40, 100, 300, 1200][linesCleared - 1];
}
}
// Rotate shape
function rotateShape() {
const newShape = [];
for (let x = 0; x < currentShape[0].length; x++) {
newShape.push([]);
for (let y = currentShape.length - 1; y >= 0; y--) {
newShape[x].push(currentShape[y][x]);
}
}
const oldShape = currentShape;
currentShape = newShape;
if (!isValidMove(0, 0)) {
currentShape = oldShape;
}
}
// Handle keyboard input
document.addEventListener('keydown', (e) => {
if (gameOver) {
if (e.key === 'Enter') {
grid = Array(rows).fill().map(() => Array(cols).fill(0));
score = 0;
gameOver = false;
newShape();
}
return;
}
switch(e.key) {
case 'ArrowLeft':
if (isValidMove(-1, 0)) currentX--;
break;
case 'ArrowRight':
if (isValidMove(1, 0)) currentX++;
break;
case 'ArrowDown':
if (isValidMove(0, 1)) currentY++;
break;
case 'ArrowUp':
rotateShape();
break;
case ' ':
while (isValidMove(0, 1)) currentY++;
break;
}
});
// Game loop
let lastTime = 0;
let dropInterval = 1000;
let dropCounter = 0;
function update(time = 0) {
const deltaTime = time - lastTime;
lastTime = time;
dropCounter += deltaTime;
if (dropCounter > dropInterval) {
if (isValidMove(0, 1)) {
currentY++;
} else {
lockShape();
clearLines();
newShape();
}
dropCounter = 0;
}
}
function draw() {
// Clear canvas
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw grid
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
if (grid[y][x]) {
ctx.fillStyle = grid[y][x];
ctx.fillRect(x * blockSize, y * blockSize, blockSize - 1, blockSize - 1);
}
}
}
// Draw current shape
if (!gameOver) {
ctx.fillStyle = currentColor;
for (let y = 0; y < currentShape.length; y++) {
for (let x = 0; x < currentShape[y].length; x++) {
if (currentShape[y][x]) {
ctx.fillRect(
(currentX + x) * blockSize,
(currentY + y) * blockSize,
blockSize - 1,
blockSize - 1
);
}
}
}
}
// Draw score
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.textAlign = 'left';
ctx.fillText('Score: ' + score, 10, 30);
// Draw game over
if (gameOver) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = '40px Arial';
ctx.textAlign = 'center';
ctx.fillText('Game Over!', canvas.width/2, canvas.height/2 - 20);
ctx.font = '20px Arial';
ctx.fillText('Score: ' + score, canvas.width/2, canvas.height/2 + 20);
ctx.fillText('Press Enter to Play Again', canvas.width/2, canvas.height/2 + 50);
}
}
function gameLoop(time = 0) {
update(time);
draw();
requestAnimationFrame(gameLoop);
}
// Start game
newShape();
gameLoop();
# Tetris Game Implementation
import pygame
import random
from dataclasses import dataclass
from typing import List, Tuple
import numpy as np
@dataclass
class Shape:
blocks: List[List[int]]
color: Tuple[int, int, int]
class TetrisGame:
def __init__(self):
pygame.init()
# Game settings
self.block_size = 30
self.cols = 10
self.rows = 20
self.width = self.cols * self.block_size
self.height = self.rows * self.block_size
# Initialize display
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Tetris')
self.clock = pygame.time.Clock()
# Colors (RGB)
self.colors = [
(0, 240, 240), # Cyan
(0, 0, 240), # Blue
(240, 160, 0), # Orange
(240, 240, 0), # Yellow
(0, 240, 0), # Green
(160, 0, 240), # Purple
(240, 0, 0) # Red
]
# Shapes
self.shapes = [
[[1, 1, 1, 1]], # I
[[1, 1, 1], [0, 1, 0]], # T
[[1, 1, 1], [1, 0, 0]], # L
[[1, 1, 1], [0, 0, 1]], # J
[[1, 1], [1, 1]], # O
[[1, 1, 0], [0, 1, 1]], # Z
[[0, 1, 1], [1, 1, 0]] # S
]
# Game state
self.grid = np.zeros((self.rows, self.cols), dtype=object)
self.score = 0
self.game_over = False
# Current piece
self.current_shape = None
self.current_color = None
self.current_x = 0
self.current_y = 0
# Timing
self.last_time = pygame.time.get_ticks()
self.drop_interval = 1000
self.drop_counter = 0
self.new_shape()
def new_shape(self):
"""Create a new random shape"""
shape_index = random.randrange(len(self.shapes))
self.current_shape = self.shapes[shape_index]
self.current_color = self.colors[shape_index]
self.current_x = (self.cols - len(self.current_shape[0])) // 2
self.current_y = 0
if not self.is_valid_move(0, 0):
self.game_over = True
def is_valid_move(self, move_x: int, move_y: int) -> bool:
"""Check if move is valid"""
for y, row in enumerate(self.current_shape):
for x, cell in enumerate(row):
if cell:
new_x = self.current_x + x + move_x
new_y = self.current_y + y + move_y
if (new_x < 0 or new_x >= self.cols or
new_y >= self.rows):
return False
if new_y >= 0 and self.grid[new_y][new_x]:
return False
return True
def lock_shape(self):
"""Lock current shape in place"""
for y, row in enumerate(self.current_shape):
for x, cell in enumerate(row):
if cell:
if self.current_y + y < 0:
continue
self.grid[self.current_y + y][self.current_x + x] = self.current_color
def clear_lines(self):
"""Clear completed lines and update score"""
lines_cleared = 0
y = self.rows - 1
while y >= 0:
if all(cell for cell in self.grid[y]):
self.grid = np.roll(self.grid[0:y+1], 1, axis=0)
self.grid[0] = [None] * self.cols
lines_cleared += 1
else:
y -= 1
if lines_cleared > 0:
self.score += [40, 100, 300, 1200][lines_cleared - 1]
def rotate_shape(self):
"""Rotate current shape clockwise"""
new_shape = [[self.current_shape[y][x]
for y in range(len(self.current_shape)-1, -1, -1)]
for x in range(len(self.current_shape[0]))]
old_shape = self.current_shape
self.current_shape = new_shape
if not self.is_valid_move(0, 0):
self.current_shape = old_shape
def handle_input(self) -> bool:
"""Handle keyboard input"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.KEYDOWN:
if self.game_over:
if event.key == pygame.K_RETURN:
self.grid = np.zeros((self.rows, self.cols), dtype=object)
self.score = 0
self.game_over = False
self.new_shape()
else:
if event.key == pygame.K_LEFT:
if self.is_valid_move(-1, 0):
self.current_x -= 1
elif event.key == pygame.K_RIGHT:
if self.is_valid_move(1, 0):
self.current_x += 1
elif event.key == pygame.K_DOWN:
if self.is_valid_move(0, 1):
self.current_y += 1
elif event.key == pygame.K_UP:
self.rotate_shape()
elif event.key == pygame.K_SPACE:
while self.is_valid_move(0, 1):
self.current_y += 1
return True
def update(self):
"""Update game state"""
if self.game_over:
return
current_time = pygame.time.get_ticks()
delta_time = current_time - self.last_time
self.last_time = current_time
self.drop_counter += delta_time
if self.drop_counter > self.drop_interval:
if self.is_valid_move(0, 1):
self.current_y += 1
else:
self.lock_shape()
self.clear_lines()
self.new_shape()
self.drop_counter = 0
def draw(self):
"""Draw the game state"""
# Clear screen
self.screen.fill((0, 0, 0))
# Draw grid
for y in range(self.rows):
for x in range(self.cols):
if self.grid[y][x]:
pygame.draw.rect(self.screen,
self.grid[y][x],
(x * self.block_size,
y * self.block_size,
self.block_size - 1,
self.block_size - 1))
# Draw current shape
if not self.game_over:
for y, row in enumerate(self.current_shape):
for x, cell in enumerate(row):
if cell:
pygame.draw.rect(self.screen,
self.current_color,
((self.current_x + x) * self.block_size,
(self.current_y + y) * self.block_size,
self.block_size - 1,
self.block_size - 1))
# Draw score
font = pygame.font.Font(None, 36)
score_text = font.render(f'Score: {self.score}', True, (255, 255, 255))
self.screen.blit(score_text, (10, 10))
# Draw game over
if self.game_over:
overlay = pygame.Surface((self.width, self.height))
overlay.fill((0, 0, 0))
overlay.set_alpha(178) # 70% opacity
self.screen.blit(overlay, (0, 0))
font = pygame.font.Font(None, 64)
game_over = font.render('Game Over!', True, (255, 255, 255))
game_over_rect = game_over.get_rect(
center=(self.width//2, self.height//2 - 20))
self.screen.blit(game_over, game_over_rect)
font = pygame.font.Font(None, 36)
score = font.render(f'Score: {self.score}', True, (255, 255, 255))
score_rect = score.get_rect(
center=(self.width//2, self.height//2 + 20))
self.screen.blit(score, score_rect)
play_again = font.render('Press Enter to Play Again',
True, (255, 255, 255))
play_again_rect = play_again.get_rect(
center=(self.width//2, self.height//2 + 50))
self.screen.blit(play_again, play_again_rect)
pygame.display.flip()
def run(self):
"""Main game loop"""
running = True
while running:
running = self.handle_input()
self.update()
self.draw()
self.clock.tick(60)
pygame.quit()
if __name__ == '__main__':
game = TetrisGame()
game.run()
Play Game