Skip to content

Commit 9853075

Browse files
feat: partially solve 3rd stage of the project
1 parent 8a0ac37 commit 9853075

18 files changed

+537
-7
lines changed

hyperskill/05_minesweeper/03/.gitkeep

Whitespace-only changes.

hyperskill/05_minesweeper/03/game.png

69.9 KB
Loading
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
2+
3+
* {
4+
box-sizing: border-box;
5+
}
6+
7+
.App {
8+
text-align: center;
9+
}
10+
11+
.App-logo {
12+
height: 40vmin;
13+
pointer-events: none;
14+
}
15+
16+
@media (prefers-reduced-motion: no-preference) {
17+
.App-logo {
18+
animation: App-logo-spin infinite 20s linear;
19+
}
20+
}
21+
22+
.App-header {
23+
background-color: #282c34;
24+
min-height: 100vh;
25+
display: flex;
26+
flex-direction: column;
27+
align-items: center;
28+
justify-content: center;
29+
font-size: calc(10px + 2vmin);
30+
color: white;
31+
}
32+
33+
.App-link {
34+
color: #61dafb;
35+
}
36+
37+
@keyframes App-logo-spin {
38+
from {
39+
transform: rotate(0deg);
40+
}
41+
to {
42+
transform: rotate(360deg);
43+
}
44+
}
45+
46+
.App p {
47+
font-family: 'Roboto', sans-serif;
48+
}
49+
50+
.minesweeper {
51+
display: flex;
52+
flex-direction: column;
53+
align-items: center;
54+
justify-content: center;
55+
font-family: 'Roboto', sans-serif;
56+
margin: 20px;
57+
border: none;
58+
border-radius: 20px;
59+
box-shadow: 0px 0px 20px red;
60+
width: 60vmin;
61+
}
62+
63+
.game-title {
64+
font-size: 36px;
65+
padding: 10px;
66+
}
67+
68+
.game-title img {
69+
height: 24px;
70+
}
71+
72+
.control-panel {
73+
display: flex;
74+
flex-direction: row;
75+
align-items: center;
76+
justify-content: space-around;
77+
margin: 0 20px 20px;
78+
width: 100%;
79+
}
80+
81+
.flags-counter {
82+
font-size: 24px;
83+
}
84+
85+
.reset-button {
86+
font-size: 24px;
87+
cursor: pointer;
88+
background-color: inherit;
89+
border: none;
90+
border-radius: 25%;
91+
}
92+
93+
.reset-button:hover {
94+
cursor: pointer;
95+
}
96+
97+
.timer {
98+
font-size: 24px;
99+
}
100+
101+
.field {
102+
display: grid;
103+
gap: 10px;
104+
width: 60vmin;
105+
height: 60vmin;
106+
padding: 20px;
107+
}
108+
109+
.cell {
110+
width: 48px;
111+
height: 48px;
112+
justify-self: center;
113+
align-self: center;
114+
background-color: black;
115+
border: black;
116+
outline: black;
117+
}
118+
119+
.is-revealed {
120+
background-color: #282c34;
121+
border: red;
122+
border-radius: 5px;
123+
box-shadow: 0px 0px 5px red;
124+
outline: red;
125+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import './App.css';
3+
import Minesweeper from "./components/Minesweeper";
4+
import Spinner from "./components/Spinner";
5+
6+
function App() {
7+
const isReady = true;
8+
9+
const rows = 9;
10+
const columns = 8;
11+
const minesQuantity = 10;
12+
13+
return (
14+
<div className="App">
15+
<header className="App-header">
16+
{isReady ? <Minesweeper rows={rows} columns={columns} minesQuantity={minesQuantity}/> : <Spinner/>}
17+
</header>
18+
</div>
19+
);
20+
}
21+
22+
export default App;
Lines changed: 30 additions & 0 deletions
Loading
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from "react";
2+
3+
const Cell = ({cell, onCellClick, onCellContext}) => {
4+
return (
5+
<div
6+
className={`cell ${cell.isRevealed ? "is-revealed" : ""}`}
7+
onClick={() => onCellClick(cell.x, cell.y)}
8+
onContextMenu={(e) => {
9+
e.preventDefault();
10+
onCellContext(cell.x, cell.y);
11+
}}
12+
>
13+
{cell.isRevealed && !cell.isMine && cell.neighbours === 0
14+
? ""
15+
: cell.isRevealed && !cell.isMine
16+
? cell.neighbours
17+
: cell.isRevealed && cell.isMine
18+
? "💥"
19+
: cell.isFlagged
20+
? "🚩"
21+
: ""}
22+
</div>
23+
);
24+
}
25+
26+
export default Cell;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from "react";
2+
3+
import FlagsCounter from "./FlagsCounter";
4+
import ResetButton from "./ResetButton";
5+
import Timer from "./Timer";
6+
7+
const ControlPanel = ({flags, time, onResetGame}) => {
8+
return (
9+
<div className="control-panel">
10+
<FlagsCounter flags={flags}/>
11+
<ResetButton onResetGame={onResetGame}/>
12+
<Timer time={time}/>
13+
</div>
14+
);
15+
}
16+
17+
export default ControlPanel;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from "react";
2+
3+
import Row from "./Row";
4+
5+
const Field = ({field, onCellClick, onCellContext}) => {
6+
const rows = field.length;
7+
const columns = field[0].length;
8+
9+
return (
10+
<div className="field" style={{
11+
gridTemplateColumns: `repeat(${columns}, 1fr)`,
12+
gridTemplateRows: `repeat(${rows}, 1fr)`,
13+
}}>
14+
{field.map((row, rowIndex) => (
15+
<Row
16+
key={rowIndex}
17+
row={row}
18+
onCellClick={onCellClick}
19+
onCellContext={onCellContext}
20+
/>
21+
))}
22+
</div>
23+
);
24+
}
25+
26+
export default Field;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from "react";
2+
3+
const FlagsCounter = ({flags}) => {
4+
return (
5+
<div className="flags-counter"><span role="img" aria-label="flag">🚩</span> {flags}</div>
6+
);
7+
}
8+
9+
export default FlagsCounter;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from "react";
2+
3+
import bomb from "../bomb.svg";
4+
5+
const GameTitle = () => {
6+
return (
7+
<div className="game-title">
8+
<p>Minesweeper <span role="img"><img src={bomb} alt="logo"/></span></p>
9+
</div>
10+
);
11+
}
12+
13+
export default GameTitle;

0 commit comments

Comments
 (0)