0% found this document useful (0 votes)
5 views7 pages

SnakeSweeper V1.2

The document is an HTML file that implements a hybrid game combining elements of Snake and Minesweeper. It features a canvas for rendering the game, controls for player input, and logic for handling game mechanics such as snake movement, apple spawning, and mine collisions. The game includes a scoring system and allows players to retry after a game over.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views7 pages

SnakeSweeper V1.2

The document is an HTML file that implements a hybrid game combining elements of Snake and Minesweeper. It features a canvas for rendering the game, controls for player input, and logic for handling game mechanics such as snake movement, apple spawning, and mine collisions. The game includes a scoring system and allows players to retry after a game over.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

<!

DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SnakeSweeper Hybrid Game</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #333;
color: white;
font-family: sans-serif;
}
canvas {
border: 2px solid white;
background-color: #eee;
}
#controls {
margin-top: 10px;
text-align: center;
}
#retryButton {
display: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
#status-container {
display: flex;
justify-content: space-between;
width: 400px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="status-container">
<div id="status">Status: Loading...</div>
<div id="score">Score: 0</div>
</div>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="controls">
<button id="retryButton">Retry?</button>
</div>

<script>
const canvas = [Link]('gameCanvas');
const ctx = [Link]('2d');
const statusEl = [Link]('status');
const scoreEl = [Link]('score');
const retryButton = [Link]('retryButton');
const TILE_SIZE = 20;
// Ensure the grid size matches the canvas dimensions set in HTML
const GRID_SIZE = [Link] / TILE_SIZE; // 400 / 20 = 20x20 grid
const MINE_COUNT = 30;

let snake;
let direction;
let gameOver = false;
let gameBoard;
let gameInterval;
let apple;
let score = 0;

// --- Game Initialization & Reset Functions ---


function initializeGame() {
snake = [{ x: 10, y: 10 }];
direction = { x: 0, y: -1 };
gameOver = false;
gameBoard = [];
score = 0;
[Link] = `Score: ${score}`;
[Link] = "Status: Active";
[Link] = 'none';

// 1. Setup empty board


for (let y = 0; y < GRID_SIZE; y++) {
gameBoard[y] = [];
for (let x = 0; x < GRID_SIZE; x++) {
// Added 'collidable' property, initially false
gameBoard[y][x] = { mine: false, count: 0, revealed: false,
collidable: false };
}
}

// 2. Place Mines
for (let i = 0; i < MINE_COUNT; i++) {
let mx = [Link]([Link]() * GRID_SIZE);
let my = [Link]([Link]() * GRID_SIZE);
// Ensure mines aren't on top of the starting snake head
if (gameBoard[my][mx].mine || (mx === snake[0].x && my ===
snake[0].y)) {
i--;
continue;
}
gameBoard[my][mx].mine = true;
}

// 3. Calculate adjacent mine counts


for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
if (gameBoard[y][x].mine) continue;
let count = 0;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
const nx = x + dx;
const ny = y + dy;
if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny <
GRID_SIZE) {
if (gameBoard[ny][nx].mine) {
count++;
}
}
}
}
gameBoard[y][x].count = count;
}
}

// 4. Spawn the first apple


spawnApple();
}

function resetGame() {
if (gameInterval) {
clearInterval(gameInterval);
}
initializeGame();
// Start the main game loop at a reasonable speed
gameInterval = setInterval(gameLoop, 150); // Speed set to 150ms
interval
}

function endGame(message) {
gameOver = true;
clearInterval(gameInterval);
[Link] = `Status: ${message} Game Over!`;
[Link] = 'inline-block';
}

// --- Apple Spawning Logic ---


function spawnApple() {
let validSpot = false;
while (!validSpot) {
const ax = [Link]([Link]() * GRID_SIZE);
const ay = [Link]([Link]() * GRID_SIZE);
const tile = gameBoard[ay][ax];

// Check 1: Is it a mine, next to a mine, on snake body, or a


new black collidable tile?
// `[Link] > 0` check removed to allow apples near mines if
not directly adjacent (a design choice)
if ([Link] || [Link] || [Link](segment =>
segment.x === ax && segment.y === ay)) {
continue;
}

// If all checks pass


apple = { x: ax, y: ay };
validSpot = true;
}
}

// --- Input Handling ---


[Link]('keydown', e => {
if (gameOver) return;
switch ([Link]) {
case 'ArrowUp': case 'w': if (direction.y === 0) direction =
{ x: 0, y: -1 }; break;
case 'ArrowDown': case 's': if (direction.y === 0) direction = {
x: 0, y: 1 }; break;
case 'ArrowLeft': case 'a': if (direction.x === 0) direction = {
x: -1, y: 0 }; break;
case 'ArrowRight': case 'd': if (direction.x === 0) direction =
{ x: 1, y: 0 }; break;
}
});

// Add event listener to the retry button


[Link]('click', resetGame);

// --- Game Logic (Update function) ---


