aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorVidhu Kant Sharma <araararagikoyomi@protonmail.com>2021-07-25 01:13:24 +0530
committerGitHub <noreply@github.com>2021-07-25 01:13:24 +0530
commit6b58ffac163b9b3637bfab1294069c55b6d5702c (patch)
tree95f270639f3a2fc6aa936961d9787a59a63b079e /src/components
parent166f8d4262729b2f771c30f8e71a305052cc13d5 (diff)
parentb353dda4df7fc7be973e52a2f529360e7bfc8fed (diff)
Merge pull request #1 from MikunoNaka/multiplayer
Merge multiplayer into master
Diffstat (limited to 'src/components')
-rw-r--r--src/components/App.js90
-rw-r--r--src/components/App.tsx42
-rw-r--r--src/components/Box.js (renamed from src/components/Box.tsx)8
-rw-r--r--src/components/Footer.js (renamed from src/components/Footer.tsx)2
-rw-r--r--src/components/GamemodeChooser.js63
-rw-r--r--src/components/Grid.js (renamed from src/components/Grid.tsx)50
-rw-r--r--src/components/MessageBox.js (renamed from src/components/MessageBox.tsx)9
-rw-r--r--src/components/MultiplayerGrid.js77
-rw-r--r--src/components/MultiplayerMenu.js40
-rw-r--r--src/components/ScoreBoard.js (renamed from src/components/ScoreBoard.tsx)15
-rw-r--r--src/components/style.css30
11 files changed, 317 insertions, 109 deletions
diff --git a/src/components/App.js b/src/components/App.js
new file mode 100644
index 0000000..db5af1b
--- /dev/null
+++ b/src/components/App.js
@@ -0,0 +1,90 @@
+/*
+ * Tic Tac Toe - Minimalistic Tic Tac Toe
+ * Copyright (C) 2021 Vidhu Kant Sharma
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import React, { useState } from 'react';
+import GamemodeChooser from './GamemodeChooser';
+import MessageBox from './MessageBox';
+import ScoreBoard from './ScoreBoard';
+import Grid from './Grid';
+import MultiplayerGrid from './MultiplayerGrid';
+import Footer from './Footer';
+import './style.css';
+
+const App = () => {
+ const [gameStarted, setGameStarted] = useState(false);
+ const [multiplayer, setMultiplayer] = useState(false);
+ const [scoreX, setScoreX] = useState(0);
+ const [scoreO, setScoreO] = useState(0);
+ const [turn, setTurn] = useState(1);
+ const [showMessageBox, setShowMessageBox] = useState(false);
+ const [message, setMessage] = useState("");
+ const [isHost, setIsHost] = useState(false);
+
+ return gameStarted ? (
+ <>
+ {showMessageBox &&
+ <MessageBox
+ message={message}
+ setShowMessage={setShowMessageBox}
+ />
+ }
+
+ <ScoreBoard
+ turn={turn}
+ scoreX={scoreX}
+ scoreO={scoreO}
+ multiplayer={multiplayer}
+ isHost={isHost}
+ />
+
+ {multiplayer ? <MultiplayerGrid
+ turn={turn}
+ isHost={isHost}
+ setTurn={setTurn}
+ scoreX={scoreX}
+ setScoreX={setScoreX}
+ scoreO={scoreO}
+ setScoreO={setScoreO}
+ setMessage={setMessage}
+ setShowMessage={setShowMessageBox}
+ /> : <Grid
+ turn={turn}
+ setTurn={setTurn}
+ scoreX={scoreX}
+ setScoreX={setScoreX}
+ scoreO={scoreO}
+ setScoreO={setScoreO}
+ setMessage={setMessage}
+ setShowMessage={setShowMessageBox}
+ />
+ }
+
+ <Footer/>
+ </>
+ ) : (
+ <>
+ <GamemodeChooser
+ setMultiplayer={setMultiplayer}
+ setGameStarted={setGameStarted}
+ setIsHost={setIsHost}
+ />
+ <Footer/>
+ </>
+ );
+}
+
+export default App;
diff --git a/src/components/App.tsx b/src/components/App.tsx
deleted file mode 100644
index 6a9c60e..0000000
--- a/src/components/App.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Tic Tac Toe - Minimalistic Tic Tac Toe
- * Copyright (C) 2021 Vidhu Kant Sharma
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-import React, { useState } from 'react';
-import MessageBox from './MessageBox';
-import ScoreBoard from './ScoreBoard';
-import Grid from './Grid';
-import Footer from './Footer';
-import './style.css';
-
-const App: React.FC = () => {
- const [scoreX, setScoreX] = useState<number>(0);
- const [scoreO, setScoreO] = useState<number>(0);
- const [turn, setTurn] = useState<number>(0);
- const [showMessageBox, setShowMessageBox] = useState<boolean>(false);
- const [message, setMessage] = useState<string>("");
- return (
- <>
- {showMessageBox && <MessageBox message={message} setShowMessage={setShowMessageBox}/>}
- <ScoreBoard turn={turn} scoreX={scoreX} scoreO={scoreO}/>
- <Grid turn={turn} setTurn={setTurn} scoreX={scoreX} setScoreX={setScoreX} scoreO={scoreO} setScoreO={setScoreO} setMessage={setMessage} setShowMessage={setShowMessageBox}/>
- <Footer/>
- </>
- );
-}
-
-export default App;
diff --git a/src/components/Box.tsx b/src/components/Box.js
index abe8b66..effd446 100644
--- a/src/components/Box.tsx
+++ b/src/components/Box.js
@@ -19,13 +19,7 @@
import React from 'react';
import './style.css';
-interface Props {
- sign: number
- index: number
- setSign: (index: number) => void
-}
-
-const Box: React.FC<Props> = (props) => {
+const Box = (props) => {
const handleClick = () => {
props.sign === 2 &&
props.setSign(props.index)
diff --git a/src/components/Footer.tsx b/src/components/Footer.js
index 3bcaa2a..3ec1aea 100644
--- a/src/components/Footer.tsx
+++ b/src/components/Footer.js
@@ -19,7 +19,7 @@
import React from 'react';
import './style.css';
-const Footer: React.FC = () => {
+const Footer = () => {
return (
<div className={"Footer"}>
<p><a href="https://github.com/MikunoNaka/tic-tac-toe">Tic Tac Toe</a> Copyright (C) 2021 Vidhu Kant Sharma</p>
diff --git a/src/components/GamemodeChooser.js b/src/components/GamemodeChooser.js
new file mode 100644
index 0000000..91010e4
--- /dev/null
+++ b/src/components/GamemodeChooser.js
@@ -0,0 +1,63 @@
+/*
+ * Tic Tac Toe - Minimalistic Tic Tac Toe
+ * Copyright (C) 2021 Vidhu Kant Sharma
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import React, { useState } from 'react';
+import MultiplayerMenu from './MultiplayerMenu';
+import './style.css';
+
+const GamemodeChooser = (props) => {
+ const [showMPMenu, setShowMPMenu] = useState(false);
+
+ return (
+ <div className={"GamemodeChooser"}>
+ {showMPMenu ||
+ <>
+ <div className={"GamemodeButton"} onClick={() => {
+ props.setGameStarted(true);
+ props.setMultiplayer(false);
+ }}>
+ SINGLE PLAYER
+ </div>
+
+ <div className={"GamemodeButton"} onClick={() => {
+ setShowMPMenu(true);
+ props.setMultiplayer(true);
+ }}>
+ MULTIPLAYER (beta)
+ </div>
+ </>
+ }
+
+ {showMPMenu &&
+ <>
+ <MultiplayerMenu
+ setIsHost={props.setIsHost}
+ setGameStarted={props.setGameStarted}
+ />
+
+ <div className={"GamemodeButton"} onClick={() => {
+ setShowMPMenu(false);
+ }}>
+ GO BACK
+ </div>
+ </>
+ }
+ </div>
+ );
+}
+
+export default GamemodeChooser;
diff --git a/src/components/Grid.tsx b/src/components/Grid.js
index 30bab11..289f142 100644
--- a/src/components/Grid.tsx
+++ b/src/components/Grid.js
@@ -16,49 +16,38 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import React, { useState, useEffect, Dispatch, SetStateAction } from 'react';
+import React, { useState, useEffect } from 'react';
import Box from './Box';
import './style.css';
-interface Props {
- turn: number
- setTurn: Dispatch<SetStateAction<number>>
- scoreX: number
- scoreO: number
- setScoreX: Dispatch<SetStateAction<number>>
- setScoreO: Dispatch<SetStateAction<number>>
- setMessage: Dispatch<SetStateAction<string>>
- setShowMessage: Dispatch<SetStateAction<boolean>>
-}
-
-const Grid: React.FC<Props> = (props) => {
+const Grid = (props) => {
// 0 is O, 1 is X, 2 is blank
- const [board, setBoard] = useState<number[]>([2,2,2,2,2,2,2,2,2]);
+ const [board, setBoard] = useState([2,2,2,2,2,2,2,2,2]);
const turn = props.turn;
- const getBoard = (index: number) => {
+ const getBoard = (index) => {
setBoard(board.slice(0, index).concat(turn).concat(board.slice(index+1, 9)));
props.setTurn(turn === 1 ? 0 : 1)
}
- const allEqual = (arr: number[]) =>
+ const allEqual = (arr) =>
arr.includes(2) ? false : arr.every(i => i === arr[0])
- const getRow = (r: number) => board.slice(r * 3, (r * 3) + 3);
- const getRows: any = (r: number = 0) =>
+ const getRow = (r) => board.slice(r * 3, (r * 3) + 3);
+ const getRows = (r = 0) =>
r <= 2 ? [getRow(r)].concat(getRows(r+1)) : getRow(r)
- const getCol = (arr: number[][], c: number) => arr.map((i: any) => i[c])
- const getCols: any = (rows: number[][], c: number = 0) =>
+ const getCol = (arr, c) => arr.map((i) => i[c])
+ const getCols = (rows, c = 0) =>
c < 2 ? [getCol(rows, c)].concat(getCols(rows, c+1)) : [getCol(rows, c)]
- const getLeftDiagonal: any = (i: number = 0) =>
+ const getLeftDiagonal = (i = 0) =>
i < 3 ? [getRow(i)[i]].concat(getLeftDiagonal(i+1)) : [];
- const getRightDiagonal: any = (i: number = 2) =>
+ const getRightDiagonal = (i = 2) =>
i >= 0 ? [getRow(2-i)[i]].concat(getRightDiagonal(i-1)) : [];
- const endGame = (winner: number) => {
+ const endGame = (winner) => {
const gameWinner = winner < 2 ? (winner === 1 ? "X" : "O") : "Draw";
props.setMessage(`WINNER: ${gameWinner}`);
props.setShowMessage(true);
@@ -72,21 +61,18 @@ const Grid: React.FC<Props> = (props) => {
useEffect(() => {
if (board.includes(0) || board.includes(1)) {
const rows = getRows();
- (rows.some((i: number[]) => allEqual(i))
- || getCols(rows).some((i: number[]) => allEqual(i))
+ (rows.some((i) => allEqual(i))
+ || getCols(rows).some((i) => allEqual(i))
|| [getLeftDiagonal(), getRightDiagonal()].some((i) => allEqual(i))
) ? endGame(turn === 0 ? 1 : 0) : (board.includes(2) || endGame(2));
}
});
return (
- <div className="Grid">
- {
- board.map(
- (i, index) =>
- <Box key={index} index={index} sign={i} setSign={getBoard}/>
- )
- }
+ <div className="Grid">
+ {board.map((i, index) =>
+ <Box key={index} index={index} sign={i} setSign={getBoard}/>
+ )}
</div>
);
}
diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.js
index de65c48..6194f7b 100644
--- a/src/components/MessageBox.tsx
+++ b/src/components/MessageBox.js
@@ -16,15 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import React, {Dispatch, SetStateAction} from 'react';
+import React from 'react';
import './style.css';
-interface Props {
- message: string
- setShowMessage: Dispatch<SetStateAction<boolean>>
-}
-
-const MessageBox: React.FC<Props> = (props) => {
+const MessageBox = (props) => {
return (
<div className={"MessageBox"} onClick={() => props.setShowMessage(false)}>
<p>{props.message}</p>
diff --git a/src/components/MultiplayerGrid.js b/src/components/MultiplayerGrid.js
new file mode 100644
index 0000000..88a8259
--- /dev/null
+++ b/src/components/MultiplayerGrid.js
@@ -0,0 +1,77 @@
+/*
+ * Tic Tac Toe - Minimalistic Tic Tac Toe
+ * Copyright (C) 2021 Vidhu Kant Sharma
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import React, { useState, useEffect } from 'react';
+import { io } from 'socket.io-client';
+import Box from './Box';
+import './style.css';
+
+const socket = io("http://localhost:5000");
+
+const MultiplayerGrid = (props) => {
+ // 0 is O, 1 is X, 2 is blank
+ const [board, setBoard] = useState([2,2,2,2,2,2,2,2,2]);
+ const turn = props.turn;
+
+ const getBoard = (index) => {
+ // if it's not your turn you can't play
+ if ((turn === 0) === props.isHost) return;
+
+ const newBoard = board.slice(0, index).concat(turn).concat(board.slice(index+1, 9));
+ socket.emit("update-remote-data", {
+ board: newBoard,
+ turn: turn,
+ scoreX: props.scoreX,
+ scoreO: props.scoreO
+ });
+ }
+
+ const endGame = (data) => {
+ props.setMessage(
+ `${data.winner === "Data" ? "" : "WINNER: "}${data.winner}`
+ );
+ props.setShowMessage(true);
+ props.setScoreX(data.scoreX);
+ props.setScoreO(data.scoreO);
+
+ // socket.emit messes everything up
+ // and this does the job very well
+ setBoard([2,2,2,2,2,2,2,2,2]);
+ props.setTurn(data.winner === "Draw" ? turn : (data.winner === "X" ? 1 : 0));
+ }
+
+ useEffect(() => {
+ socket.on("update-client-data", (data) => {
+ setBoard(data.board);
+ props.setTurn(data.turn);
+ props.setScoreX(data.score.scoreX);
+ props.setScoreO(data.score.scoreO);
+ });
+ socket.on("update-winner", (data) => endGame(data));
+ });
+
+ return (
+ <div className="Grid">
+ {board.map((i, index) =>
+ <Box key={index} index={index} sign={i} setSign={getBoard}/>
+ )}
+ </div>
+ );
+}
+
+export default MultiplayerGrid;
diff --git a/src/components/MultiplayerMenu.js b/src/components/MultiplayerMenu.js
new file mode 100644
index 0000000..1dfe9dd
--- /dev/null
+++ b/src/components/MultiplayerMenu.js
@@ -0,0 +1,40 @@
+/*
+ * Tic Tac Toe - Minimalistic Tic Tac Toe
+ * Copyright (C) 2021 Vidhu Kant Sharma
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import React from 'react';
+import './style.css';
+
+const MultiplayerMenu = (props) => {
+ return (
+ <div className={"MultiplayerMenu"}>
+ <div className={"GamemodeButton"} onClick={() => {
+ props.setIsHost(true);
+ props.setGameStarted(true);
+ }}>
+ HOST GAME
+ </div>
+
+ <div className={"GamemodeButton"} onClick={() => {
+ props.setGameStarted(true);
+ }}>
+ JOIN GAME
+ </div>
+ </div>
+ );
+}
+
+export default MultiplayerMenu;
diff --git a/src/components/ScoreBoard.tsx b/src/components/ScoreBoard.js
index b50af30..d393285 100644
--- a/src/components/ScoreBoard.tsx
+++ b/src/components/ScoreBoard.js
@@ -19,20 +19,19 @@
import React from 'react';
import './style.css';
-interface Props {
- scoreX: number
- scoreO: number
- turn: number
-}
-
-const ScoreBoard: React.FC<Props> = (props) => {
+const ScoreBoard = (props) => {
return (
<div className={"ScoreBoardContainer"}>
<div className={"ScoreBoard"}>
<span>X: {props.scoreX}</span>
<span>O: {props.scoreO}</span>
</div>
- <div className={"turnMessage"}>-- {props.turn === 0 ? "O" : "X"}'s turn --</div>
+ <div className={"turnMessage"}>
+ --
+ {` ${props.turn === 0 ? "O" : "X"}'s turn `}
+ {props.multiplayer && ` (You are ${props.isHost ? "'X'" : "'O'"}) `}
+ --
+ </div>
</div>
);
}
diff --git a/src/components/style.css b/src/components/style.css
index d33d775..79ef49e 100644
--- a/src/components/style.css
+++ b/src/components/style.css
@@ -16,18 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*body, #root {
- margin: 0px;
- height: 100vh;
- width: 100vw;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- background-color: #232627;
- color: white;
-}*/
-
body {
margin: 0;
padding: 0;
@@ -42,6 +30,24 @@ body {
left: 0; right: 0;
}
+.GamemodeChooser {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ height: 90%;
+ width: 100%;
+}
+
+.GamemodeChooser .GamemodeButton {
+ border: 1px solid #5b76b7;
+ text-align: center;
+ font-size: 1.5rem;
+ padding: 0.5rem 0;
+ width: 15rem;
+ margin: 1rem;
+}
+
.MessageBox {
font-size: 7rem;
display: flex;