1
Fork 0

Add more logic

This commit is contained in:
Hadeed 2024-06-02 21:52:05 +04:00
parent 0918fe65fa
commit 5ea9e93239
8 changed files with 106 additions and 32 deletions

View file

@ -4,7 +4,7 @@ name: Deploy static content to Pages
on: on:
# Runs on pushes targeting the default branch # Runs on pushes targeting the default branch
push: push:
branches: ['main'] branches: ["main"]
# Allows you to run this workflow manually from the Actions tab # Allows you to run this workflow manually from the Actions tab
workflow_dispatch: workflow_dispatch:
@ -17,7 +17,7 @@ permissions:
# Allow one concurrent deployment # Allow one concurrent deployment
concurrency: concurrency:
group: 'pages' group: "pages"
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
@ -34,7 +34,7 @@ jobs:
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 20 node-version: 20
cache: 'npm' cache: "npm"
- name: Install dependencies - name: Install dependencies
run: | run: |
rm package-lock.json rm package-lock.json
@ -47,7 +47,7 @@ jobs:
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@v3
with: with:
# Upload dist folder # Upload dist folder
path: './dist' path: "./dist"
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v4 uses: actions/deploy-pages@v4

View file

@ -71,15 +71,17 @@ To see how you can add code snippets, see below:
```html ```html
<h1>Some HTML code I'm proud of</h1> <h1>Some HTML code I'm proud of</h1>
``` ```
```css ```css
.proud-of-this-css { .proud-of-this-css {
color: papayawhip; color: papayawhip;
} }
``` ```
```js ```js
const proudOfThisFunc = () => { const proudOfThisFunc = () => {
console.log('🎉') console.log("🎉");
} };
``` ```
If you want more help with writing markdown, we'd recommend checking out [The Markdown Guide](https://www.markdownguide.org/) to learn more. If you want more help with writing markdown, we'd recommend checking out [The Markdown Guide](https://www.markdownguide.org/) to learn more.

View file

@ -1,12 +1,15 @@
import MainMenu from "./mainMenu"; import MainMenu from "./mainMenu";
import Game from "./game"; import Game from "./game";
import Modal from "./modal"; import { useStore } from "./store";
export default () => { export default () => {
const isGameRunning = useStore((state) => state.isGameRunning);
const gameKey = useStore((state) => state.gameKey);
const players = useStore((state) => state.players);
return ( return (
<main className="flex min-h-screen items-center justify-center bg-navy-700"> <main className="flex min-h-screen items-center justify-center bg-navy-700">
{/* <MainMenu /> */} {isGameRunning ? <Game players={players} key={gameKey} /> : <MainMenu />}
<Game />
</main> </main>
); );
}; };

View file

@ -8,9 +8,39 @@ import OvalOutline from "../assets/icon-o-outline.svg?react";
import logo from "../assets/logo.svg"; import logo from "../assets/logo.svg";
import restart from "../assets/icon-restart.svg"; import restart from "../assets/icon-restart.svg";
import { restartGame } from "./store";
import Modal from "./modal"; import Modal from "./modal";
export default () => { const getWinner = (grid) => {
const combos = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
const wins = (combo) => {
const symbols = combo.map((i) => grid[i]);
return symbols.every((symbol) => symbol == symbols[0] && symbol != "");
};
const winningCombo = combos.find(wins);
if (winningCombo) {
return grid[winningCombo[0]];
}
return "";
};
export default ({ players: _players }) => {
const [score, updateScore] = useImmer({ X: 0, O: 0, ties: 0 });
const [grid, updateGrid] = useImmer(Array(9).fill("")); const [grid, updateGrid] = useImmer(Array(9).fill(""));
const [modal, setModal] = useState(false); const [modal, setModal] = useState(false);
@ -18,6 +48,15 @@ export default () => {
const TurnOutline = turn == "X" ? CrossOutline : OvalOutline; const TurnOutline = turn == "X" ? CrossOutline : OvalOutline;
const TurnIndicator = turn == "X" ? Cross : Oval; const TurnIndicator = turn == "X" ? Cross : Oval;
const winner = getWinner(grid);
if (winner) {
updateScore((score) => {
score[winner]++;
});
updateGrid(() => Array(9).fill(""));
}
const renderSymbol = (symbol) => { const renderSymbol = (symbol) => {
if (symbol == "") { if (symbol == "") {
let colorClass = turn == "X" ? "text-blue-700" : "text-yellow-700"; let colorClass = turn == "X" ? "text-blue-700" : "text-yellow-700";
@ -77,16 +116,16 @@ export default () => {
<footer className="flex items-center justify-between text-navy-700"> <footer className="flex items-center justify-between text-navy-700">
<div className="flex h-20 w-36 flex-col items-center justify-center rounded-2xl bg-blue-700"> <div className="flex h-20 w-36 flex-col items-center justify-center rounded-2xl bg-blue-700">
<p className="text-base uppercase">X (you)</p> <p className="text-base uppercase">X ({_players.X})</p>
<p className="text-h-m uppercase">14</p> <p className="text-h-m uppercase">{score.X}</p>
</div> </div>
<div className="flex h-20 w-36 flex-col items-center justify-center rounded-2xl bg-silver-700"> <div className="flex h-20 w-36 flex-col items-center justify-center rounded-2xl bg-silver-700">
<p className="text-base uppercase">Ties</p> <p className="text-base uppercase">Ties</p>
<p className="text-h-m uppercase">32</p> <p className="text-h-m uppercase">{score.ties}</p>
</div> </div>
<div className="flex h-20 w-36 flex-col items-center justify-center rounded-2xl bg-yellow-700"> <div className="flex h-20 w-36 flex-col items-center justify-center rounded-2xl bg-yellow-700">
<p className="text-base uppercase">O (cpu)</p> <p className="text-base uppercase">O ({_players.O})</p>
<p className="text-h-m uppercase">11</p> <p className="text-h-m uppercase">{score.O}</p>
</div> </div>
</footer> </footer>
</div> </div>
@ -106,9 +145,7 @@ export default () => {
<p className="text-h-xs uppercase">No, cancel</p> <p className="text-h-xs uppercase">No, cancel</p>
</button> </button>
<button <button
onClick={() => { onClick={restartGame}
updateGrid(() => Array(9).fill(""));
}}
className="rounded-xl bg-yellow-700 px-5 py-4 inner-shadow-1-yellow-900 hover:bg-yellow-400" className="rounded-xl bg-yellow-700 px-5 py-4 inner-shadow-1-yellow-900 hover:bg-yellow-400"
> >
<p className="text-h-xs uppercase">Yes, restart</p> <p className="text-h-xs uppercase">Yes, restart</p>

View file

@ -1,12 +1,24 @@
import * as RadioGroup from "@radix-ui/react-radio-group"; import * as RadioGroup from "@radix-ui/react-radio-group";
import { useState } from "react";
import logo from "../assets/logo.svg"; import logo from "../assets/logo.svg";
import Cross from "../assets/icon-x.svg?react"; import Cross from "../assets/icon-x.svg?react";
import Oval from "../assets/icon-o.svg?react"; import Oval from "../assets/icon-o.svg?react";
import { useStore, setPlayerOneSymbol } from "./store";
import { setIsGameRunning, updatePlayers } from "./store";
export default () => { export default () => {
const playerOneSymbol = useStore((state) => state.playerOneSymbol); const [playerOneSymbol, setPlayerOneSymbol] = useState("X");
const playerTwoSymbol = playerOneSymbol == "X" ? "O" : "X";
const startGame = (playerTwo) => {
updatePlayers({
[playerOneSymbol]: "P1",
[playerTwoSymbol]: playerTwo,
});
setIsGameRunning(true);
};
return ( return (
<div className="m-6 flex w-full max-w-lg flex-col items-center space-y-10"> <div className="m-6 flex w-full max-w-lg flex-col items-center space-y-10">
@ -22,8 +34,8 @@ export default () => {
loop={false} loop={false}
> >
{[ {[
["cross", Cross], ["X", Cross],
["oval", Oval], ["O", Oval],
].map(([value, Symbol]) => ( ].map(([value, Symbol]) => (
<RadioGroup.Item <RadioGroup.Item
className="group h-full w-1/2 rounded-xl hover:bg-silver-700/5 data-[state='checked']:bg-silver-700" className="group h-full w-1/2 rounded-xl hover:bg-silver-700/5 data-[state='checked']:bg-silver-700"
@ -43,10 +55,16 @@ export default () => {
</p> </p>
</div> </div>
<div className="w-full space-y-5"> <div className="w-full space-y-5">
<button className="flex w-full items-center justify-center rounded-2xl bg-yellow-700 p-4 inner-shadow-2-yellow-900 hover:bg-yellow-400"> <button
onClick={() => startGame("CPU")}
className="flex w-full items-center justify-center rounded-2xl bg-yellow-700 p-4 inner-shadow-2-yellow-900 hover:bg-yellow-400"
>
<p className="text-h-s uppercase text-navy-700">New game (vs cpu)</p> <p className="text-h-s uppercase text-navy-700">New game (vs cpu)</p>
</button> </button>
<button className="flex w-full items-center justify-center rounded-2xl bg-blue-700 p-4 inner-shadow-2-blue-900 hover:bg-blue-400"> <button
onClick={() => startGame("P2")}
className="flex w-full items-center justify-center rounded-2xl bg-blue-700 p-4 inner-shadow-2-blue-900 hover:bg-blue-400"
>
<p className="text-h-s uppercase text-navy-700"> <p className="text-h-s uppercase text-navy-700">
New game (vs player) New game (vs player)
</p> </p>

View file

@ -17,7 +17,7 @@ export default ({ isOpen, children, className, onClose }) => {
return ( return (
<dialog <dialog
className="backdrop:bg-black/50 h-64 w-screen max-w-[100vw] bg-navy-700" className="h-64 w-screen max-w-[100vw] bg-navy-700 backdrop:bg-black/50"
ref={ref} ref={ref}
> >
<div className="flex h-full w-full items-center justify-center"> <div className="flex h-full w-full items-center justify-center">

View file

@ -1,8 +1,22 @@
import { produce } from "immer";
import { create } from "zustand"; import { create } from "zustand";
export const useStore = create((set) => ({ export const useStore = create((set) => ({
playerOneSymbol: "cross", isGameRunning: false,
gameKey: 0,
players: {
X: "",
O: "",
},
})); }));
export const setPlayerOneSymbol = (playerOneSymbol) => export const setIsGameRunning = (isGameRunning) =>
useStore.setState(() => ({ playerOneSymbol })); useStore.setState(() => ({ isGameRunning }));
export const updatePlayers = (players) =>
useStore.setState(() => ({ players }));
export const restartGame = () =>
useStore.setState(({ gameKey }) => ({
gameKey: 1 - gameKey,
}));