react web game : 틱택토 구현
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import React, { useCallback } from "react";
|
||||
import { CLICK_CELL, CHANGE_TURN } from "./TicTacToe";
|
||||
import { CLICK_CELL } from "./TicTacToe";
|
||||
|
||||
const Td = ({ rowIndex, cellIndex, dispatch, cellData }) => {
|
||||
const onClickTd = useCallback(() => {
|
||||
console.log(rowIndex, cellIndex);
|
||||
if(cellData) {
|
||||
return;
|
||||
}
|
||||
dispatch({ type: CLICK_CELL, row: rowIndex, cell: cellIndex });
|
||||
dispatch({ type: CHANGE_TURN });
|
||||
});
|
||||
}, [cellData]);
|
||||
|
||||
return <td onClick={onClickTd}>{cellData}</td>;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useReducer, useCallback } from "react";
|
||||
import React, { useState, useEffect, useReducer, useCallback } from "react";
|
||||
import Table from "./Table";
|
||||
|
||||
// 초기 state 값 설정
|
||||
@@ -10,12 +10,14 @@ const initialState = {
|
||||
["", "", ""],
|
||||
["", "", ""],
|
||||
],
|
||||
recentCell: [-1, -1],
|
||||
};
|
||||
|
||||
// action 이름 설정 - 하위 컴포넌트에서 사용하기 위해 모듈화
|
||||
export const SET_WINNER = "SET_WINNER";
|
||||
export const CLICK_CELL = "CLICK_CELL";
|
||||
export const CHANGE_TURN = "CHANGE_TURN";
|
||||
export const RESET_GAME = "RESET_GAME";
|
||||
|
||||
// reducer 설정 - dispatch 한 action 의 값들을 이용해 state 변경
|
||||
const reducer = (state, action) => {
|
||||
@@ -34,6 +36,7 @@ const reducer = (state, action) => {
|
||||
return {
|
||||
...state,
|
||||
tableData,
|
||||
recentCell: [action.row, action.cell]
|
||||
};
|
||||
}
|
||||
// 칸을 클릭 할 때마다 O X 번갈아가면서 출력
|
||||
@@ -43,17 +46,72 @@ const reducer = (state, action) => {
|
||||
turn: state.turn === "O" ? "X" : "O",
|
||||
};
|
||||
}
|
||||
case RESET_GAME: {
|
||||
return {
|
||||
...state,
|
||||
turn: "O",
|
||||
tableData: [
|
||||
["", "", ""],
|
||||
["", "", ""],
|
||||
["", "", ""],
|
||||
],
|
||||
recentCell: [-1, -1],
|
||||
}
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const TicTacToe = () => {
|
||||
// useReducer 사용
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
const { tableData, turn, winner, recentCell } = state;
|
||||
// 승자 체크
|
||||
useEffect(() => {
|
||||
const [row, cell] = recentCell;
|
||||
if (row < 0) {
|
||||
return;
|
||||
}
|
||||
let win = false;
|
||||
if (tableData[row][0] === turn && tableData[row][1] === turn && tableData[row][2] === turn) {
|
||||
win = true;
|
||||
}
|
||||
if (tableData[0][cell] === turn && tableData[1][cell] === turn && tableData[2][cell] === turn) {
|
||||
win = true;
|
||||
}
|
||||
if (tableData[0][0] === turn && tableData[1][1] === turn && tableData[2][2] === turn) {
|
||||
win = true;
|
||||
}
|
||||
if (tableData[0][2] === turn && tableData[1][1] === turn && tableData[2][0] === turn) {
|
||||
win = true;
|
||||
}
|
||||
if (win) {
|
||||
// 승자가 있을 때
|
||||
dispatch({type:SET_WINNER, winner: turn})
|
||||
dispatch({type:RESET_GAME});
|
||||
} else {
|
||||
// 무승부 일 때
|
||||
let all = true; // all 이 true 면 무승부
|
||||
tableData.forEach((row) => {
|
||||
row.forEach((cell) => {
|
||||
if(!cell) {
|
||||
all = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
if(all) { // 모든 칸이 다 차있으면 무승부
|
||||
dispatch({type:RESET_GAME});
|
||||
} else {
|
||||
dispatch({ type: CHANGE_TURN });
|
||||
}
|
||||
}
|
||||
}, [recentCell])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table tableData={state.tableData} dispatch={dispatch} />
|
||||
{state.winner && <div>{state.winner}님의 승리</div>}
|
||||
<Table tableData={tableData} dispatch={dispatch} />
|
||||
{winner && <div>{winner}님의 승리</div>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user