function update() {
const newHead = {
x: snake[0].x + direction.x,
y: snake[0].y + direction.y
};

// Boundary and self-collision checks


if (newHead.x < 0 || newHead.x >= GRID_SIZE || newHead.y < 0 ||
newHead.y >= GRID_SIZE ||
[Link]((segment, index) => index > 0 && segment.x ===
newHead.x && segment.y === newHead.y))
{
endGame("Collision with wall or self!");
return;
}

// Check if the tile the snake is moving INTO is collidable


if (gameBoard[newHead.y][newHead.x].collidable) {
endGame("Collision with black debris!");
return;
}

[Link](newHead);

// --- Apple Eating Logic ---


if (newHead.x === apple.x && newHead.y === apple.y) {
score += 10;
[Link] = `Score: ${score}`;
spawnApple(); // Spawn a new apple in a safe place
} else {
// If no apple eaten, pop the tail to simulate movement
[Link]();
}

// --- Minesweeper Interaction & Mine Collision ---


handleTileReveal(newHead.x, newHead.y);
// checkWinCondition(); // This function was missing in original
code, so I won't implement a complex win condition beyond "don't die"
}

function handleTileReveal(hx, hy) {


// Reveal tiles around the head (3x3 area)
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
const nx = hx + dx;
const ny = hy + dy;
if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE)
{
gameBoard[ny][nx].revealed = true;
}
}
}

// Check if the NEW HEAD is on a mine


if (gameBoard[hy][hx].mine) {
// MINE EXPLOSION LOGIC ADDED HERE
explodeMine(hx, hy);

// End the game instantly when hitting a mine


endGame("Detonated a mine!");
}
}

function explodeMine(mx, my) {


// Step 1: Turn the 8 squares immediately around the mine to black
(collidable)
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
// Skip the center mine itself
if (dx === 0 && dy === 0) continue;
const nx = mx + dx;
const ny = my + dy;

if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE)
{
const neighborTile = gameBoard[ny][nx];
// Only turn non-mine tiles collidable
if (![Link]) {
[Link] = true;
[Link] = true;
}
}
}
}

// Step 2: Check the squares AROUND those 8 squares (2 steps away


from the center mine)
// This is where the original code cut off. I am adding a simple
completion logic here:

for (let dy = -2; dy <= 2; dy++) {


for (let dx = -2; dx <= 2; dx++) {
// Skip the 3x3 area already processed, and the center
if ([Link](dx) <= 1 && [Link](dy) <= 1) continue;

const nx = mx + dx;
const ny = my + dy;

if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE)
{
const outerTile = gameBoard[ny][nx];
// 25% chance to turn black/collidable
if ([Link]() < 0.25 && ![Link]) {
[Link] = true;
[Link] = true; // Mark as revealed to
render black
}
}
}
}
// Mark the mine itself as revealed so it can be drawn during render
gameBoard[my][mx].revealed = true;
}

// --- Rendering Logic (Draw function) ---


function draw() {
// Clear canvas for next frame
[Link](0, 0, [Link], [Link]);

// 1. Draw the board background and revealed tiles (Minesweeper


part)
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
const tile = gameBoard[y][x];
const posX = x * TILE_SIZE;
const posY = y * TILE_SIZE;

if ([Link]) {
[Link] = '#000'; // Black for explosion debris
[Link](posX, posY, TILE_SIZE, TILE_SIZE);
} else if ([Link]) {
[Link] = '#ccc'; // Light gray for revealed safe
areas
[Link](posX, posY, TILE_SIZE, TILE_SIZE);

// Draw mine counts if > 0


if ([Link] > 0 && ![Link]) {
[Link] = 'blue';
[Link] = '12px sans-serif';
[Link] = 'center';
[Link] = 'middle';
[Link]([Link], posX + TILE_SIZE / 2, posY
+ TILE_SIZE / 2);
} else if ([Link]) {
[Link] = 'red'; // Red for exploded mines
[Link](posX + 5, posY + 5, TILE_SIZE - 10,
TILE_SIZE - 10);
}
} else {
[Link] = '#eee'; // Unrevealed standard light
gray (matches initial background)
[Link](posX, posY, TILE_SIZE, TILE_SIZE);
}
// Optional: Draw grid lines
[Link] = '#999';
[Link](posX, posY, TILE_SIZE, TILE_SIZE);
}
}

// 2. Draw the Apple


[Link] = 'green';
[Link]();
[Link](apple.x * TILE_SIZE + TILE_SIZE / 2, apple.y * TILE_SIZE +
TILE_SIZE / 2, TILE_SIZE / 2 - 2, 0, [Link] * 2);
[Link]();

// 3. Draw the Snake


[Link] = 'blue';
[Link]((segment, index) => {
[Link](segment.x * TILE_SIZE, segment.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE);
// Draw eyes for the head
if (index === 0) {
[Link] = 'white';
// Simplified eye drawing
if (direction.x === 0) { // Up/Down
[Link](segment.x * TILE_SIZE + 4, segment.y *
TILE_SIZE + 4, 3, 3);
[Link](segment.x * TILE_SIZE + TILE_SIZE - 7,
segment.y * TILE_SIZE + 4, 3, 3);
} else { // Left/Right
[Link](segment.x * TILE_SIZE + 4, segment.y *
TILE_SIZE + 4, 3, 3);
[Link](segment.x * TILE_SIZE + 4, segment.y *
TILE_SIZE + TILE_SIZE - 7, 3, 3);
}
[Link] = 'blue'; // Reset color for next segment
}
});
}

// --- Main Game Loop ---


function gameLoop() {
if (gameOver) return;
update();
draw();
}

// Start the game for the first time


resetGame();

</script>
</body>
</html>

You might also like