Skip to content

Commit 12f7f1b

Browse files
committed
added minesweeper game
1 parent ed4d2ce commit 12f7f1b

4 files changed

Lines changed: 315 additions & 0 deletions

File tree

‎Mine-Sweeper/README.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Instructions for MineSweeper
2+
3+
## Quick Start
4+
5+
- You are presented with a board of squares. Some squares contain mines (bombs), others don't. If you click on a square containing a bomb, you lose. If you manage to click all the squares (without clicking on any bombs) you win.
6+
- Clicking a square which doesn't have a bomb reveals the number of neighbouring squares containing bombs. Use this information plus some guess work to avoid the bombs.
7+
- To open a square, point at the square and click on it. To mark a square you think is a bomb, point and right-click.
8+
9+
## Detailed Instructions
10+
11+
- A squares "neighbours" are the squares adjacent above, below, left, right, and all 4 diagonals. Squares on the sides of the board or in a corner have fewer neighbors. The board does not wrap around the edges.
12+
- If you open a square with 0 neighboring bombs, all its neighbors will automatically open. This can cause a large area to automatically open.
13+
- To remove a bomb marker from a square, point at it and right-click again.
14+
- If you mark a bomb incorrectly, you will have to correct the mistake before you can win. Incorrect bomb marking doesn't kill you, but it can lead to mistakes which do.
15+
- You don't have to mark all the bombs to win, you just need to open all non-bomb squares.
16+
- Right-clicking twice will undo the flag.
17+
- Refresh the page to start a new game.

‎Mine-Sweeper/app.js‎

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
document.addEventListener("DOMContentLoaded", () => {
2+
const grid = document.querySelector(".grid");
3+
const flagsLeft = document.querySelector("#flags-left");
4+
const result = document.querySelector("#result");
5+
let width = 10;
6+
let bombAmount = 20;
7+
let flags = 0;
8+
let squares = [];
9+
let isGameOver = false;
10+
11+
//create board
12+
function createBoard() {
13+
flagsLeft.innerHTML = bombAmount;
14+
15+
//get shuffled game array with random bombs
16+
const bombsArray = Array(bombAmount).fill("bomb");
17+
const emptyArray = Array(width * width - bombAmount).fill("valid");
18+
const gameArray = emptyArray.concat(bombsArray);
19+
const shuffledArray = gameArray.sort(() => Math.random() - 0.5);
20+
21+
for (let i = 0; i < width * width; i++) {
22+
const square = document.createElement("div");
23+
square.setAttribute("id", i);
24+
square.classList.add(shuffledArray[i]);
25+
grid.appendChild(square);
26+
squares.push(square);
27+
28+
//normal click
29+
square.addEventListener("click", function (e) {
30+
click(square);
31+
});
32+
33+
//cntrl and left click
34+
square.oncontextmenu = function (e) {
35+
e.preventDefault();
36+
addFlag(square);
37+
};
38+
}
39+
40+
//add numbers
41+
for (let i = 0; i < squares.length; i++) {
42+
let total = 0;
43+
const isLeftEdge = i % width === 0;
44+
const isRightEdge = i === width - 1;
45+
46+
if (squares[i].classList.contains("valid")) {
47+
if (i > 0 && !isLeftEdge && squares[i - 1].classList.contains("bomb"))
48+
total++;
49+
if (
50+
i > 9 &&
51+
!isRightEdge &&
52+
squares[i + 1 - width].classList.contains("bomb")
53+
)
54+
total++;
55+
if (i > 10 && squares[i - width].classList.contains("bomb")) total++;
56+
if (
57+
i > 11 &&
58+
!isLeftEdge &&
59+
squares[i - 1 - width].classList.contains("bomb")
60+
)
61+
total++;
62+
if (i < 98 && !isRightEdge && squares[i + 1].classList.contains("bomb"))
63+
total++;
64+
if (
65+
i < 90 &&
66+
!isLeftEdge &&
67+
squares[i - 1 + width].classList.contains("bomb")
68+
)
69+
total++;
70+
if (
71+
i < 88 &&
72+
!isRightEdge &&
73+
squares[i + 1 + width].classList.contains("bomb")
74+
)
75+
total++;
76+
if (i < 89 && squares[i + width].classList.contains("bomb")) total++;
77+
squares[i].setAttribute("data", total);
78+
}
79+
}
80+
}
81+
createBoard();
82+
83+
// add flag with right click
84+
function addFlag(square) {
85+
if (isGameOver) return;
86+
if (!square.classList.contains("checked") && flags < bombAmount) {
87+
if (!square.classList.contains("flag")) {
88+
square.classList.add("flag");
89+
square.innerHTML = " 🚩";
90+
flags++;
91+
flagsLeft.innerHTML = bombAmount - flags;
92+
checkForWin();
93+
} else {
94+
square.classList.remove("flag");
95+
square.innerHTML = "";
96+
flags--;
97+
flagsLeft.innerHTML = bombAmount - flags;
98+
}
99+
}
100+
}
101+
102+
//click on square actions
103+
function click(square) {
104+
let currentId = square.id;
105+
if (isGameOver) return;
106+
if (
107+
square.classList.contains("checked") ||
108+
square.classList.contains("flag")
109+
)
110+
return;
111+
if (square.classList.contains("bomb")) {
112+
gameOver(square);
113+
} else {
114+
let total = square.getAttribute("data");
115+
if (total != 0) {
116+
square.classList.add("checked");
117+
if (total == 1) square.classList.add("one");
118+
if (total == 2) square.classList.add("two");
119+
if (total == 3) square.classList.add("three");
120+
if (total == 4) square.classList.add("four");
121+
square.innerHTML = total;
122+
return;
123+
}
124+
checkSquare(square, currentId);
125+
}
126+
square.classList.add("checked");
127+
}
128+
129+
//check neighboring squares once square is clicked
130+
function checkSquare(square, currentId) {
131+
const isLeftEdge = currentId % width === 0;
132+
const isRightEdge = currentId % width === width - 1;
133+
134+
setTimeout(() => {
135+
if (currentId > 0 && !isLeftEdge) {
136+
const newId = squares[parseInt(currentId) - 1].id;
137+
const newSquare = document.getElementById(newId);
138+
click(newSquare);
139+
}
140+
if (currentId > 9 && !isRightEdge) {
141+
const newId = squares[parseInt(currentId) + 1 - width].id;
142+
const newSquare = document.getElementById(newId);
143+
click(newSquare);
144+
}
145+
if (currentId > 10) {
146+
const newId = squares[parseInt(currentId - width)].id;
147+
const newSquare = document.getElementById(newId);
148+
click(newSquare);
149+
}
150+
if (currentId > 11 && !isLeftEdge) {
151+
const newId = squares[parseInt(currentId) - 1 - width].id;
152+
const newSquare = document.getElementById(newId);
153+
click(newSquare);
154+
}
155+
if (currentId < 98 && !isRightEdge) {
156+
const newId = squares[parseInt(currentId) + 1].id;
157+
const newSquare = document.getElementById(newId);
158+
click(newSquare);
159+
}
160+
if (currentId < 90 && !isLeftEdge) {
161+
const newId = squares[parseInt(currentId) - 1 + width].id;
162+
const newSquare = document.getElementById(newId);
163+
click(newSquare);
164+
}
165+
if (currentId < 88 && !isRightEdge) {
166+
const newId = squares[parseInt(currentId) + 1 + width].id;
167+
const newSquare = document.getElementById(newId);
168+
click(newSquare);
169+
}
170+
if (currentId < 89) {
171+
const newId = squares[parseInt(currentId) + width].id;
172+
const newSquare = document.getElementById(newId);
173+
click(newSquare);
174+
}
175+
}, 10);
176+
}
177+
178+
// game over
179+
function gameOver(square) {
180+
result.innerHTML = "BOOM! Game Over!";
181+
isGameOver = true;
182+
183+
// show all the bombs when the game is over
184+
squares.forEach((square) => {
185+
if (square.classList.contains("bomb")) {
186+
square.innerHTML = "💣";
187+
square.classList.remove("bomb");
188+
square.classList.add("checked");
189+
}
190+
});
191+
}
192+
193+
// check for win
194+
function checkForWin() {
195+
let matches = 0;
196+
for (let i = 0; i < squares.length; i++) {
197+
if (
198+
squares[i].classList.contains("flag") &&
199+
squares[i].classList.contains("bomb")
200+
) {
201+
matches++;
202+
}
203+
if (matches === bombAmount) {
204+
console.log("YOU WIN!");
205+
isGameOver = true;
206+
}
207+
}
208+
}
209+
});

