Mercurial
diff react_games/public/games/main-QNFKFAB2.js @ 37:fb9bcd3145cb
[ReactGames] Few games I made using react just to practice few things.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 01 Dec 2025 20:22:47 -0800 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/react_games/public/games/main-QNFKFAB2.js Mon Dec 01 20:22:47 2025 -0800 @@ -0,0 +1,194 @@ +import { + __toESM, + require_jsx_runtime, + require_react +} from "./chunk-AX5M7HF6.js"; + +// src/Minesweeper/main.tsx +var import_react = __toESM(require_react()); +var import_jsx_runtime = __toESM(require_jsx_runtime()); +var MAX_SIZE_LEN = 10; +var N_BOMBS = 10; +var DIRECTION = [ + [0, 1], + [1, 1], + [1, 0], + [1, -1], + [0, -1], + [-1, -1], + [-1, 0], + [-1, 1] +]; +var constructGameState = () => { + let board = Array.from( + { length: MAX_SIZE_LEN }, + () => Array.from( + { length: MAX_SIZE_LEN }, + () => ({ + value: 0 /* EMPTY */, + numberOfAdjacentBomb: 0, + isShown: false, + isFlag: false + }) + ) + ); + let placedBomb = 0; + const bombPlacments = []; + while (placedBomb < N_BOMBS) { + const bombRowIdx = Math.floor(Math.random() * MAX_SIZE_LEN); + const bombColIdx = Math.floor(Math.random() * MAX_SIZE_LEN); + if (board[bombRowIdx][bombColIdx].value === 0 /* EMPTY */) { + board[bombRowIdx][bombColIdx] = { + ...board[bombRowIdx][bombColIdx], + value: 1 /* BOMB */ + }; + placedBomb++; + bombPlacments.push([bombRowIdx, bombColIdx]); + } + } + for (const [bombR, bombC] of bombPlacments) { + for (const [dr, dc] of DIRECTION) { + if (board[bombR + dr]?.[bombC + dc]?.value === 0 /* EMPTY */) { + board[bombR + dr][bombC + dc] = { + ...board[bombR + dr][bombC + dc], + numberOfAdjacentBomb: board[bombR + dr][bombC + dc].numberOfAdjacentBomb + 1 + }; + } + } + } + return { + board, + status: "Reveal all the map while not clicking on mine" /* PLAYABLE */ + }; +}; +var gameStateReducer = (state, action) => { + switch (action.type) { + case 0 /* CHECK */: + const { position } = action; + const board = state.board.map((row) => row.map((col) => ({ ...col }))); + const start = board[position.row][position.col]; + if (start.value === 1 /* BOMB */) { + for (const row of board) for (const cell of row) cell.isShown = true; + return { board, status: "YOU LOST" /* LOST */ }; + } + if (!start.isShown) start.isShown = true; + if (start.numberOfAdjacentBomb === 0) { + const q = [position]; + while (q.length) { + const { row, col } = q.shift(); + for (const [dr, dc] of DIRECTION) { + const r = row + dr, c = col + dc; + const n = board[r]?.[c]; + if (!n || n.isShown || n.value === 1 /* BOMB */) continue; + n.isShown = true; + if (n.numberOfAdjacentBomb === 0) q.push({ row: r, col: c }); + } + } + } + const hidden = board.flat().filter((c) => !c.isShown).length; + const status = hidden === N_BOMBS ? "YOU WON" /* WON */ : "Reveal all the map while not clicking on mine" /* PLAYABLE */; + return { board, status }; + case 2 /* FLAG */: + const newBoard = state.board.map( + (row, rowIdx) => rowIdx === action.position.row ? row.map( + (col, colIdx) => colIdx === action.position.col ? { ...col, isFlag: true } : col + ) : row + ); + console.log(newBoard); + return { + ...state, + board: newBoard + }; + case 1 /* RESET */: + return constructGameState(); + } +}; +var styles = { + board: { + display: "grid", + gridTemplateColumns: `repeat(${MAX_SIZE_LEN}, 1fr)`, + width: 400 + }, + cell: { + display: "flex", + justifyContent: "center", + alignItems: "center", + width: "100%", + aspectRatio: "1 / 1", + border: "1px solid black", + backgroundColor: "#e6e6e6" + } +}; +var CellComponent = (0, import_react.memo)(({ + cellValue, + row, + col, + placeDispatch, + flagDispatch +}) => { + console.log("re-render"); + const handleOnClikck = (0, import_react.useCallback)(() => { + placeDispatch(row, col); + }, [row, col, placeDispatch]); + const handleOnRightClikck = (0, import_react.useCallback)((event) => { + event.preventDefault(); + flagDispatch(row, col); + }, [row, col, placeDispatch]); + return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( + "div", + { + style: { + ...styles.cell, + cursor: "pointer", + backgroundColor: cellValue.isShown ? "#fafafa" : "#e6e6e6" + }, + onClick: handleOnClikck, + onContextMenu: handleOnRightClikck, + children: cellValue.isShown ? cellValue.value === 1 /* BOMB */ ? "\u{1F4A3}" : cellValue.numberOfAdjacentBomb || "" : cellValue.isFlag ? "\u{1F6A9}" : "" + } + ); +}, (prev, next) => prev.cellValue.isShown === next.cellValue.isShown && prev.cellValue.isFlag === next.cellValue.isFlag); +var Minesweeper = () => { + const [state, dispatch] = (0, import_react.useReducer)(gameStateReducer, null, constructGameState); + const placeDispatch = (0, import_react.useCallback)( + (row, col) => { + dispatch({ type: 0 /* CHECK */, position: { row, col } }); + }, + [dispatch] + ); + const flagDispatch = (0, import_react.useCallback)( + (row, col) => { + dispatch({ type: 2 /* FLAG */, position: { row, col } }); + }, + [dispatch] + ); + return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ + /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h1", { children: [ + " ", + state.status, + " " + ] }), + /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.board, children: state.board.map( + (row, rowIdx) => row.map( + (cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)( + CellComponent, + { + cellValue: cell, + row: rowIdx, + col: colIdx, + placeDispatch, + flagDispatch + }, + `${rowIdx}-${colIdx}` + ) + ) + ) }), + /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => { + dispatch({ type: 1 /* RESET */ }); + }, children: " reset " }) + ] }); +}; +export { + Minesweeper +}; +//# sourceMappingURL=main-QNFKFAB2.js.map