├── img
├── cell-0.png
├── cell-covered.png
├── cell-flagged.png
├── display-digit-0.png
├── display-digit-1.png
├── display-digit-2.png
├── display-digit-3.png
├── display-digit-4.png
├── display-digit-5.png
├── display-digit-6.png
├── display-digit-7.png
├── display-digit-8.png
├── display-digit-9.png
├── face-active.png
├── face-clicking.png
├── face-lost.png
├── face-won.png
├── face.png
├── mine-exploded.png
├── minesweeper-icon.png
└── share-image.png
├── index.html
├── index.js
├── readme.md
└── style.css
/img/cell-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/cell-0.png
--------------------------------------------------------------------------------
/img/cell-covered.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/cell-covered.png
--------------------------------------------------------------------------------
/img/cell-flagged.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/cell-flagged.png
--------------------------------------------------------------------------------
/img/display-digit-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-0.png
--------------------------------------------------------------------------------
/img/display-digit-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-1.png
--------------------------------------------------------------------------------
/img/display-digit-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-2.png
--------------------------------------------------------------------------------
/img/display-digit-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-3.png
--------------------------------------------------------------------------------
/img/display-digit-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-4.png
--------------------------------------------------------------------------------
/img/display-digit-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-5.png
--------------------------------------------------------------------------------
/img/display-digit-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-6.png
--------------------------------------------------------------------------------
/img/display-digit-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-7.png
--------------------------------------------------------------------------------
/img/display-digit-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-8.png
--------------------------------------------------------------------------------
/img/display-digit-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/display-digit-9.png
--------------------------------------------------------------------------------
/img/face-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/face-active.png
--------------------------------------------------------------------------------
/img/face-clicking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/face-clicking.png
--------------------------------------------------------------------------------
/img/face-lost.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/face-lost.png
--------------------------------------------------------------------------------
/img/face-won.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/face-won.png
--------------------------------------------------------------------------------
/img/face.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/face.png
--------------------------------------------------------------------------------
/img/mine-exploded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/mine-exploded.png
--------------------------------------------------------------------------------
/img/minesweeper-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/minesweeper-icon.png
--------------------------------------------------------------------------------
/img/share-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/one-square-minesweeper/fabb9dfa146c51d8dc872f20d4682cc1f81a9444/img/share-image.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | One Square Minesweeper
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
21 |
22 |
23 |
24 |
25 |
29 |
33 |
37 |
38 |
39 |
40 |
73 |
74 |
75 |

76 |

77 |

78 |

79 |

80 |

81 |

