Skip to content

Instantly share code, notes, and snippets.

@alexmgrant
Last active December 2, 2020 16:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexmgrant/f21f534dcfc7364567c3fc409da18cac to your computer and use it in GitHub Desktop.
Save alexmgrant/f21f534dcfc7364567c3fc409da18cac to your computer and use it in GitHub Desktop.
Board Component
import React, { useState, useEffect } from 'react';
import { getWinner } from './game-rules';
import './Grid.css';
enum Player {
playerOne = 'X',
playerTwo = 'O',
}
export type SelectedPostion = {
position: number;
player: string;
};
const board = [0, 1, 2, 3, 4, 5, 6, 7, 8];
const initBoard = board.map((position) => ({ position, player: '' }));
const getCurrentPlayer = (player: string): string => {
return player === Player.playerOne ? Player.playerTwo : Player.playerOne;
};
const Grid = () => {
const [selectedPositions, setSelectedPositions] = useState(
initBoard as SelectedPostion[]
);
const [player, setPlayer] = useState('X');
useEffect(() => {
const winner = getWinner(selectedPositions);
if (winner) {
alert(`${winner.player} wins! 🎉`);
setSelectedPositions(initBoard);
}
}, [selectedPositions]);
const handleSelectPosition = (position: number, player: string) => {
const selectedPosition = { position, player };
const currentPositions = [...selectedPositions];
const { player: currentPlayer } = currentPositions[position];
const hasPlayer = currentPlayer.length > 0;
if (hasPlayer) {
return;
}
currentPositions[position] = selectedPosition;
setPlayer(getCurrentPlayer(player));
setSelectedPositions(currentPositions);
};
return (
<ul className="Grid">
{board.map(position =>
(
<li
onClick={() => handleSelectPosition(position, player)}
key={position}
>
{selectedPositions[position].player}
</li>
)
)}
</ul>
);
};
export default Grid;
import { getWinner, winningConditions } from './game-rules';
function initBoard() {
return Array(9)
.fill({})
.map((_, index) => ({ position: index, player: '' }));
}
let mockBoard: any[] = [];
const [a, b, c, d, e, f, g, h] = winningConditions;
beforeEach(() => {
mockBoard = initBoard();
});
test('handles no turn taken', () => {
expect(getWinner(mockBoard)).toBe(null);
});
test('handles row win with x or o', () => {
const testRowsX = mockBoard.map((position) => ({ ...position, player: 'x' }));
expect(getWinner(testRowsX)).toBe(testRowsX[0]);
const testRowsO = mockBoard.map((position) => ({ ...position, player: 'o' }));
expect(getWinner(testRowsO)).toBe(testRowsO[0]);
});
test('handles column win', () => {
const columns = [...d, ...e, ...f];
columns.forEach((cell) => {
mockBoard[cell] = { ...mockBoard[cell], player: 'x' };
});
expect(getWinner(mockBoard)).toBe(mockBoard[0]);
});
test('handles diangonal win', () => {
const diangles = [...g, ...h];
diangles.forEach((cell) => {
mockBoard[cell] = { ...mockBoard[cell], player: 'x' };
});
expect(getWinner(mockBoard)).toBe(mockBoard[0]);
});
import { SelectedPostion } from './Grid';
export const winningConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
export function getWinner(board: SelectedPostion[]): SelectedPostion | null {
let result: SelectedPostion | null = null;
winningConditions.some((_, index) => {
const [a, b, c] = winningConditions[index];
const { player: playerA } = board[a];
const { player: playerB } = board[b];
const { player: playerC } = board[c];
if (playerA && playerA === playerB && playerA === playerC) {
return (result = board[a]);
}
});
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment