Skip to content

Commit 628d936

Browse files
feat: support game lost (#17)
* feat: support game lost * feat: ui tweaks * chore: clean up Signed-off-by: mateusz <[email protected]> * chore: clean up Signed-off-by: mateusz <[email protected]> * chore: clean up Signed-off-by: mateusz <[email protected]> --------- Signed-off-by: mateusz <[email protected]>
1 parent e586fd6 commit 628d936

File tree

6 files changed

+47
-10
lines changed

6 files changed

+47
-10
lines changed

components/board.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ export default function Board() {
8787
return (
8888
<MobileSwiper onSwipe={handleSwipe}>
8989
<div className={styles.board}>
90-
{status === "won" && <Splash heading="You won!" />}
90+
{status === "won" && <Splash heading="You won!" type="won" />}
91+
{status === "lost" && <Splash heading="You lost!" />}
9192
<div className={styles.tiles}>{renderTiles()}</div>
9293
<div className={styles.grid}>{renderGrid()}</div>
9394
</div>

components/splash.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { GameContext } from "@/context/game-context";
22
import styles from "@/styles/splash.module.css";
33
import { useContext } from "react";
44

5-
export default function Splash({ heading = "You won!" }) {
5+
export default function Splash({ heading = "You won!", type = "" }) {
66
const { startGame } = useContext(GameContext);
77

88
return (
9-
<div className={`${styles.splash} ${styles.win}`}>
9+
<div className={`${styles.splash} ${type === "won" && styles.win}`}>
1010
<div>
1111
<h1>{heading}</h1>
1212
<button className={styles.button} onClick={startGame}>

context/game-context.tsx

+32-1
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,50 @@ export default function GameProvider({ children }: PropsWithChildren) {
7878

7979
if (isWon) {
8080
dispatch({ type: "update_status", status: "won" });
81+
return;
8182
}
83+
84+
const { tiles, board } = gameState;
85+
86+
const maxIndex = tileCountPerDimension - 1;
87+
for (let x = 0; x < maxIndex; x += 1) {
88+
for (let y = 0; y < maxIndex; y += 1) {
89+
if (
90+
isNil(gameState.board[x][y]) ||
91+
isNil(gameState.board[x + 1][y]) ||
92+
isNil(gameState.board[x][y + 1])
93+
) {
94+
return;
95+
}
96+
97+
if (tiles[board[x][y]].value === tiles[board[x + 1][y]].value) {
98+
return;
99+
}
100+
101+
if (tiles[board[x][y]].value === tiles[board[x][y + 1]].value) {
102+
return;
103+
}
104+
}
105+
}
106+
107+
dispatch({ type: "update_status", status: "lost" });
82108
};
83109

84110
useEffect(() => {
85111
if (gameState.hasChanged) {
86112
setTimeout(() => {
87113
dispatch({ type: "clean_up" });
88114
appendRandomTile();
89-
checkGameState();
90115
}, mergeAnimationDuration);
91116
}
92117
}, [gameState.hasChanged]);
93118

119+
useEffect(() => {
120+
if (!gameState.hasChanged) {
121+
checkGameState();
122+
}
123+
}, [gameState.hasChanged]);
124+
94125
return (
95126
<GameContext.Provider
96127
value={{

reducers/game-reducer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { uid } from "uid";
33
import { tileCountPerDimension } from "@/constants";
44
import { Tile, TileMap } from "@/models/tile";
55

6-
type GameStatus = "ongoing" | "won";
6+
type GameStatus = "ongoing" | "won" | "lost";
77

88
type State = {
99
board: string[][];

styles/globals.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
/* Backgrounds */
55
--primary-background: #faf8ef;
6-
--secondary-background: #bbada0;
7-
--cell-background: #cac1b5;
6+
--secondary-background: #b59d87;
7+
--cell-background: #cebda6;
88
--tile-background: #eee4da;
99
--button-background: #8f7a66;
1010

styles/splash.module.css

+8-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
right: 0;
1111
bottom: 0;
1212
border-radius: calc(var(--pixel-size) * 0.75);
13-
background: rgba(238, 228, 218, 0.6);
13+
background: rgba(181, 157, 135, 0.6);
1414
}
1515

1616
.win {
@@ -26,13 +26,18 @@
2626
margin: calc(var(--pixel-size) * 3) auto;
2727
}
2828

29+
.splash > div > h1 {
30+
color: rgba(240, 240, 240, 1);
31+
}
32+
2933
.button {
3034
background: var(--button-background);
31-
border: calc(var(--pixel-size) * 0.5) solid var(--button-background);
35+
border: calc(var(--pixel-size) * 0.125) solid var(--primary-background);
3236
border-radius: calc(var(--pixel-size) * 0.5);
3337
font-size: calc(var(--pixel-size) * 2);
3438
line-height: calc(var(--pixel-size) * 4);
39+
padding: calc(var(--pixel-size) * 0.5) calc(var(--pixel-size) * 2);
3540
font-weight: bold;
36-
color: var(--tile-text-color);
41+
color: white;
3742
cursor: pointer;
3843
}

0 commit comments

Comments
 (0)