Skip to content

Instantly share code, notes, and snippets.

@senko
Created June 3, 2026 18:11
Show Gist options
  • Select an option

  • Save senko/f7e54469906dde943805ccdc1ef16d7b to your computer and use it in GitHub Desktop.

Select an option

Save senko/f7e54469906dde943805ccdc1ef16d7b to your computer and use it in GitHub Desktop.
Minesweeper by Gemma 4 12B Q4 - had to fix a few trivial syntax errors manually
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="=device-width, initial-scale=initial-scale=1.0">
<title>Modern Minesweeper</title>
<style>
:root {
--bg-color: #eef2f3;
--cell-bg: #d1d9de;
--cell-border: #adb5bd;
--cell-revealed: #ffffff;
--primary-color: #2c3e50;
--accent-color: #3498db;
--danger-color: #e74c3c;
--success-color: #2ecc71;
--font-main: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--bg-color);
font-family: var(--font-main);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
}
.game-container {
background: white;
padding: 2rem;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
text-align: center;
}
h1 { margin-bottom: 1rem; color: var(--primary-color); }
.stats-bar {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
font-weight: bold;
font-size: 1.2rem;
background: #f8f9fa;
padding: 10px 20px;
border-radius: 8px;
}
#grid {
display: grid;
gap: 4px;
background-color: var(--cell-border);
border: 4px solid var(--cell-border);
border-radius: 4px;
margin: 0 auto;
}
.cell {
width: 30px;
height: 30px;
background-color: var(--cell-bg);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
cursor: pointer;
user-select: none;
transition: background 0.1s, transform 0.1s;
border-radius: 2px;
}
.cell:hover:not(.revealed) {
background-color: #bdc3c7;
transform: scale(1.05);
}
.cell.revealed {
background-color: var(--cell-revealed);
cursor: default;
transform: none;
}
.cell.mine {
background-color: var(--danger-color) !important;
}
.cell.flagged::after {
content: "🚩";
font-size: 14px;
}
.cell.revealed.n1 { color: blue; }
.cell.revealed.n2 { color: green; }
.cell.revealed.n3 { color: red; }
.cell.revealed.n4 { color: darkblue; }
.cell.revealed.n5 { color: brown; }
.cell.revealed.n6 { color: cyan; }
.cell.revealed.n7 { color: black; }
.cell.revealed.n8 { color: grey; }
.controls {
margin-top: 1.5rem;
display: flex;
gap: 10px;
justify-content: center;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background: var(--accent-color);
color: white;
font-weight: bold;
cursor: pointer;
transition: opacity 0.2s;
}
button:hover { opacity: 0.8; }
select {
padding: 10px;
border-radius: 5px;
border: 1px solid var(--cell-border);
}
.game-over {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.8);
color: white;
padding: 2rem;
border-radius: 10px;
display: none;
z-index: 10;
}
</style>
</head>
<body>
<div class="game-container">
<h1>Minesweeper</h1>
<div class="stats-bar">
<div>💣 <span id="mine-count">0</span></div>
<div>⏱️ <span id="timer">000</span></div>
</div>
<div id="grid"></div>
<div class="controls">
<select id="difficulty">
<option value="easy">Easy (10x10, 10 Mines)</option>
<option value="medium"> Medium (15x15, 30 Mines)</option>
<option value="hard"> Hard (20x20, 60 Mines)</option>
</select>
<button id="reset-btn">New Game</button>
</div>
</div>
<div id="overlay" class="game-over">
<h2 id="status-msg">Game Over</h2>
<button onclick="resetGame()">Play Again</button>
</div>
<script>
const gridElement = document.getElementById('grid');
const mineCountElement = document.getElementById('mine-count');
const timerElement = document.getElementById('timer');
const resetBtn = document.getElementById('reset-btn');
const difficultySelect = document.getElementById('difficulty');
const overlay = document.getElementById('overlay');
const statusMsg = document.getElementById('status-msg');
let board = [];
let mines = 0;
let rows, cols;
let revealedCount = 0;
let timerInterval = null;
let seconds = 0;
let gameOver = false;
const configs = {
easy: { r: 10, c: 10, m: 10 },
medium: { r: 15, c: 15, m: 30 },
hard: { r: 20, c: 20, m: 60 }
};
function initGame() {
gameOver = false;
revealedCount = 0;
seconds = 0;
clearInterval(timerInterval);
timerElement.innerText = "000";
overlay.style.display = "none";
const config = configs[difficultySelect.value];
rows = config.r;
cols = config.c;
mines = config.m;
mineCountElement.innerText = mines;
// Setup Grid CSS
gridElement.style.gridTemplateColumns = `repeat(${cols}, 30px)`;
gridElement.innerHTML = '';
// Initialize Board Array
board = [];
for (let r = 0; r < rows; r++) {
board[r] = [];
for (let c = 0; c < cols; c++) {
const cell = {
r, c,
mine: false,
revealed: false,
flagged: false,
neighborCount: 0,
element: null
};
board[r][c] = cell;
}
}
// Place Mines
let placed = 0;
while (placed < mines) {
let r = Math.floor(Math.random() * rows);
let c = Math.floor(Math.random() * cols);
if (!board[r][c].mine) {
board[r][c].mine = true;
placed++;
}
}
// Calculate Neighbors
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (!board[r][c].mine) {
let count = 0;
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
let nr = r + dr;
let nc = c + dc;
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) {
if (board[nr][nc].mine) count++;
}
}
}
board[r][c].neighborCount = count;
}
}
}
// Create DOM Elements
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
const cellObj = board[r][c];
const div = document.createElement('div');
div.classList.add('cell');
div.addEventListener('click', (e) => handleLeftClick(r, c));
div.addEventListener('contextmenu', (e) => {
e.preventDefault();
handleRightClick(r, c);
});
cellObj.element = div;
gridElement.appendChild(div);
}
}
startTimer();
}
function startTimer() {
timerInterval = setInterval(() => {
seconds++;
timerElement.innerText = String(seconds).padStart(3, '0');
}, 1000);
}
function handleLeftClick(r, c) {
if (gameOver || board[r][c].flagged || board[r][c].revealed) return;
if (board[r][c].mine) {
revealAllMines();
endGame(false);
return;
}
revealCell(r, c);
checkWin();
}
function handleRightClick(r, c) {
if (gameOver || board[r][c].revealed) return;
const cell = board[r][c];
cell.flagged = !cell.flagged;
cell.element.classList.toggle('flagged', cell.flagged);
const currentFlags = document.querySelectorAll('.flagged').length;
mineCountElement.innerText = mines - currentFlags;
}
function revealCell(r, c) {
const cell = board[r][c];
if (cell.revealed || cell.flagged) return;
cell.revealed = true;
cell.element.classList.add('revealed');
revealedCount++;
if (cell.mine) {
cell.element.classList.add('mine');
return;
}
if (cell.neighborCount > 0) {
cell.element.innerText = cell.neighborCount;
cell.element.classList.add(`n${cell.neighborCount}`);
} else {
// Flood fill
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
let nr = r + dr;
let nc = c + dc;
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) {
revealCell(nr, nc);
}
}
}
}
}
function revealAllMines() {
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (board[r][c].mine) {
board[r][c].element.classList.add('mine');
board[r][c].element.classList.add('revealed');
}
}
}
}
function checkWin() {
if (revealedCount === (rows * cols) - mines) {
endGame(true);
}
}
function endGame(win) {
gameOver = true;
clearInterval(timerInterval);
statusMsg.innerText = win ? "YOU WIN! 🎉" : "GAME OVER 💥";
statusMsg.style.color = win ? "var(--success-color)" : "var(--danger-color)";
overlay.style.display = "block";
}
function resetGame() {
initGame();
}
resetBtn.addEventListener('click', resetGame);
difficultySelect.addEventListener('change', resetGame);
// Start initial game
initGame();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment