Mystery Game #21

← Back to Games List
// Grid Movement Puzzle const levels = [ [ '#######', '#.....#', '#.o.*.#', '#.p...#', '#.o.*.#', '#.....#', '#######' ], [ '########', '#......#', '#.p.o..#', '#..o.*.#', '#..*...#', '#......#', '########' ] ]; const entity = { x: 0, y: 0 }; const objectives = []; const items = []; let currentLevel = 0; let moves = 0; let isActive = true; function initializeLevel() { objectives.length = 0; items.length = 0; const level = levels[currentLevel]; for (let y = 0; y < level.length; y++) { for (let x = 0; x < level[y].length; x++) { switch(level[y][x]) { case 'p': entity.x = x; entity.y = y; break; case 'o': items.push({x, y}); break; case '*': objectives.push({x, y}); break; } } } } function isWall(x, y) { return levels[currentLevel][y][x] === '#'; } function getItemAt(x, y) { return items.find(i => i.x === x && i.y === y); } function isObjectiveAt(x, y) { return objectives.some(o => o.x === x && o.y === y); } function moveEntity(dx, dy) { if (!isActive) return; const newX = entity.x + dx; const newY = entity.y + dy; if (isWall(newX, newY)) return; const item = getItemAt(newX, newY); if (item) { const pushX = newX + dx; const pushY = newY + dy; if (isWall(pushX, pushY) || getItemAt(pushX, pushY)) return; item.x = pushX; item.y = pushY; } entity.x = newX; entity.y = newY; moves++; checkWin(); } function checkWin() { const allMatched = objectives.every(obj => items.some(item => item.x === obj.x && item.y === obj.y) ); if (allMatched) { if (currentLevel < levels.length - 1) { currentLevel++; initializeLevel(); } else { isActive = false; showMessage('Puzzle Complete!'); } } } function render(ctx) { const tileSize = 40; const level = levels[currentLevel]; // Draw grid for (let y = 0; y < level.length; y++) { for (let x = 0; x < level[y].length; x++) { const char = level[y][x]; if (char === '#') { ctx.fillStyle = '#666'; ctx.fillRect(x * tileSize, y * tileSize, tileSize, tileSize); } } } // Draw objectives ctx.fillStyle = '#f00'; objectives.forEach(obj => { ctx.beginPath(); ctx.arc(obj.x * tileSize + tileSize/2, obj.y * tileSize + tileSize/2, 5, 0, Math.PI * 2); ctx.fill(); }); // Draw items ctx.fillStyle = '#a52'; items.forEach(item => { ctx.fillRect(item.x * tileSize + 2, item.y * tileSize + 2, tileSize - 4, tileSize - 4); }); // Draw entity ctx.fillStyle = '#0f0'; ctx.fillRect(entity.x * tileSize + 8, entity.y * tileSize + 8, tileSize - 16, tileSize - 16); // Draw moves ctx.fillStyle = '#fff'; ctx.font = '20px Arial'; ctx.fillText('Moves: ' + moves, 10, 30); } document.addEventListener('keydown', (e) => { switch(e.key) { case 'ArrowLeft': moveEntity(-1, 0); break; case 'ArrowRight': moveEntity(1, 0); break; case 'ArrowUp': moveEntity(0, -1); break; case 'ArrowDown': moveEntity(0, 1); break; } });
# Grid Movement Puzzle Implementation import pygame from dataclasses import dataclass from typing import List, Tuple @dataclass class Entity: x: int y: int @dataclass class Item: x: int y: int @dataclass class Objective: x: int y: int class PuzzleGame: def __init__(self): pygame.init() # Game settings self.tile_size = 40 self.levels = [ [ '#######', '#.....#', '#.o.*.#', '#.p...#', '#.o.*.#', '#.....#', '#######' ], [ '########', '#......#', '#.p.o..#', '#..o.*.#', '#..*...#', '#......#', '########' ] ] # Calculate window size based on largest level max_width = max(len(level[0]) for level in self.levels) max_height = max(len(level) for level in self.levels) self.width = max_width * self.tile_size self.height = max_height * self.tile_size # Initialize display self.screen = pygame.display.set_mode((self.width, self.height)) pygame.display.set_caption('Grid Puzzle') self.clock = pygame.time.Clock() # Game state self.entity = Entity(0, 0) self.items: List[Item] = [] self.objectives: List[Objective] = [] self.current_level = 0 self.moves = 0 self.is_active = True self.initialize_level() def initialize_level(self): """Initialize current level""" self.items.clear() self.objectives.clear() level = self.levels[self.current_level] for y, row in enumerate(level): for x, char in enumerate(row): if char == 'p': self.entity.x = x self.entity.y = y elif char == 'o': self.items.append(Item(x, y)) elif char == '*': self.objectives.append(Objective(x, y)) def is_wall(self, x: int, y: int) -> bool: """Check if position contains a wall""" return self.levels[self.current_level][y][x] == '#' def get_item_at(self, x: int, y: int) -> Item: """Get item at position if any""" for item in self.items: if item.x == x and item.y == y: return item return None def move_entity(self, dx: int, dy: int): """Move entity and handle item pushing""" if not self.is_active: return new_x = self.entity.x + dx new_y = self.entity.y + dy if self.is_wall(new_x, new_y): return item = self.get_item_at(new_x, new_y) if item: push_x = new_x + dx push_y = new_y + dy if (self.is_wall(push_x, push_y) or self.get_item_at(push_x, push_y)): return item.x = push_x item.y = push_y self.entity.x = new_x self.entity.y = new_y self.moves += 1 self.check_win() def check_win(self): """Check if all objectives are covered""" all_matched = all( any(item.x == obj.x and item.y == obj.y for item in self.items) for obj in self.objectives ) if all_matched: if self.current_level < len(self.levels) - 1: self.current_level += 1 self.initialize_level() else: self.is_active = False 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 event.key == pygame.K_LEFT: self.move_entity(-1, 0) elif event.key == pygame.K_RIGHT: self.move_entity(1, 0) elif event.key == pygame.K_UP: self.move_entity(0, -1) elif event.key == pygame.K_DOWN: self.move_entity(0, 1) return True def draw(self): """Draw the game state""" # Clear screen self.screen.fill((0, 0, 0)) # Black background level = self.levels[self.current_level] # Draw grid for y, row in enumerate(level): for x, char in enumerate(row): if char == '#': pygame.draw.rect(self.screen, (102, 102, 102), (x * self.tile_size, y * self.tile_size, self.tile_size, self.tile_size)) # Draw objectives for obj in self.objectives: pygame.draw.circle(self.screen, (255, 0, 0), (int(obj.x * self.tile_size + self.tile_size/2), int(obj.y * self.tile_size + self.tile_size/2)), 5) # Draw items for item in self.items: pygame.draw.rect(self.screen, (170, 85, 34), (item.x * self.tile_size + 2, item.y * self.tile_size + 2, self.tile_size - 4, self.tile_size - 4)) # Draw entity pygame.draw.rect(self.screen, (0, 255, 0), (self.entity.x * self.tile_size + 8, self.entity.y * self.tile_size + 8, self.tile_size - 16, self.tile_size - 16)) # Draw moves font = pygame.font.Font(None, 36) moves_text = font.render(f'Moves: {self.moves}', True, (255, 255, 255)) self.screen.blit(moves_text, (10, 10)) # Draw completion message if not self.is_active: font = pygame.font.Font(None, 64) complete_text = font.render('Puzzle Complete!', True, (255, 255, 255)) text_rect = complete_text.get_rect( center=(self.width//2, self.height//2)) self.screen.blit(complete_text, text_rect) pygame.display.flip() def run(self): """Main game loop""" running = True while running: running = self.handle_input() self.draw() self.clock.tick(60) pygame.quit() if __name__ == '__main__': game = PuzzleGame() game.run()
Play Game