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

View file

@ -71,15 +71,17 @@ To see how you can add code snippets, see below:
```html
<h1>Some HTML code I'm proud of</h1>
```
```css
.proud-of-this-css {
color: papayawhip;
}
```
```js
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.

View file

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

View file

@ -8,9 +8,39 @@ import OvalOutline from "../assets/icon-o-outline.svg?react";
import logo from "../assets/logo.svg";
import restart from "../assets/icon-restart.svg";
import { restartGame } from "./store";
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 [modal, setModal] = useState(false);
@ -18,6 +48,15 @@ export default () => {
const TurnOutline = turn == "X" ? CrossOutline : OvalOutline;
const TurnIndicator = turn == "X" ? Cross : Oval;
const winner = getWinner(grid);
if (winner) {
updateScore((score) => {
score[winner]++;
});
updateGrid(() => Array(9).fill(""));
}
const renderSymbol = (symbol) => {
if (symbol == "") {
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">
<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-h-m uppercase">14</p>
<p className="text-base uppercase">X ({_players.X})</p>
<p className="text-h-m uppercase">{score.X}</p>
</div>
<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-h-m uppercase">32</p>
<p className="text-h-m uppercase">{score.ties}</p>
</div>
<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-h-m uppercase">11</p>
<p className="text-base uppercase">O ({_players.O})</p>
<p className="text-h-m uppercase">{score.O}</p>
</div>
</footer>
</div>
@ -106,9 +145,7 @@ export default () => {
<p className="text-h-xs uppercase">No, cancel</p>
</button>
<button
onClick={() => {
updateGrid(() => Array(9).fill(""));
}}
onClick={restartGame}
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>

View file

@ -1,12 +1,24 @@
import * as RadioGroup from "@radix-ui/react-radio-group";
import { useState } from "react";
import logo from "../assets/logo.svg";
import Cross from "../assets/icon-x.svg?react";
import Oval from "../assets/icon-o.svg?react";
import { useStore, setPlayerOneSymbol } from "./store";
import { setIsGameRunning, updatePlayers } from "./store";
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 (
<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}
>
{[
["cross", Cross],
["oval", Oval],
["X", Cross],
["O", Oval],
].map(([value, Symbol]) => (
<RadioGroup.Item
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>
</div>
<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>
</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">
New game (vs player)
</p>

View file

@ -17,7 +17,7 @@ export default ({ isOpen, children, className, onClose }) => {
return (
<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}
>
<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";
export const useStore = create((set) => ({
playerOneSymbol: "cross",
isGameRunning: false,
gameKey: 0,
players: {
X: "",
O: "",
},
}));
export const setPlayerOneSymbol = (playerOneSymbol) =>
useStore.setState(() => ({ playerOneSymbol }));
export const setIsGameRunning = (isGameRunning) =>
useStore.setState(() => ({ isGameRunning }));
export const updatePlayers = (players) =>
useStore.setState(() => ({ players }));
export const restartGame = () =>
useStore.setState(({ gameKey }) => ({
gameKey: 1 - gameKey,
}));