Bomb Grid Revisted (or And the Winner Is…)
A random Custom GPT easily implemented a web-based version of Minesweeper
So there I was feeling despondent. The cat didn’t help at all. So I decided to give the Bomb Grid/Minesweeper challenge another go, but this time with a ChatGPT custom GPTs.
The goal, as before, was to try and implement a web-based version of Minesweeper. When I did this last December I tried to get both ChatGPT and Bard (Gemini) to create a workable version. At the time, ChatGPT did the better job, but that was such a long time ago and both models have been updated and things are just hunky.
I used the Code Copilot from ChatGPT and this was our conversation (the only thing changed was that the code was moved into a code block):
Me:
what do you need to know in order to implement a web-based version of minesweeper
Code Copilot:
To implement a web-based version of Minesweeper, several aspects need to be considered, including the game mechanics, the user interface, and the backend logic. Here’s a detailed breakdown of what is needed:
- Game Mechanics:
- Define the grid size (e.g., 9×9, 16×16).
- Determine the number of mines for each difficulty level.
- Develop the logic to randomly place mines on the grid.
- Implement the logic to calculate the numbers for each cell (i.e., the number of adjacent mines).
- Define the win and lose conditions.
- User Interface (UI):
- Create a visual representation of the grid using HTML and CSS.
- Ensure each cell can display different states (hidden, revealed, flagged).
- Implement responsive design to support various screen sizes.
- Provide visual feedback for game status (win, lose, time taken, mines left).
- User Interactions:
- Handle left-click to reveal cells.
- Handle right-click to flag/unflag cells.
- Implement a restart button to reset the game.
- Game Logic:
- Implement the logic to reveal cells when clicked.
- Ensure clicking on a mine ends the game.
- Implement flood fill algorithm to reveal adjacent cells when a blank cell is clicked.
- Check for win condition after each move (all non-mine cells are revealed).
- Backend (Optional):
- If you want to store game progress or high scores, implement a backend using a technology like Node.js with a database.
- Implement APIs for saving and retrieving game data.
- Additional Features (Optional):
- Implement a timer to track how long the player takes to complete the game.
- Allow players to choose different difficulty levels.
- Implement a leaderboard to display high scores.
- Add animations and sound effects to enhance the user experience.
Step-by-Step Plan in Pseudocode
- Setup Basic HTML Structure:
- Create a grid container.
- Create cells within the grid.
- Style the Game with CSS:
- Style the grid and cells.
- Define different states for cells (hidden, revealed, flagged).
- Implement Game Logic in JavaScript:
- Initialize the game with a specified grid size and number of mines.
- Randomly place mines and calculate numbers for each cell.
- Add event listeners for cell clicks (left-click and right-click).
- Implement the reveal logic for cells.
- Implement the flagging logic for cells.
- Check for win/lose conditions after each move.
- Add a restart function to reset the game.
Example Implementation in Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Minesweeper</title>
<style>
/* Basic styling for the game */
.grid {
display: grid;
grid-template-columns: repeat(9, 40px);
gap: 2px;
}
.cell {
width: 40px;
height: 40px;
background-color: #ccc;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.cell.revealed {
background-color: #eee;
cursor: default;
}
.cell.flagged {
background-color: #f00;
}
</style>
</head>
<body>
<div class="grid" id="grid"></div>
<button onclick="startGame()">Restart</button>
<script>
const grid = document.getElementById('grid');
const rows = 9;
const cols = 9;
const minesCount = 10;
let mines, cells;
function startGame() {
grid.innerHTML = '';
mines = [];
cells = [];
// Initialize grid
for (let r = 0; r < rows; r++) {
const row = [];
for (let c = 0; c < cols; c++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.dataset.row = r;
cell.dataset.col = c;
cell.addEventListener('click', () => revealCell(r, c));
cell.addEventListener('contextmenu', (e) => {
e.preventDefault();
flagCell(r, c);
});
grid.appendChild(cell);
row.push(cell);
}
cells.push(row);
}
placeMines();
calculateNumbers();
}
function placeMines() {
let minesPlaced = 0;
while (minesPlaced < minesCount) {
const r = Math.floor(Math.random() * rows);
const c = Math.floor(Math.random() * cols);
if (!mines.includes(`${r},${c}`)) {
mines.push(`${r},${c}`);
minesPlaced++;
}
}
}
function calculateNumbers() {
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (mines.includes(`${r},${c}`)) {
cells[r][c].dataset.mine = true;
} else {
let count = 0;
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
if (mines.includes(`${r+dr},${c+dc}`)) {
count++;
}
}
}
cells[r][c].dataset.number = count;
}
}
}
}
function revealCell(row, col) {
const cell = cells[row][col];
if (cell.classList.contains('revealed') || cell.classList.contains('flagged')) return;
cell.classList.add('revealed');
if (cell.dataset.mine) {
alert('Game Over!');
startGame();
} else if (cell.dataset.number > 0) {
cell.textContent = cell.dataset.number;
} else {
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
if (row+dr >= 0 && row+dr < rows && col+dc >= 0 && col+dc < cols) {
revealCell(row+dr, col+dc);
}
}
}
}
checkWin();
}
function flagCell(row, col) {
const cell = cells[row][col];
if (cell.classList.contains('revealed')) return;
cell.classList.toggle('flagged');
}
function checkWin() {
let revealedCount = 0;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (cells[r][c].classList.contains('revealed')) {
revealedCount++;
}
}
}
if (revealedCount === rows * cols - minesCount) {
alert('You Win!');
startGame();
}
}
startGame();
</script>
</body>
</html>
Next Steps:
a. Add a timer to track how long the player takes to complete the game.
b. Implement a backend to store high scores and game progress.
I copied the code into one file (index.html) and opened it in Firefox.
And just like that, a working version of a web-based Minesweeper was done. The gaps in logic, etc. that I found when I tried the challenge with other LLMs simply didn’t exist. The game is not complete, but it works.
One prompt (and it wasn’t even very good).
What are you doing with custom GPTs?