From cdb1cae631956b60f38406af06fdd874569b7007 Mon Sep 17 00:00:00 2001 From: Muhammad Zourdy Date: Sun, 7 Aug 2022 05:07:28 +0200 Subject: [PATCH 01/15] Add open-cell logic behaviour and create game-settings --- src/helpers/cells/cells-manipulator.test.ts | 114 +++++++++++++++++- src/helpers/cells/cells-manipulator.ts | 44 ++++++- src/modules/GameSettings.ts | 11 ++ .../GameWithHooks/GameWithHooks.test.tsx | 0 src/modules/GameWithHooks/GameWithHooks.tsx | 0 src/modules/GameWithHooks/hooks/.gitkeep | 0 tsconfig.json | 3 +- webpack/config/alias.js | 1 + 8 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 src/modules/GameSettings.ts create mode 100644 src/modules/GameWithHooks/GameWithHooks.test.tsx create mode 100644 src/modules/GameWithHooks/GameWithHooks.tsx create mode 100644 src/modules/GameWithHooks/hooks/.gitkeep diff --git a/src/helpers/cells/cells-manipulator.test.ts b/src/helpers/cells/cells-manipulator.test.ts index 0af72cc1..e8da5e76 100644 --- a/src/helpers/cells/cells-manipulator.test.ts +++ b/src/helpers/cells/cells-manipulator.test.ts @@ -1,7 +1,7 @@ import { CellState, Field } from "../field"; -import { checkItemInField, getNeighbours, incrementNeighbours } from "./cells-manipulator"; +import { checkItemInField, getNeighbours, incrementNeighbours, openCell } from "./cells-manipulator"; -const { empty, bomb } = CellState; +const { empty, bomb, hidden } = CellState; describe("Check neighbours selectors", function () { it("should render with [0, 0] as coordinates value", function () { @@ -112,3 +112,113 @@ describe("Check Increment Neighbours on each cells", () => { }); }); }); + +describe("Open cell action", () => { + describe("Simple cases with loose", () => { + it("Open cell with the bomb", () => { + expect(() => + openCell( + [1, 1], + [ + [hidden, hidden], + [hidden, hidden], + ], + [ + [1, 1], + [1, bomb], + ] + ) + ).toThrow("Game Over"); + }); + }); + describe("Open cell with number", () => { + it("Open cell with state == 1", () => { + const playerField = openCell( + [1, 1], + [ + [hidden, hidden, hidden], + [hidden, hidden, hidden], + [hidden, hidden, hidden], + ], + [ + [1, 1, 0], + [9, 1, 0], + [1, 1, 0], + ] + ); + expect(playerField).toStrictEqual([ + [hidden, hidden, hidden], + [hidden, 1, hidden], + [hidden, hidden, hidden], + ]); + }); + it("Open cell with state == 3", () => { + const playerField = openCell( + [1, 1], + [ + [hidden, hidden, hidden], + [hidden, hidden, hidden], + [hidden, hidden, hidden], + ], + [ + [9, 2, 0], + [9, 3, 0], + [9, 2, 0], + ] + ); + expect(playerField).toStrictEqual([ + [hidden, hidden, hidden], + [hidden, 3, hidden], + [hidden, hidden, hidden], + ]); + }); + }); + describe("Open empty cell", () => { + it("Open empty cell, simple 3*3 case", () => { + const playerField = openCell( + [1, 2], + [ + [hidden, hidden, hidden], + [hidden, hidden, hidden], + [hidden, hidden, hidden], + ], + [ + [1, 1, 0], + [9, 1, 0], + [1, 1, 0], + ] + ); + expect(playerField).toStrictEqual([ + [hidden, 1, 0], + [hidden, 1, 0], + [hidden, 1, 0], + ]); + }); + it("Open empty cell 5*5 case", () => { + const playerField = openCell( + [2, 2], + [ + [hidden, hidden, hidden, hidden, hidden], + [hidden, hidden, hidden, hidden, hidden], + [hidden, hidden, hidden, hidden, hidden], + [hidden, hidden, hidden, hidden, hidden], + [hidden, hidden, hidden, hidden, hidden], + ], + [ + [9, 9, 1, 1, 2], + [9, 3, 1, 0, 0], + [1, 1, 0, 1, 1], + [1, 0, 0, 1, 9], + [2, 1, 0, 1, 0], + ] + ); + expect(playerField).toStrictEqual([ + [hidden, hidden, 1, 1, 2], + [hidden, 3, 1, 0, 0], + [1, 1, 0, 1, 1], + [1, 0, 0, 1, hidden], + [2, 1, 0, 1, hidden], + ]); + }); + }); +}); diff --git a/src/helpers/cells/cells-manipulator.ts b/src/helpers/cells/cells-manipulator.ts index f4ad1370..f4e5e85f 100644 --- a/src/helpers/cells/cells-manipulator.ts +++ b/src/helpers/cells/cells-manipulator.ts @@ -1,4 +1,4 @@ -import { Cell, Coordinates, Field } from "../field"; +import { Cell, CellState, Coordinates, Field } from "../field"; /** * Get neighbour cells indexes @@ -40,3 +40,45 @@ export const incrementNeighbours = (coords: Coordinates, field: Field): Field => return field; }; + +/** + * Open cell in the player field using game field info + * @param {Coords} coords + * @param {Field} playerField + * @param {Field} gameField + * @returns {Field} + */ + +export const openCell = (coords: Coordinates, playerField: Field, gameField: Field): Field => { + const { empty, hidden, bomb } = CellState; + + const [y, x] = coords; + const gameCell = gameField[y][x]; + + if (gameCell === bomb) throw new Error("Game Over!"); + + if (gameCell === empty) { + playerField[y][x] = gameCell; + + const items = getNeighbours(coords); + + for (const [y, x] of Object.values(items)) { + if (checkItemInField([y, x], gameField)) { + const scopedGameCell = gameField[y][x]; + const scopedPlayerCell = playerField[y][x]; + + if (scopedGameCell === empty && scopedPlayerCell === hidden) { + playerField = openCell([y, x], playerField, gameField); + } + + if (scopedGameCell < bomb) { + playerField[y][x] = scopedGameCell; + } + } + } + } + + playerField[y][x] = gameCell; + + return playerField; +}; diff --git a/src/modules/GameSettings.ts b/src/modules/GameSettings.ts new file mode 100644 index 00000000..abd911fa --- /dev/null +++ b/src/modules/GameSettings.ts @@ -0,0 +1,11 @@ +export const GameLevels = ["beginner", "intermediate", "expert"] as const; + +export type LevelNames = typeof GameLevels[number]; + +export type Settings = [number, number]; + +export const GameSettings: Record = { + beginner: [9, 10], + intermediate: [16, 44], + expert: [22, 99], +}; diff --git a/src/modules/GameWithHooks/GameWithHooks.test.tsx b/src/modules/GameWithHooks/GameWithHooks.test.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/modules/GameWithHooks/GameWithHooks.tsx b/src/modules/GameWithHooks/GameWithHooks.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/modules/GameWithHooks/hooks/.gitkeep b/src/modules/GameWithHooks/hooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tsconfig.json b/tsconfig.json index e37d53f1..cd8d5d46 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,7 +23,8 @@ "@assets/*": ["src/assets/*"], "@helpers/*": ["src/helpers/*"], "~types/*": ["src/@types/*"], - "~hooks/*": ["src/hooks/*"] + "~hooks/*": ["src/hooks/*"], + "@modules": ["src/modules/*"] }, "allowSyntheticDefaultImports": true, "esModuleInterop": true, diff --git a/webpack/config/alias.js b/webpack/config/alias.js index 4a3518e0..63b6346a 100644 --- a/webpack/config/alias.js +++ b/webpack/config/alias.js @@ -12,6 +12,7 @@ export const aliasItems = { "@components": join(rootDir, "/src/components"), "@assets": join(rootDir, "/src/assets"), "@helpers": join(rootDir, "/src/helpers"), + "@modules": join(rootDir, "/src/modules"), "~types": join(rootDir, "/src/@types"), "~hooks": join(rootDir, "/src/hooks"), }; From f82ec63eb9f4f82d3be81d604405d7f86e839fbc Mon Sep 17 00:00:00 2001 From: Muhammad Zourdy Date: Sun, 7 Aug 2022 08:18:04 +0200 Subject: [PATCH 02/15] Add `game-with-hooks` game module --- .../game-area/game-section-example.tsx | 2 +- .../scoreboard/components/level/level.tsx | 5 +-- src/components/scoreboard/scoreboard.test.tsx | 4 +-- src/components/scoreboard/scoreboard.tsx | 17 +++++++-- src/index.tsx | 7 ++-- src/modules/GameWithHooks/GameWithHooks.tsx | 35 +++++++++++++++++++ src/modules/GameWithHooks/index.ts | 1 + 7 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 src/modules/GameWithHooks/index.ts diff --git a/src/components/game-area/game-section-example.tsx b/src/components/game-area/game-section-example.tsx index dc99692b..f87484c2 100644 --- a/src/components/game-area/game-section-example.tsx +++ b/src/components/game-area/game-section-example.tsx @@ -18,7 +18,7 @@ export const GameSectionExample: FunctionComponent = () => { mines="000" levels={["beginner", "intermediate", "expert"]} onReset={() => null} - onChange={() => null} + onChangeLevel={() => null} /> null} isWin={true} /> null} onContextMenu={() => null} /> diff --git a/src/components/scoreboard/components/level/level.tsx b/src/components/scoreboard/components/level/level.tsx index fd1f8427..828a621a 100644 --- a/src/components/scoreboard/components/level/level.tsx +++ b/src/components/scoreboard/components/level/level.tsx @@ -5,8 +5,9 @@ import styles from "./level.module.scss"; export const Level: FunctionComponent<{ levelData: string[]; onChange: (event: ChangeEvent) => void; -}> = ({ levelData, onChange }) => ( - {levelData.map((item: string) => { return (