Skip to content

Commit

Permalink
Added timer, and mines left.
Browse files Browse the repository at this point in the history
Also showing mines on gameover
  • Loading branch information
funkjunky committed May 9, 2023
1 parent ba73c0d commit 8d2dc3f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 21 deletions.
5 changes: 3 additions & 2 deletions Minesweeper/Square.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Pressable, Text } from 'react-native';

const Square = ({ square: { hasMine, minesAround, cleared, flagged }, clearSquare, flagSquare, onPressIn, onPressOut }) => {
const Square = ({ square: { hasMine, minesAround, cleared, flagged }, clearSquare, flagSquare, onPressIn, onPressOut, gameover }) => {
const title = hasMine ? 'x' : minesAround;
let style = {
flexDirection: 'row',
Expand All @@ -17,9 +17,10 @@ const Square = ({ square: { hasMine, minesAround, cleared, flagged }, clearSquar
borderBottom: 'solid 2px #888',
};
}
// TODO: logic is a mess for what to show
return (
<Pressable onPress={clearSquare} onLongPress={flagSquare} style={style} onPressIn={onPressIn} onPressOut={onPressOut}>
<Text style={{fontFamily: 'monospace', fontSize: 48}}>{cleared ? title : (flagged ? 'βš‘' : ' ')}</Text>
<Text style={{fontFamily: 'monospace', fontSize: 48}}>{cleared ? title : (gameover ? (hasMine ? (flagged ? 'x' : 'βœ“') : ' ') : (flagged ? 'βš‘' : ' '))}</Text>
</Pressable>
);
}
Expand Down
74 changes: 55 additions & 19 deletions Minesweeper/index.jsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,88 @@
import { Button, View, Text } from 'react-native';
import { useEffect, useState } from 'react';
import { useEffect, useState, useMemo } from 'react';
import { connect } from 'react-redux';

import { resetSquares, clearSquare, flagSquare } from './squares';

import Square from './Square';

let intervalId;

const Minesweeper = ({ squares, resetSquares, clearSquare, flagSquare }) => {
useEffect(() => void resetSquares(), []);

const [gameover, setGameover] = useState(false);
const [pressedIn, setPressedIn] = useState(false);
const [gameStartTime, setGameStartTime] = useState();
const [gameTime, setGameTime] = useState();

const pressSquare = ([x, y]) => {
clearSquare([x, y])
if (squares[x][y].hasMine) setGameover(true);
if (!gameStartTime) {
setGameStartTime(Date.now());
intervalId = setInterval(() => setGameTime(Date.now()), 100);
}
if (squares[x][y].hasMine) {
setGameover(true);
clearInterval(intervalId);
}
};

const timePassed = Math.floor((gameTime - gameStartTime) / 1000);

const newGame = () => {
resetSquares();
setGameStartTime(0);
setGameover(false);
clearInterval(intervalId);
};

const gotVictory = () => !gameover && squares.every(row => row.every(square => square.hasMine || square.cleared))

const calcMinesLeft = useMemo(
// TODO: replace 10, with the number of mines known
() => 10 - squares.reduce((minesLeft, row) =>
minesLeft + row.filter(s => s.flagged).length
, 0),
[squares]
);

let title = 'πŸ™‚';

if (pressedIn) title = '😯';
if (gameover) title = '😡';
if (gotVictory()) title = '😎';
if (gotVictory()) {
title = '😎';
// hacky: if we win, this will stop the timer.
intervalId && clearInterval(intervalId);
}

const textStyles = {color: '#FCC', backgroundColor: '#F00', font: '24px monospace'};

return (
<View>
{gameover && <Text>Game Over</Text>}
<Button title={title} onPress={() => newGame()} />
{squares.map((row, r) => (
<View key={r} style={{flexDirection: 'row'}}>
{row.map((square, c) => (
<Square
square={square}
clearSquare={() => !gameover && !squares[r][c].flagged && pressSquare([r, c])}
key={c}
flagSquare={() => !gameover && flagSquare([r, c])}
onPressIn={() => setPressedIn(true)}
onPressOut={() => setPressedIn(false)}
/>
))}
</View>
))}
<View style={{flexDirection: 'row', justifyContent: 'space-around'}}>
<Text style={textStyles}>{calcMinesLeft}</Text>
<Button title={title} onPress={() => newGame()} />
<Text style={textStyles}>{timePassed || '-'}</Text>
</View>
<View>
{squares.map((row, r) => (
<View key={r} style={{flexDirection: 'row'}}>
{row.map((square, c) => (
<Square
square={square}
clearSquare={() => !gameover && !squares[r][c].flagged && pressSquare([r, c])}
key={c}
flagSquare={() => !gameover && flagSquare([r, c])}
onPressIn={() => setPressedIn(true)}
onPressOut={() => setPressedIn(false)}
gameover={gameover}
/>
))}
</View>
))}
</View>
</View>
);
};
Expand Down

0 comments on commit 8d2dc3f

Please sign in to comment.