‎Mine-Sweeper/index.html‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Minesweeper</title>
7+
<link rel="stylesheet" href="style.css" />
8+
<link
9+
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@700&display=swap"
10+
rel="stylesheet"
11+
/>
12+
</head>
13+
<body>
14+
<div class="container">
15+
<div class="grid"></div>
16+
<div>Flags left: <span id="flags-left"></span></div>
17+
<div id="result"></div>
18+
</div>
19+
<script src="app.js"></script>
20+
</body>
21+
</html>

‎Mine-Sweeper/style.css‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
.container {
2+
width: 500px;
3+
align-content: center;
4+
}
5+
6+
.grid {
7+
height: 400px;
8+
width: 400px;
9+
display: flex;
10+
flex-wrap: wrap;
11+
background-color: #dcd6bc;
12+
margin-left: 50px;
13+
margin-top: 20px;
14+
border: 10px solid #dcd6bc;
15+
margin-bottom: 10px;
16+
}
17+
18+
div {
19+
font-size: 25px;
20+
text-align: center;
21+
font-family: "Robot Mono", monospace;
22+
}
23+
24+
.valid {
25+
height: 40px;
26+
width: 40px;
27+
border: 5px solid;
28+
border-color: #f5f3eb #bab7a9 #bab7a9 #fff9db;
29+
box-sizing: border-box;
30+
}
31+
32+
.checked {
33+
height: 40px;
34+
width: 40px;
35+
border: 2px solid;
36+
background-color: #cecab7;
37+
border-color: #9c998d;
38+
box-sizing: border-box;
39+
}
40+
41+
.bomb {
42+
height: 40px;
43+
width: 40px;
44+
border: 5px solid;
45+
border-color: #f5f3eb #bab7a9 #bab7a9 #fff9db;
46+
box-sizing: border-box;
47+
}
48+
49+
.one {
50+
color: #e76346;
51+
}
52+
53+
.two {
54+
color: #4199d3;
55+
}
56+
57+
.three {
58+
color: #57da59;
59+
}
60+
61+
.four {
62+
color: #bb41d3;
63+
}
64+
65+
#result {
66+
margin-top: 5px;
67+
color: #e76346;
68+
}

0 commit comments

Comments
 (0)