diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js index 0712a90fda..170f7c28c0 100644 --- a/src/meta/play-meta.js +++ b/src/meta/play-meta.js @@ -16,6 +16,7 @@ QuoteGenerator, PasswordGenerator, WhyTypescript, NetlifyCardGame, +TicTacToeGame, Calendar, FunQuiz, //import play here @@ -243,6 +244,20 @@ export const plays = [ language: 'js', featured: true, }, { + id: 'pl-tic-tac-toe-game', + name: 'Tic Tac Toe Game', + description: 'This game is coded in ReactJS and VanillaCSS', + component: () => {return }, + path: '/plays/tic-tac-toe-game', + level: 'Beginner', + tags: 'Hooks,JSX,Functions,ResetState,CSS', + github: 'tejinder-sharma', + cover: '', + blog: '', + video: '', + language: 'js', + }, + { id: 'pl-calendar', name: 'Calendar', description: 'Simple calendar app to manage events', diff --git a/src/plays/index.js b/src/plays/index.js index 89543a1073..1f6dcb9eaf 100644 --- a/src/plays/index.js +++ b/src/plays/index.js @@ -18,6 +18,10 @@ export { default as AnalogClock } from 'plays/analog-clock/AnalogClock'; export { default as PasswordGenerator } from 'plays/password-generator/PasswordGenerator'; export { default as WhyTypescript } from 'plays/why-typescript/WhyTypescript'; export { default as NetlifyCardGame } from 'plays/memory-game/NetlifyCardGame'; + +export { default as TicTacToeGame } from 'plays/tic-tac-toe-game/TicTacToeGame'; + export { default as Calendar } from 'plays/calendar/Calendar'; export { default as FunQuiz } from 'plays/fun-quiz/FunQuiz'; + //add export here diff --git a/src/plays/tic-tac-toe-game/Readme.md b/src/plays/tic-tac-toe-game/Readme.md new file mode 100644 index 0000000000..c37197340d --- /dev/null +++ b/src/plays/tic-tac-toe-game/Readme.md @@ -0,0 +1,17 @@ +# Tic Tac Toe Game + +It is a Tic Tac Toe Game to made with React. + + +## What will you learn? + +- Functional Components +- Event handling for user interaction. +- Update of states. +- How to reuse the components.(e.g we reused our game square button many times). +- How to reset the states. + + +The file `TicTacToeGAme` is the main file along with the css. + +If you want to implement your learnings about states and useEffect hooks try implementing it on your own! \ No newline at end of file diff --git a/src/plays/tic-tac-toe-game/TicTacToeGame.jsx b/src/plays/tic-tac-toe-game/TicTacToeGame.jsx new file mode 100644 index 0000000000..67440fcc06 --- /dev/null +++ b/src/plays/tic-tac-toe-game/TicTacToeGame.jsx @@ -0,0 +1,32 @@ +import { getPlayById } from 'meta/play-meta-util'; + +import PlayHeader from 'common/playlists/PlayHeader'; + +import React from "react"; + +import Game from "./components/Game.jsx" + +import "./styles/tic-tac-toe-tj.css"; + +function TicTacToeGame(props) { + // Do not remove the below lines. + // The following code is to fetch the current play from the URL + const { id } = props; + const play = getPlayById(id); + + // Your Code Start below. + return ( + <> +
+ +
+ {/* Your Code Starts Here */} + + {/* Your Code Ends Here */} +
+
+ + ); +} + +export default TicTacToeGame; \ No newline at end of file diff --git a/src/plays/tic-tac-toe-game/components/Game.jsx b/src/plays/tic-tac-toe-game/components/Game.jsx new file mode 100644 index 0000000000..33b2658403 --- /dev/null +++ b/src/plays/tic-tac-toe-game/components/Game.jsx @@ -0,0 +1,120 @@ +import React, { useState } from "react"; + +function Square(props) { + return ( + + ); +} +function Restart({ onClick }) { + return ( + + ); +} + +function Game() { + const [squares, setSquares] = useState(Array(9).fill(null)); + const [isXNext, setIsXNext] = useState(true); + + const nextSymbol = isXNext ? "X" : "O"; + + const winner = calculateWinner(squares); + + + function renderSquare(i) { + return ( + { + const nextSquares = squares.slice(); + if (squares[i] != null || winner != null) { + return; + } + nextSquares[i] = nextSymbol; + setSquares(nextSquares); + setIsXNext(!isXNext); + }} + /> + ); + } + function getStatus() { + if (winner) { + return `Winner: ${winner.player}`; + } else if (isBoardFull(squares)) { + return "Draw!"; + } else { + return `Next player: ${nextSymbol}`; + } + } + function renderRestartButton() { + return ( + { + setSquares(Array(9).fill(null)); + setIsXNext(true); + }} + /> + ); + } + function renderSquares(n) { + let squares = []; + for (let i = n; i < n + 3; i++) { + squares.push(renderSquare(i)); + } + return squares; + } + + function renderRow(i) { + return
{renderSquares(i)}
; + } + + return ( +
+
Tic Tac Toe Game
+
+ {renderRow(0)} + {renderRow(3)} + {renderRow(6)} +
+
{getStatus()}
+
{renderRestartButton()}
+
+ ); +} + +function calculateWinner(squares) { + const possibleLines = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6], + ]; + for (let i = 0; i < possibleLines.length; i++) { + const [a, b, c] = possibleLines[i]; + if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { + return {player:squares[a], line:[a, b, c]}; + } + } + return null; +} + +function isBoardFull(squares) { + for (let i = 0; i < squares.length; i++) { + if (squares[i] == null) { + return false; + } + } + return true; +} + +export default Game; diff --git a/src/plays/tic-tac-toe-game/cover.png b/src/plays/tic-tac-toe-game/cover.png new file mode 100644 index 0000000000..48622014c3 Binary files /dev/null and b/src/plays/tic-tac-toe-game/cover.png differ diff --git a/src/plays/tic-tac-toe-game/styles/tic-tac-toe-tj.css b/src/plays/tic-tac-toe-game/styles/tic-tac-toe-tj.css new file mode 100644 index 0000000000..2cc5ed5861 --- /dev/null +++ b/src/plays/tic-tac-toe-game/styles/tic-tac-toe-tj.css @@ -0,0 +1,70 @@ +.tic-tac-toe-tj .container{ + text-align: center; +} + + +.tic-tac-toe-tj .squareButton{ + width: 5rem; + height: 5rem; + margin: 1px; + background-color: #EC4899; + + display: inline-flex; + justify-content: center; + align-items: center; + + border: none; + font: bold; + font-size: 32px; + color: white; +} +.tic-tac-toe-tj .squareButton:hover{ + background-color: #10B981; +} +.tic-tac-toe-tj .row{ + display: flex; +} +.tic-tac-toe-tj .jumpButton{ + padding: 0.5rem 1rem; + background-color: #10B981; + + display: inline-flex; + justify-content: center; + align-items: center; + + border: none; + color: white; + font-size: 18px; + border-radius: 4px; + margin-top: 1rem; +} +.tic-tac-toe-tj .bg-yellow-500{ + background-color: #f59e0b; +} +.tic-tac-toe-tj .jumpButton:hover{ + background-color: #EC4899; +} +.tic-tac-toe-tj .list{ + margin-top: 1rem; +} +.tic-tac-toe-tj .status{ + margin-top: 1rem; + font-size: 24px; +} +.tic-tac-toe-tj .header{ + width: 100%; + padding: 16px 8px; + color: white; + font-size: 24px; + + display: grid; + place-content: center; + + background-color: #010326; + margin-bottom: 2rem; +} + +.tic-tac-toe-tj .boardMain{ + display: grid; + place-content: center; +} \ No newline at end of file