Skip to content

Instantly share code, notes, and snippets.

@omept
Last active March 21, 2022 17:04
Show Gist options
  • Save omept/c0cd822fe44c87290dbb0d930c0f0af8 to your computer and use it in GitHub Desktop.
Save omept/c0cd822fe44c87290dbb0d930c0f0af8 to your computer and use it in GitHub Desktop.
React Tic Tac Toe
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
const rowStyle = {
display: 'flex'
}
const squareStyle = {
'width':'60px',
'height':'60px',
'backgroundColor': '#ddd',
'margin': '4px',
'display': 'flex',
'justifyContent': 'center',
'alignItems': 'center',
'fontSize': '20px',
'color': 'white'
}
const boardStyle = {
'backgroundColor': '#eee',
'width': '208px',
'alignItems': 'center',
'justifyContent': 'center',
'display': 'flex',
'flexDirection': 'column',
'border': '3px #eee solid'
}
const containerStyle = {
'display': 'flex',
'alignItems': 'center',
'flexDirection': 'column'
}
const instructionsStyle = {
'marginTop': '5px',
'marginBottom': '5px',
'fontWeight': 'bold',
'fontSize': '16px',
}
const buttonStyle = {
'marginTop': '15px',
'marginBottom': '16px',
'width': '80px',
'height': '40px',
'backgroundColor': '#8acaca',
'color': 'white',
'fontSize': '16px',
}
class Square extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<div onClick={() => this.props.mark()}
className="square"
style={squareStyle}>
{this.props.text()}
</div>
);
}
}
class Board extends React.Component {
constructor(props){
super(props);
this.nextPlayer = this.nextPlayer.bind(this);
this.defaultTiles = this.defaultTiles.bind(this);
this.state = {
currentPlayer: 'X',
clickCount: 0,
winner: 'None',
gameEnded: false,
tiles: this.defaultTiles()
};
}
defaultTiles = () => {
let row = 3;
let col = 3;
let tiles= new Array(row);
for(let j =0; j<row; j++){
tiles[j] = new Array(col);
}
return tiles;
};
markTile = (i,j) => {
let {tiles, gameEnded, currentPlayer} = this.state;
if(tiles[i][j] == null && !gameEnded){
tiles[i][j] = currentPlayer;
let {winner, gameEnded, clickCount} = this.evalBoard();
this.setState({
currentPlayer: this.nextPlayer(),
tiles,
winner,
clickCount,
gameEnded
});
}
};
evalBoard = () => {
let winner = 'None';
let gameEnded = false;
let {tiles, clickCount} = this.state;
let playerArr = ['X', 'O'];
clickCount = clickCount+1;
// check the 8 conditions for game completion
if((tiles[0][2] == tiles[1][2]) && (tiles[0][2] == tiles[2][2]) && playerArr.indexOf(tiles[0][2]) > -1){
winner = tiles[0][2];
gameEnded = true;
}else if((tiles[0][0] == tiles[0][1]) && (tiles[0][0] == tiles[0][2]) && playerArr.indexOf(tiles[0][0]) > -1){
winner = tiles[0][0];
gameEnded = true;
}else if((tiles[0][0] == tiles[1][1]) && (tiles[0][0] == tiles[2][2]) && playerArr.indexOf(tiles[0][0]) > -1){
winner = tiles[0][0];
gameEnded = true;
}else if((tiles[0][0] == tiles[1][0]) && (tiles[0][0] == tiles[2][0]) && playerArr.indexOf(tiles[0][0]) > -1){
winner = tiles[0][0];
gameEnded = true;
}else if((tiles[2][0] == tiles[2][1]) && (tiles[2][0] == tiles[2][2]) && playerArr.indexOf(tiles[2][0]) > -1){
winner = tiles[2][0];
gameEnded = true;
}else if((tiles[2][0] == tiles[1][1]) && (tiles[2][0] == tiles[0][2]) && playerArr.indexOf(tiles[2][0]) > -1){
winner = tiles[2][0];
gameEnded = true;
}else if((tiles[1][0] == tiles[1][1]) && (tiles[1][0] == tiles[1][2]) && playerArr.indexOf(tiles[1][0]) > -1){
winner = tiles[1][0];
gameEnded = true;
}else if((tiles[0][1] == tiles[1][1]) && (tiles[0][1] == tiles[2][1]) && playerArr.indexOf(tiles[0][1]) > -1){
winner = tiles[0][1];
gameEnded = true;
}else if(clickCount == 9){
gameEnded = true;
winner = 'None';
}
return {winner, gameEnded, clickCount}
}
nextPlayer = () => {
let currentPlayer = this.state.currentPlayer;
let playSwitch = {
'X': 'O',
'O': 'X'
};
return playSwitch[currentPlayer];
};
tileValAt = (i, j) => {
return this.state.tiles[i][j];
};
resetGame = () => {
let val = {
currentPlayer: 'X',
winner: 'None',
gameEnded: false,
clickCount: 0,
tiles: this.defaultTiles()
};
this.setState(val);
}
render() {
let {currentPlayer, winner, gameEnded } = this.state;
return (
<div style={containerStyle} className="gameBoard">
{!gameEnded ?<div id="statusArea" className="status" style={instructionsStyle}>Next player: <span>{ currentPlayer }</span></div> : null}
{winner && gameEnded ? <div id="winnerArea" className="winner" style={instructionsStyle}>Winner: <span>{ winner }</span></div> : null}
<button onClick={()=> this.resetGame()} style={buttonStyle}>Reset</button>
<div style={boardStyle}>
<div className="board-row" style={rowStyle}>
<Square mark={() => this.markTile(0,0)} text={() => this.tileValAt(0,0)}/>
<Square mark={() => this.markTile(0,1)} text={() => this.tileValAt(0,1)}/>
<Square mark={() => this.markTile(0,2)} text={() => this.tileValAt(0,2)}/>
</div>
<div className="board-row" style={rowStyle}>
<Square mark={() => this.markTile(1,0)} text={() => this.tileValAt(1,0)}/>
<Square mark={() => this.markTile(1,1)} text={() => this.tileValAt(1,1)}/>
<Square mark={() => this.markTile(1,2)} text={() => this.tileValAt(1,2)}/>
</div>
<div className="board-row" style={rowStyle}>
<Square mark={() => this.markTile(2,0)} text={() => this.tileValAt(2,0)}/>
<Square mark={() => this.markTile(2,1)} text={() => this.tileValAt(2,1)}/>
<Square mark={() => this.markTile(2,2)} text={() => this.tileValAt(2,2)}/>
</div>
</div>
</div>
);
}
}
class Game extends React.Component {
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
</div>
);
}
}
ReactDOM.render(
<Game />,
document.getElementById('root')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment