import React, {useCallback, useEffect, useReducer} from 'react';
import Table from "./Table";
const initialState = {
winner: '',
turn : 'O',
tableData : [['','',''],['','',''],['','','']],
recentPos: [], //해당 값이 바뀔 때마다 useEffect에서 게임이 끝났는지 체크, 턴 변경
}
const SET_WINNER = "SET_WINNER";
const CLICK_CELL = 'CLICK_CELL';
const TURN_CHANGE = 'TURN_CHANGE';
const RESET_GAME = 'RESET_GAME';
const reducer = (state,action) => {
switch (action.type){
case SET_WINNER:
return {
...state,
winner: action.winner,
}
case CLICK_CELL:
const {row,cell} = action;
const tableData = [...state.tableData];
tableData[row] = [...tableData[row]];
if(tableData[row][cell] === ''){
tableData[row][cell] = state.turn;
return {
...state,
tableData,
recentPos: [row,cell],
}
}
return {
...state,
}
case TURN_CHANGE:
return {
...state,
turn : state.turn === 'O' ? 'X' : 'O',
}
case RESET_GAME:
return {
winner: '',
turn : 'O',
tableData : [['','',''],['','',''],['','','']],
recentPos: [], //해당 값이 바뀔 때마다 useEffect에서 게임이 끝났는지 체크, 턴 변경
}
}
}
const TicTacToe = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const tableOnClick = useCallback((e) => {
if(state.winner !== '') return ;
const {target} = e;
const tr = target.parentElement;
const rowIndex = tr.rowIndex;
const cellIndex = target.cellIndex;
dispatch({type:CLICK_CELL, row:rowIndex, cell:cellIndex});
},[state.winner]);
const winnerCheck = ({recentPos, tableData, turn}) => {
let end = true;
//가로줄 검사
tableData[recentPos[0]].forEach(value => {
if(value !== turn) end = false;
});
if(end) return true;
//세로줄 검사
end=true;
tableData.forEach((arr,index)=>{
if(arr[recentPos[1]] !== turn) end = false;
});
if(end)return true;
//대각선 검사
if((tableData[0][0] === turn && tableData[1][1] === turn && tableData[2][2] === turn)
|| (tableData[0][2] === turn && tableData[1][1] === turn && tableData[2][0] === turn) ){
end = true;
}
return end;
}
const fullCheck = (tableData) => {
let isFull = true;
tableData.forEach(arr => arr.forEach(v => {
if(v === '')isFull = false;
}));
return isFull;
}
const onResetClick = () => {
dispatch({type:RESET_GAME});
}
useEffect(()=>{
const {recentPos, tableData, turn} = state;
if(recentPos.length ===0)return ;
const end = winnerCheck(state);
if(end){
//승리자 나옴.
dispatch({type:SET_WINNER, winner:turn});
} else {
if(fullCheck(tableData)){
dispatch({type:SET_WINNER, winner:'draw!!!'});
}else{
dispatch({type:TURN_CHANGE});
}
}
},[state.recentPos]);
return (
<>
<Table onClick={tableOnClick} tableData={state.tableData}/>
{
state.winner &&
<>
<div>WINNER IS {state.winner}</div>
<button onClick={onResetClick}>RESET</button>
</>
}
</>
);
};
export default TicTacToe;