82 |
83 |
84 |
85 |
86 |
87 |
88 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | (() => {
2 | const digit = document.querySelector(".digit");
3 | const timer0 = document.querySelector(".timer-0");
4 | const timer1 = document.querySelector(".timer-1");
5 | const timer2 = document.querySelector(".timer-2");
6 | const faceButton = document.querySelector(".face-button");
7 | const oneSquare = document.querySelector(".one-square");
8 |
9 | let startTime, animationFrame;
10 | let last = "";
11 |
12 | startTimer();
13 |
14 | document.oncontextmenu = function (e) {
15 | if (e.target === oneSquare) return false;
16 | };
17 |
18 | function reset() {
19 | cancelAnimationFrame(animationFrame);
20 | dead = false;
21 | win = false;
22 | faceButton.classList.remove("face-button-clicking");
23 | faceButton.classList.remove("face-button-dead");
24 | faceButton.classList.remove("face-button-won");
25 | oneSquare.classList.remove("exploded");
26 | oneSquare.classList.remove("flagged");
27 | digit.src = "./img/display-digit-1.png";
28 | startTimer();
29 | }
30 |
31 | function startTimer() {
32 | startTime = Date.now();
33 | animationFrame = window.requestAnimationFrame(tick);
34 | }
35 |
36 | function tick() {
37 | setTime(Date.now() - startTime);
38 | animationFrame = window.requestAnimationFrame(tick);
39 | }
40 |
41 | function setTime(duration) {
42 | let seconds = Math.floor((duration / 1000) % 60);
43 |
44 | if (seconds > 999) {
45 | seconds = 999;
46 | }
47 |
48 | const secondString = seconds.toString().padStart(3, 0).split("");
49 | timer0.src = `./img/display-digit-${secondString[0]}.png`;
50 | timer1.src = `./img/display-digit-${secondString[1]}.png`;
51 | timer2.src = `./img/display-digit-${secondString[2]}.png`;
52 | }
53 |
54 | oneSquare.addEventListener("mousedown", (e) => {
55 | if (e.ctrlKey) {
56 | e.preventDefault();
57 | e.stopPropagation();
58 | }
59 | clicking = true;
60 | faceButton.classList.add("face-button-clicking");
61 | });
62 |
63 | oneSquare.addEventListener("mouseup", (e) => {
64 | if (clicking === false) {
65 | return;
66 | }
67 |
68 | if (e.ctrlKey || e.which === 3) {
69 | faceButton.classList.remove("face-button-clicking");
70 | oneSquare.classList.add("flagged");
71 | faceButton.classList.add("face-button-won");
72 | digit.src = "./img/display-digit-0.png";
73 | } else {
74 | faceButton.classList.remove("face-button-clicking");
75 | oneSquare.classList.add("exploded");
76 | faceButton.classList.add("face-button-dead");
77 | digit.src = "./img/display-digit-1.png";
78 | }
79 |
80 | cancelAnimationFrame(animationFrame);
81 | clicking = false;
82 | });
83 |
84 | oneSquare.addEventListener("mouseout", () => {
85 | if (clicking === true) {
86 | clicking = false;
87 | faceButton.classList.remove("face-button-clicking");
88 | }
89 | });
90 |
91 | faceButton.addEventListener("click", () => {
92 | reset();
93 | });
94 | })();
95 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # One Square Minesweeper
2 |
3 | A game of minesweeper that is easy to complete (or lose). Play at [https://onesquareminesweeper.com](https://onesquareminesweeper.com).
4 |
5 | ### Instructions
6 | - Right click (or crtl + click) is flag
7 | - Normal Click to sweep mines
8 | - Click the face to reset
9 |
10 |
11 |
12 | ### Attributions
13 | Assets and some styles borrowed from this fantastic [open source minesweeper](https://github.com/leyanlo/minesweeper/) (with more than 1 tile to sweep)
14 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | image-rendering: pixelated;
4 | }
5 |
6 | html,
7 | body {
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
12 | .preload {
13 | width: 0;
14 | visibility: hidden;
15 | }
16 |
17 | body {
18 | height: 100vh;
19 | display: flex;
20 | align-items: center;
21 | justify-content: center;
22 | background: #fafafa;
23 | font-family: "Segoe UI", sans-serif;
24 | font-size: 11px;
25 | background-color: rgb(0, 134, 137);
26 | }
27 |
28 | .minesweeper {
29 | border-width: 1px;
30 | border-style: solid;
31 | border-image: initial;
32 | border-color: rgb(212, 208, 200) rgb(64, 64, 64) rgb(64, 64, 64)
33 | rgb(212, 208, 200);
34 | }
35 |
36 | .minesweeper-inner {
37 | border-width: 1px;
38 | border-style: solid;
39 | border-image: initial;
40 | border-color: rgb(255, 255, 255) rgb(128, 128, 128) rgb(128, 128, 128)
41 | rgb(255, 255, 255);
42 | background-color: rgb(212, 208, 200);
43 | padding: 1px;
44 | }
45 |
46 | header {
47 | background: linear-gradient(to right, rgb(11, 36, 106), rgb(166, 202, 240));
48 | color: rgb(255, 255, 255);
49 | display: flex;
50 | font-weight: 700;
51 | height: 18px;
52 | padding: 1px 2px;
53 | align-items: center;
54 | }
55 |
56 | header img {
57 | width: 16px;
58 | height: 16px;
59 | margin-right: 4px;
60 | }
61 |
62 | .game {
63 | padding: 6px;
64 | background-color: rgb(192, 192, 192);
65 | border-width: 3px 0px 0px 3px;
66 | border-style: solid;
67 | border-color: rgb(255, 255, 255);
68 | }
69 |
70 | section {
71 | border-width: 2px;
72 | border-style: solid;
73 | border-image: initial;
74 | border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255)
75 | rgb(128, 128, 128);
76 | }
77 |
78 | .scoring {
79 | margin-bottom: 6px;
80 | }
81 |
82 | .scoreboard {
83 | display: flex;
84 | align-items: flex-end;
85 | -webkit-box-pack: justify;
86 | justify-content: space-between;
87 | padding: 4px 5px;
88 | }
89 |
90 | .panel {
91 | border-width: 1px;
92 | border-style: solid;
93 | border-image: initial;
94 | border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255)
95 | rgb(128, 128, 128);
96 | background-color: rgb(0, 0, 0);
97 | gap: 2px;
98 | padding: 2px;
99 | display: flex;
100 | }
101 |
102 | .face-button {
103 | border: none;
104 | padding: 0px;
105 | width: 26px;
106 | height: 28px;
107 | background: none;
108 | margin: 0 2px;
109 | background-image: url("./img/face.png");
110 | background-position: center;
111 | background-repeat: no-repeat;
112 | }
113 |
114 | .board-items {
115 | background-color: rgb(123 123 123 / 4%);
116 | user-select: none;
117 | height: 160px;
118 | display: flex;
119 | justify-content: center;
120 | align-items: center;
121 | }
122 |
123 | .one-square {
124 | width: 16px;
125 | height: 16px;
126 | background-image: url("./img/cell-covered.png");
127 | }
128 |
129 | .one-square:active {
130 | background-image: url("./img/cell-0.png");
131 | }
132 |
133 | .exploded {
134 | pointer-events: none;
135 | background-image: url("./img/mine-exploded.png");
136 | }
137 |
138 | .flagged {
139 | pointer-events: none;
140 | background-image: url("./img/cell-flagged.png");
141 | }
142 |
143 | .face-button:active {
144 | background-image: url("./img/face-active.png");
145 | }
146 |
147 | .face-button-clicking {
148 | background-image: url("./img/face-clicking.png");
149 | }
150 |
151 | .face-button-won {
152 | background-image: url("./img/face-won.png");
153 | }
154 |
155 | .face-button-dead {
156 | background-image: url("./img/face-lost.png");
157 | }
158 |
159 | .sitter {
160 | position: fixed;
161 | bottom: 15px;
162 | font-family: monospace;
163 | font-size: 11px;
164 | font-weight: bold;
165 | text-transform: uppercase;
166 | }
167 |
168 | .watch {
169 | background: rgba(255, 255, 255, 0.6);
170 | padding: 10px 15px;
171 | border-radius: 22px;
172 | display: inline-block;
173 | margin-right: 5px;
174 | }
175 |
176 | .twitter {
177 | background: url("data:image/png;base64,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");
178 | width: 33px;
179 | height: 33px;
180 | display: inline-block;
181 | background-repeat: no-repeat;
182 | background-color: rgba(255, 255, 255, 0.6);
183 | border-radius: 50%;
184 | background-size: 20px 20px;
185 | background-position: center;
186 | vertical-align: top;
187 | }
188 |
189 | .left {
190 | left: 15px;
191 | }
192 |
193 | .right {
194 | right: 15px;
195 | }
196 |
--------------------------------------------------------------------------------