Almost done
This commit is contained in:
86
src/App.js
86
src/App.js
@@ -6,27 +6,30 @@ import { GameService } from 'services';
|
|||||||
const gameClient = new GameService();
|
const gameClient = new GameService();
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [rows, setRows] = useState(10);
|
|
||||||
const [cols, setCols] = useState(10);
|
const [cols, setCols] = useState(10);
|
||||||
const [mines, setMines] = useState(5);
|
|
||||||
const [flags, setFlags] = useState(5);
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
const [dummyBoard, setDummyBoard] = useState([]);
|
const [dummyBoard, setDummyBoard] = useState([]);
|
||||||
|
const [flags, setFlags] = useState(5);
|
||||||
|
const [mines, setMines] = useState(5);
|
||||||
|
const [rows, setRows] = useState(10);
|
||||||
const [updateDummyBoard, setUpdateDummyBoard] = useState(true);
|
const [updateDummyBoard, setUpdateDummyBoard] = useState(true);
|
||||||
|
const [activeGame, setActiveGame] = useState(null);
|
||||||
|
|
||||||
const handleSetRows = value => {
|
const handleSetRows = value => {
|
||||||
// TODO can't be less than 3
|
if (value < 3 || value > 99) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setRows(value);
|
setRows(value);
|
||||||
setUpdateDummyBoard(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSetCols = value => {
|
const handleSetCols = value => {
|
||||||
// TODO can't be less than 3
|
if (value < 3 || value > 99) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setCols(value);
|
setCols(value);
|
||||||
setUpdateDummyBoard(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateDummyBoard = () => {
|
const generateDummyBoard = () => {
|
||||||
|
setDummyBoard([]);
|
||||||
const board = [];
|
const board = [];
|
||||||
|
|
||||||
for (let row = 0; row < rows; row++) {
|
for (let row = 0; row < rows; row++) {
|
||||||
@@ -41,41 +44,67 @@ function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSetMines = event => {
|
const handleSetMines = event => {
|
||||||
// TODO can't be less than 1
|
const value = parseInt(event.target.value);
|
||||||
setMines(parseInt(event.target.value));
|
if (value < 1 || value > 99) {
|
||||||
setFlags(parseInt(event.target.value));
|
return;
|
||||||
generateDummyBoard();
|
}
|
||||||
|
|
||||||
|
setMines(value);
|
||||||
|
setFlags(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function bootstrap() {
|
function bootstrap() {
|
||||||
setMounted(true);
|
setUpdateDummyBoard(false);
|
||||||
generateDummyBoard();
|
handleCreateNewGame();
|
||||||
}
|
|
||||||
|
|
||||||
if (!mounted) {
|
|
||||||
bootstrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateDummyBoard) {
|
if (updateDummyBoard) {
|
||||||
setUpdateDummyBoard(false);
|
bootstrap();
|
||||||
generateDummyBoard();
|
}
|
||||||
|
|
||||||
|
if (activeGame && activeGame.win === true) {
|
||||||
|
document.getElementsByClassName('reset')[0].innerHTML = '😎';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCellClick = (row, col) => {
|
const handleCellClick = (row, col) => {
|
||||||
|
if (activeGame.status === 3 || activeGame.win === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const cell = document.getElementById(`cell_${row}_${col}`);
|
const cell = document.getElementById(`cell_${row}_${col}`);
|
||||||
if (cell.classList.contains('flagged')) {
|
if (cell.classList.contains('flagged')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cell.classList.contains('revealed')) {
|
if (!cell.classList.contains('revealed')) {
|
||||||
|
cell.classList.add('busy');
|
||||||
|
gameClient.cellClick(row, col, activeGame.id).then(response => {
|
||||||
cell.classList.add('revealed');
|
cell.classList.add('revealed');
|
||||||
|
cell.classList.remove('busy');
|
||||||
|
if (response.active_game.board_progress[row][col] === 0) {
|
||||||
|
cell.classList.add('empty');
|
||||||
|
} else if (response.active_game.board_progress[row][col] > 0) {
|
||||||
|
const points = `${response.active_game.board_progress[row][col]}`;
|
||||||
|
cell.classList.add('point');
|
||||||
|
cell.classList.add(`point-${points}`);
|
||||||
|
cell.innerHTML = points;
|
||||||
|
} else {
|
||||||
|
cell.classList.add('mined');
|
||||||
|
document.getElementsByClassName('reset')[0].innerHTML = '👻';
|
||||||
|
}
|
||||||
|
|
||||||
|
setActiveGame(response.active_game);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCellContextMenu = (event, row, col) => {
|
const handleCellContextMenu = (event, row, col) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (activeGame.win === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const cell = document.getElementById(`cell_${row}_${col}`);
|
const cell = document.getElementById(`cell_${row}_${col}`);
|
||||||
if (cell.classList.contains('revealed')) {
|
if (cell.classList.contains('revealed')) {
|
||||||
return;
|
return;
|
||||||
@@ -83,18 +112,22 @@ function App() {
|
|||||||
|
|
||||||
if (cell.classList.contains('flagged')) {
|
if (cell.classList.contains('flagged')) {
|
||||||
cell.classList.remove('flagged');
|
cell.classList.remove('flagged');
|
||||||
} else {
|
setFlags(flags + 1);
|
||||||
|
} else if (flags > 0) {
|
||||||
cell.classList.add('flagged');
|
cell.classList.add('flagged');
|
||||||
|
setFlags(flags - 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateNewGame = event => {
|
const handleCreateNewGame = () => {
|
||||||
gameClient
|
gameClient.createNewGame(rows, cols, mines).then(response => {
|
||||||
.createNewGame(rows, cols, mines)
|
setActiveGame(response);
|
||||||
.then(response => console.log(response));
|
setFlags(mines);
|
||||||
|
generateDummyBoard();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!mounted) {
|
if (!activeGame) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +144,7 @@ function App() {
|
|||||||
setCols={handleSetCols}
|
setCols={handleSetCols}
|
||||||
setMines={setMines}
|
setMines={setMines}
|
||||||
setRows={handleSetRows}
|
setRows={handleSetRows}
|
||||||
|
setUpdateDummyBoard={setUpdateDummyBoard}
|
||||||
/>
|
/>
|
||||||
<Board
|
<Board
|
||||||
cols={cols}
|
cols={cols}
|
||||||
|
|||||||
BIN
src/assets/images/mine.png
Normal file
BIN
src/assets/images/mine.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -1,6 +1,7 @@
|
|||||||
$gray-light: #f6f6f6;
|
$gray-light: #f6f6f6;
|
||||||
$gray-mid: #e3e3e3;
|
$gray-mid: #e3e3e3;
|
||||||
$gray-dark: #333;
|
$gray-dark: #333;
|
||||||
|
$gray-border: #808080;
|
||||||
$gray: #d1d1d1;
|
$gray: #d1d1d1;
|
||||||
$red: #ec433c;
|
$red: #ec433c;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import './styles.scss';
|
|||||||
const Board = ({ dummyBoard, handleCellClick, handleCellContextMenu }) => {
|
const Board = ({ dummyBoard, handleCellClick, handleCellContextMenu }) => {
|
||||||
return (
|
return (
|
||||||
<div className="board">
|
<div className="board">
|
||||||
|
<div className="board-col-left"> </div>
|
||||||
|
<div className="board-col-center">
|
||||||
{dummyBoard.map((cols, rowId) => (
|
{dummyBoard.map((cols, rowId) => (
|
||||||
<div className="board-row" key={`row_${rowId}`}>
|
<div className="board-row" key={`row_${rowId}`}>
|
||||||
{cols.map((col, colId) => (
|
{cols.map((col, colId) => (
|
||||||
@@ -23,6 +25,8 @@ const Board = ({ dummyBoard, handleCellClick, handleCellContextMenu }) => {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="board-col-right"> </div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,20 @@
|
|||||||
|
|
||||||
.board {
|
.board {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
|
&-col-left,
|
||||||
|
&-col-right {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-col-center {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border-width: 3px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: darken($gray, 20%) lighten($gray, 20%) lighten($gray, 20%)
|
||||||
|
darken($gray, 20%);
|
||||||
|
}
|
||||||
|
|
||||||
&-row {
|
&-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -14,8 +27,52 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-cell.revealed {
|
&-cell.revealed {
|
||||||
margin: 1px;
|
padding: 2px;
|
||||||
border: 2px solid $gray-dark;
|
border: 1px solid $gray-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-cell.busy {
|
||||||
|
background-color: $gray-mid;
|
||||||
|
margin: 3px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-cell.point {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 90%;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-cell.point-1 {
|
||||||
|
color: #0000ff;
|
||||||
|
}
|
||||||
|
&-cell.point-2 {
|
||||||
|
color: #037d02;
|
||||||
|
}
|
||||||
|
&-cell.point-3 {
|
||||||
|
color: #fd0000;
|
||||||
|
}
|
||||||
|
&-cell.point-4 {
|
||||||
|
color: #010180;
|
||||||
|
}
|
||||||
|
&-cell.point-5 {
|
||||||
|
color: #830101;
|
||||||
|
}
|
||||||
|
&-cell.point-6 {
|
||||||
|
color: #038081;
|
||||||
|
}
|
||||||
|
&-cell.point-7 {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
&-cell.point-8 {
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-cell.mined {
|
||||||
|
background-image: url(../../assets/images/mine.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-cell {
|
&-cell {
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ const Header = ({
|
|||||||
mines,
|
mines,
|
||||||
rows,
|
rows,
|
||||||
setCols,
|
setCols,
|
||||||
setRows
|
setRows,
|
||||||
|
setUpdateDummyBoard
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<div className="flags led-panel box">{flags}</div>
|
|
||||||
<div className="settings">
|
<div className="settings">
|
||||||
<div className="custom">
|
|
||||||
<input
|
<input
|
||||||
className="box"
|
className="box"
|
||||||
onChange={event => setRows(parseInt(event.target.value))}
|
onChange={event => setRows(parseInt(event.target.value))}
|
||||||
@@ -36,8 +35,14 @@ const Header = ({
|
|||||||
type="number"
|
type="number"
|
||||||
value={mines}
|
value={mines}
|
||||||
/>
|
/>
|
||||||
|
<button
|
||||||
|
className="button box"
|
||||||
|
onClick={() => setUpdateDummyBoard(true)}>
|
||||||
|
Apply
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="canvas">
|
||||||
|
<div className="flags led-panel box">{flags}</div>
|
||||||
<div
|
<div
|
||||||
className="reset box"
|
className="reset box"
|
||||||
onMouseDown={event => {
|
onMouseDown={event => {
|
||||||
@@ -51,6 +56,7 @@ const Header = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="timer led-panel box">000</div>
|
<div className="timer led-panel box">000</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,7 +69,8 @@ Header.propTypes = {
|
|||||||
rows: PropTypes.number,
|
rows: PropTypes.number,
|
||||||
setCols: PropTypes.func.isRequired,
|
setCols: PropTypes.func.isRequired,
|
||||||
setMines: PropTypes.func.isRequired,
|
setMines: PropTypes.func.isRequired,
|
||||||
setRows: PropTypes.func.isRequired
|
setRows: PropTypes.func.isRequired,
|
||||||
|
setUpdateDummyBoard: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@@ -3,10 +3,37 @@
|
|||||||
.header {
|
.header {
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
max-width: 221px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 10px auto;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 40px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background: $gray-light;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
.led-panel {
|
.led-panel {
|
||||||
font-family: 'Space Mono', monospace;
|
font-family: 'Space Mono', monospace;
|
||||||
@@ -19,22 +46,6 @@
|
|||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings {
|
|
||||||
max-width: 221px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.custom {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.reset {
|
.reset {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
@@ -42,3 +53,4 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,9 +3,17 @@ import { RestClient, getResponseData } from './base';
|
|||||||
export class GameService extends RestClient {
|
export class GameService extends RestClient {
|
||||||
base = '/';
|
base = '/';
|
||||||
|
|
||||||
|
CLICK_NAIVE = 8;
|
||||||
|
|
||||||
createNewGame(rows, cols, mines) {
|
createNewGame(rows, cols, mines) {
|
||||||
return this.client
|
return this.client
|
||||||
.post(`${this.base}games`, { rows, cols, mines })
|
.post(`${this.base}games`, { rows, cols, mines })
|
||||||
.then(getResponseData);
|
.then(getResponseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cellClick(row, col, gameId) {
|
||||||
|
return this.client
|
||||||
|
.post(`${this.base}games/${gameId}/events`, { row, col })
|
||||||
|
.then(getResponseData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user