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;

+ Recent posts