일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 리액트스타디
- mongoose
- NoSQL
- express-generator
- React
- mongo
- 제로초예제
- 클래스컴포넌트
- nodeJS
- node
- 시퀄라이즈
- npm명령어
- sementicversion
- React Component
- nodejs교과서
- 리액트컴포넌트
- 리액트
- component
- MongoDB
- 리액트기초
- 시퀄라이즈공부
- NPM
- sequelize
- Today
- Total
개발노트
14 (3)context API 본문
칸 열었을때 지뢰 갯수 표시해주기
(1) 주변에 지뢰가 있는지 검사하기 위해 around 배열에 주변 칸(상태값)들 담아줌 !
let around = [];
if(tableData[action.trIndex-1]){
around = around.concat(
tableData[action.trIndex-1][action.tdIndex -1],
tableData[action.trIndex-1][action.tdIndex ],
tableData[action.trIndex-1][action.tdIndex +1],
)
}
around = around.concat(
tableData[action.trIndex][action.tdIndex -1],
tableData[action.trIndex][action.tdIndex +1]
);
if(tableData[action.trIndex +1]){
around =around.concat(
tableData[action.trIndex+1][action.tdIndex -1],
tableData[action.trIndex+1][action.tdIndex ],
tableData[action.trIndex+1][action.tdIndex +1],
);
}
윗끝줄은 윗칸이 없기때문에 if 문으로나눴음
불변성 유지하기 위해 concat으로 복사하면서 담는다.
let arr = [];
arr = arr.concat( 1,2,3 ); // ?
let arr = [];
arr = arr.concat( 1,2,3 ); // [1,2,3]
filter안에 배열안에 포함되어있는지 검사해서 length반납해주는.. 패턴?을사용
const arr = [1,2,3,4,5,6];
arr.includes(1) // ?
arr.includes(2) // ?
arr.filter( (v)=> ( [1,2].includes(v) ) ).length // ?
const arr = [1,2,3,4,5,6];
arr.includes(1) //true
arr.includes(2) //true
arr.filter( (v)=> ( [1,2].includes(v) ) ).length // 2
(2)지뢰가 있는지 검사
const mineCount = around.filter((v)=>( [TD_STATE.MINE, TD_STATE.FLAG_BUT, TD_STATE.QUESTION_BUT].includes(v) )).length;
//const mineCount = around.filter((v)=>( [-7, -5, -4].includes(v) )).length;
//tableData[action.trIndex][action.tdIndex] = TD_STATE.OPENED;
tableData[action.trIndex][action.tdIndex] = mineCount;
구한 지뢰갯수를 클릭한 칸에 전달.
주변에 지뢰가 있는지 잘 알려줌
const tdText = ( stateCode ) =>{
switch(stateCode){
case TD_STATE.NORMAL:
return '';
case TD_STATE.MINE:
return 'X';
case TD_STATE.OPENED_MINE:
return '펑!';
case TD_STATE.FLAG_BUT:
case TD_STATE.FLAG:
return '!~'
case TD_STATE.QUESTION:
return '?'
default:
return stateCode || ''; ////
}
}
tableData에서 열었을때 상태코드를 지뢰갯수mineCount로 set해줬기 때문에,
텍스트 처리 하는 값에서 그냥 상태코드 그대로 보여주는걸로 해준다
0일경우 표시안해주려고 '' 비어있는스트링 리턴
case OPEN_TD:{
const tableData = [...state.tableData];
tableData[action.trIndex] = [...state.tableData[action.trIndex]];
// (1) 주변 칸(상태값)들 담아줌
let around = [];
if(tableData[action.trIndex-1]){
around = around.concat(
tableData[action.trIndex-1][action.tdIndex -1],
tableData[action.trIndex-1][action.tdIndex ],
tableData[action.trIndex-1][action.tdIndex +1],
)
}
around = around.concat(
tableData[action.trIndex][action.tdIndex -1],
tableData[action.trIndex][action.tdIndex +1]
);
if(tableData[action.trIndex +1]){
around =around.concat(
tableData[action.trIndex+1][action.tdIndex -1],
tableData[action.trIndex+1][action.tdIndex ],
tableData[action.trIndex+1][action.tdIndex +1],
);
}
// (2) 지뢰가 있는지 검사
const mineCount = around.filter((v)=>( [TD_STATE.MINE, TD_STATE.FLAG_BUT, TD_STATE.QUESTION_BUT].includes(v) )).length;
console.log( tableData[action.trIndex][action.tdIndex] );
console.log( around, mineCount );
tableData[action.trIndex][action.tdIndex] = mineCount;
//tableData[action.trIndex][action.tdIndex] = TD_STATE.OPENED;
return{
...state,
tableData,
}
}
칸 열었을때 주변의 여러개칸 같이 열리게
주변 지뢰가 하나도 없을때 주변칸들을 연다
한칸만열릴경우는- 내가 여는 칸만 값 가져와서 바꾸면 됬었는데, ->내가 여는 한줄만 복사
(0)주변칸도 열어야 되니까 불변성유지위해 ->전체줄 다 복사
모든 줄을 새로운 객체tableData 에 담아줌
const tableData = [...state.tableData];
tableData.forEach( (tr, i) =>{
tableData[i] = [...state.tableData[i]];
});
(1) 함수로 묶어서 호출.
case OPEN_TD:{
const tableData = [...state.tableData];
tableData.forEach( (tr, i) =>{ // (0)
tableData[i] = [...state.tableData[i]];
});
//내 tr,td 값으로 주변칸 검사해주는 함수
const checkAndOpen=(tr, td)=>{ //(1)
// (1) 주변 칸(상태값)들 담아줌
let around = [];
if(tableData[tr]-1){
around = around.concat(
tableData[tr-1][td-1],
tableData[tr-1][td],
tableData[tr-1][td+1],
)
}
around = around.concat(
tableData[tr][td-1],
tableData[tr][td+1],
);
if(tableData[tr +1]){
around =around.concat(
tableData[tr+1][td-1],
tableData[tr+1][td],
tableData[tr+1][td+1],
);
}
// (2) 지뢰가 있는지 검사 - 지뢰갯수 를 누른칸에 보여줌
const mineCount = around.filter((v)=>( [TD_STATE.MINE, TD_STATE.FLAG_BUT, TD_STATE.QUESTION_BUT].includes(v) )).length;
tableData[tr][td] = mineCount;
////////
if(mineCount === 0){ //내주변 지뢰가0이면 - 옆칸 다 검사
}
}
checkAndOpen( action.trIndex, action.tdIndex ); //(1)
재귀 함수로 쓰기 위해서 기능들을 checkAndOpen이라는 함수로 담았고
action.trIndex-> tr , action.tdIndex ->td 인자로 받음
내 tr, td 를 넘겨줘서 내tr,td위치값 8개가 지뢰가 없을경우주변칸들 까지 계속 검사하는 함수로 만든다.
만약 내가 클릭했던 칸 주변으로 지뢰가 없을 경우.
내 tr, td 주변으로 하나씩 다 눌러주기 위한 배열목록 near 을 만든다
if(mineCount === 0){ //내주변 지뢰가0이면 - 옆칸 다 검사해서 연다.
const near = [];
if( tr-1 > -1 ){ //첫째줄이여서 0-1 하면 -1 - 즉 첫째줄 일경우
near.push([tr-1, td-1]); //near [-1, ]
near.push([tr-1, td]); //near [-1, ]
near.push([tr-1, td+1]); // near [-1, ]
}
near.push([tr, td-1]);
near.push([tr, td+1]);
if( tr+1 < tableData.length ){ //마지막줄일 경우 아랫칸 없으니까, 아랫칸 없애준다(검사안한다.)
near.push([tr+1, td-1]);
near.push([tr+1, td]);
near.push([tr+1, td+1]); // near
}
console.log(near);
near.filter(v=>!!v).forEach((n)=>{
if( tableData[n[0]][n[1]] !== TD_STATE.OPEND )
checkAndOpen(n[0],n[1]);
})
}
tableData[tr][td] = mineCount; /// ?
}
그리고 모서리일 경우 안열어야 하는데,
모서리일 경우는 -값으로 한정되게 됨 (0,0부터시작하니까.)
그래서 -1 이면 리턴시키는 조건을 초반부에 적어놓아서 없는칸(-1)은 return 시킨다.
if( tr<0 || tr >= tableData.length || td<0 || td >= tableData[0].length ){
return;
}
+ 열린칸이면 꼭. return 시켜야 콜스택 터지는걸 막을수 있음;
(열린칸 안막으면 주변칸 서로가 서로를 계속 열어줘서 문제발생됨 재귀함수 조심)
if( [TD_STATE.OPENED, TD_STATE.QUESTION, TD_STATE.QUESTION_BUT, TD_STATE.FLAG, TD_STATE.FLAG_BUT].includes( tableData[tr][td]) ){
return;
}
case OPEN_TD:{
const tableData = [...state.tableData];
tableData.forEach( (tr, i) =>{
tableData[i] = [...state.tableData[i]]; // ?
//tableData[i] = [...tr];
});
const checked = [];
//내 tr,td 값으로 주변(max 8)칸 검사해서 열어주는 함수
const checkAndOpen=(tr, td)=>{
if( tr<0 || tr >= tableData.length || td<0 || td >= tableData[0].length ){
return;
}
//내tr,td값이 이미 열린칸이면 return. (지뢰칸이여도)
if( [TD_STATE.OPENED, TD_STATE.QUESTION, TD_STATE.QUESTION_BUT, TD_STATE.FLAG, TD_STATE.FLAG_BUT].includes( tableData[tr][td]) ){
return;
}
//한번 체크해서 연 칸은 다시 체크하지 않기 위해
if( checked.includes(tr+','+td) ){
return;
}else{
checked.push(tr+','+td);
}
// 1주변 칸(상태값)들 담아줌
let around = [
tableData[tr][td-1], tableData[tr][td+1] // 좌 우는 무조건 담고. /어차피 없으면 undefined
];
if(tableData[tr-1]){ // 내윗줄 있으면 담고
around = around.concat(
tableData[tr-1][td-1],
tableData[tr-1][td],
tableData[tr-1][td+1],
)
}
// around = around.concat(
// tableData[tr][td-1],
// tableData[tr][td+1],
// );
if(tableData[tr+1]){ //내아랫줄 있으면 담고
around =around.concat(
tableData[tr+1][td-1],
tableData[tr+1][td],
tableData[tr+1][td+1],
);
}
// 2지뢰가 있는지 검사 - 지뢰갯수 를 누른칸에 보여줌
const mineCount = around.filter((v)=>( [TD_STATE.MINE, TD_STATE.FLAG_BUT, TD_STATE.QUESTION_BUT].includes(v) )).length;
//tableData[tr][td] = mineCount;
if(mineCount === 0){ //내주변 지뢰가0이면 - 옆칸 다 검사해서 연다.
const near = [];
if( tr-1 > -1 ){ //첫째줄이여서 0-1 하면 -1 - 즉 첫째줄 일경우
near.push([tr-1, td-1]); //near [-1, ]
near.push([tr-1, td]); //near [-1, ]
near.push([tr-1, td+1]); // near [-1, ]
}
near.push([tr, td-1]);
near.push([tr, td+1]);
if( tr+1 < tableData.length ){ //마지막줄일 경우 아랫칸 없으니까, 아랫칸 없애준다(검사안한다.)
near.push([tr+1, td-1]);
near.push([tr+1, td]);
near.push([tr+1, td+1]); // near
}
console.log(near);
near.forEach((n)=>{
if( tableData[n[0]][n[1]] !== TD_STATE.OPEND )
checkAndOpen(n[0],n[1]);
})
}
tableData[tr][td] = mineCount; /// ?
}
checkAndOpen( action.trIndex, action.tdIndex );
return{
...state,
tableData,
}
}
승리조건
연칸이 == ( 칸갯수(가로x세로) - 지뢰갯수 ) 되면 승리.
checkAndOpen함수 실행시켜서 한번 실행때마다 칸을 총몇개열었는지 -> tdOpen(함수내)
initialState에 게임시작후 총 몇개 열었는지->opendCount (initialState)
테이블세팅 값들 -> tableInfo { row: 0, col:0, mine:0 } (initialState)
세가지 값이 필요하다
GAME_START 액션후 tableInfo 값을 넣어주고,
다른값들초기화
case START_GAME:
return{
...state,
tableData: plantMine(action.row, action.col, action.mine),
gameOver: false,
opendCount:0,
tableInfo: { row: action.row, col: action.col, mine: action.mine},
result:''
};
checkAndOpen함수로 총 몇개 열었는지 count 한다
tableData[tr][td] = mineCount; /////////
tdOpen ++;
mineCount넣어주는 곳에 (칸open) tdOpen ++;
if( ((state.tableInfo.row*state.tableInfo.col)-state.tableInfo.mine) === state.opendCount+tdOpen ){
gameOver=true;
result='승리';
}
console.log('opendCount:'+state.opendCount);
return{
...state,
tableData,
gameOver,
opendCount: state.opendCount + tdOpen,
result,
}
state.tableInfo에 넣어둔 row, col, mine값 에서 openedCount 값이 맞아지면, 승리 !
타이머
타이머는, setInterval 1초마다 실행으로 만들면 되는데,
(()=>{ /* 숫자1씩증가state.timer+1*/ }, 1000)
현재 contextAPI 로 만든 state 에 접근하기 위해서 무조건 action 으로 처리해야 되기 때문에,
useEffect( ()=>{
const timer = setInterval( ()=>{
dispatch({ type:INCREMENT_TIMER });
}, 1000 );
return()=>{
clearInterval(timer)
}
} )
액션으로 만들어준 다음
case INCREMENT_TIMER:{
return{
...state,
timer: state.timer+1,
}
}
reducer 에서 처리해야된다
버튼눌렀을때 타이머가 실행되야 함으로 gameOver state를 이용해서 타이머를 제어한다
useEffect( ()=>{
let timer ;
if( gameOver == false ){
timer = setInterval( ()=>{
dispatch({ type:INCREMENT_TIMER });
}, 1000 );
}
return()=>{
clearInterval(timer)
}
} ,[gameOver])
Mine.jsx
import React ,{ useEffect, useReducer, createContext, useMemo }from 'react';
import Form from './Form';
import Table from './Table';
export const TD_STATE = {
MINE:-7, //지뢰심어짐
NORMAL:-1, //기본
FLAG: -3, //우클릭1 깃발
QUESTION:-2, //우클릭2 물음표
QUESTION_BUT: -4, //우클릭2 물음표(근데.지뢰있음)
FLAG_BUT:-5, //우클릭1 깃발(근데.지뢰있음)
OPENED_MINE: -6, //지뢰를클릭함.
OPENED :0, // 통과.
}
// 입력받은 값으로 칸 만들고 지뢰도 심어주는 함수.
const plantMine = (row, col, mine)=>{
const numArray = Array(row*col).fill().map((arr,i)=>{ return i }); //배열 0~99
const shuffle=[];
while( numArray.length > ((row*col)-mine) ){ // 100>80 // 99-- > 80
const beMine = numArray.splice(Math.floor(Math.random()*numArray.length), 1)[0];
//20개의 랜덤숫자(지뢰 위치가 될)
shuffle.push(beMine);
}
//칸만들어서 전부다 기본으로 채운다
const data = [];
for (let i=0; i<row; i++){
const rowData = [];
for(let j=0; j<col; j++){
rowData.push(TD_STATE.NORMAL);
}
data.push(rowData);
}
for( let k=0; k<shuffle.length; k++){ //지뢰갯수만큼.
const ver = Math.floor(shuffle[k] / col); //몇번째줄
const hor = shuffle[k] % col; //몇번째칸
data[ver][hor]=TD_STATE.MINE; //지뢰를 심음
}
return data;
}
export const TableContext = createContext({
tableData:[],
dispatch: () => {},
gameOver: true,
});
const initialState = { //2
tableData:[],
timer:0,
result:'',
gameOver: true,
opendCount: 0,
tableInfo:{ row:0, col:0, mine:0}, //////
}
export const START_GAME = 'START_GAME';
export const OPEN_TD = 'OPEN_TD';
export const OPEN_MINE = 'OPEN_MINE';
export const SET_QUESTION = 'SET_QUESTION';
export const SET_NORMAL = 'SET_NORMAL';
export const SET_FLAG = 'SET_FLAG';
export const INCREMENT_TIMER = 'INCREMENT_TIMER';
const reducer = (state,action)=>{ //3
switch (action.type){
case START_GAME:
return{
...state,
tableData: plantMine(action.row, action.col, action.mine),
gameOver: false,
opendCount:0,
tableInfo: { row: action.row, col: action.col, mine: action.mine},
result:'',
timer:0,
};
case OPEN_TD:{
const tableData = [...state.tableData];
tableData.forEach( (tr, i) =>{
tableData[i] = [...state.tableData[i]]; // ?
//tableData[i] = [...tr];
});
const checked = [];
let tdOpen = 0; //////
const checkAndOpen=(tr, td)=>{
if( tr<0 || tr >= tableData.length || td<0 || td >= tableData[0].length ){
return;
}
if( [TD_STATE.OPENED, TD_STATE.QUESTION, TD_STATE.QUESTION_BUT, TD_STATE.FLAG, TD_STATE.FLAG_BUT].includes( tableData[tr][td]) ){
return;
}
if( checked.includes(tr+','+td) ){
return;
}else{
checked.push(tr+','+td);
}
//주변 지뢰있는지검사.
let around = [
tableData[tr][td-1], tableData[tr][td+1]
];
if(tableData[tr-1]){
around = around.concat(
tableData[tr-1][td-1],
tableData[tr-1][td],
tableData[tr-1][td+1],
)
}
if(tableData[tr+1]){
around =around.concat(
tableData[tr+1][td-1],
tableData[tr+1][td],
tableData[tr+1][td+1],
);
}
const mineCount = around.filter((v)=>( [TD_STATE.MINE, TD_STATE.FLAG_BUT, TD_STATE.QUESTION_BUT].includes(v) )).length;
//지뢰가없으면 주변까지 연다.
if(mineCount === 0){
const near = [];
if( tr-1 > -1 ){
near.push([tr-1, td-1]);
near.push([tr-1, td]);
near.push([tr-1, td+1]);
}
near.push([tr, td-1]);
near.push([tr, td+1]);
if( tr+1 < tableData.length ){
near.push([tr+1, td-1]);
near.push([tr+1, td]);
near.push([tr+1, td+1]);
}
near.forEach((n)=>{
if( tableData[n[0]][n[1]] !== TD_STATE.OPEND ){
checkAndOpen(n[0],n[1]);
}
})
}
//지뢰 있으면 하나만 연다
if( tableData[tr][td] === TD_STATE.NORMAL ){
tdOpen ++;
tableData[tr][td] = mineCount; /////////
}
}
checkAndOpen( action.trIndex, action.tdIndex );
let gameOver = false;
let result = '';
//승리조건 체크
console.log( `((${state.tableInfo.row}*${state.tableInfo.col})-${state.tableInfo.mine}) === ${state.opendCount}+${tdOpen}` );
if( ((state.tableInfo.row*state.tableInfo.col)-state.tableInfo.mine) === state.opendCount+tdOpen ){
gameOver=true;
result=`${state.timer}초만에 승리`;
}
//console.log('opendCount:'+state.opendCount);
return{
...state,
tableData,
gameOver,
opendCount: state.opendCount + tdOpen,
result,
}
}
case OPEN_MINE:{
const tableData = [...state.tableData];
tableData[action.trIndex] = [...state.tableData[action.trIndex]];
tableData[action.trIndex][action.tdIndex] = TD_STATE.OPENED_MINE;
return{
...state,
tableData,
gameOver:true,
}
}
case SET_QUESTION:{
const tableData = [...state.tableData];
tableData[action.trIndex] = [...state.tableData[action.trIndex]];
if( tableData[action.trIndex][action.tdIndex] === TD_STATE.MINE){
tableData[action.trIndex][action.tdIndex] = TD_STATE.QUESTION_BUT;
}else{
tableData[action.trIndex][action.tdIndex] = TD_STATE.QUESTION;
}
return{
...state,
tableData,
}
}
case SET_NORMAL:{
const tableData = [...state.tableData];
tableData[action.trIndex] = [...state.tableData[action.trIndex]];
if( tableData[action.trIndex][action.tdIndex] === TD_STATE.QUESTION_BUT){
tableData[action.trIndex][action.tdIndex] = TD_STATE.MINE;
}else{
tableData[action.trIndex][action.tdIndex] = TD_STATE.NORMAL;
}
return{
...state,
tableData,
}
}
case SET_FLAG:{
const tableData = [...state.tableData];
tableData[action.trIndex] = [...state.tableData[action.trIndex]];
if( tableData[action.trIndex][action.tdIndex] === TD_STATE.MINE){
tableData[action.trIndex][action.tdIndex] = TD_STATE.FLAG_BUT;
}else{
tableData[action.trIndex][action.tdIndex] = TD_STATE.FLAG;
}
return{
...state,
tableData,
}
}
case INCREMENT_TIMER:{
return{
...state,
timer: state.timer+1,
}
}
default:
return state;
}
}
const Mine = () =>{
const [state, dispatch] = useReducer( reducer, initialState); //1
const { timer , result , tableData, gameOver } = state;
const tblContextValue = useMemo( ()=>({ tableData, dispatch , gameOver }) ,[tableData]);
useEffect( ()=>{
let timer ;
if( gameOver == false ){
timer = setInterval( ()=>{
dispatch({ type:INCREMENT_TIMER });
}, 1000 );
}
return()=>{
clearInterval(timer)
}
} ,[gameOver])
return(
<TableContext.Provider value={tblContextValue}>
<h3>지뢰찾기</h3>
<Form />
<Table />
<p>타이머:{timer}</p>
<p>결과:{result}</p>
</TableContext.Provider>
)
}
export default Mine;
Form.jsx
import React ,{ useState, useCallback ,useContext} from 'react';
import { TableContext ,START_GAME } from './Mine'; //
const Form = () =>{
const [ row, setRow ] = useState(10);
const [ col, setCol] = useState(10);
const [ mine, setMine] = useState(20);
const { dispatch } = useContext(TableContext);
const onChangeRow = useCallback( (e) =>{
setRow(e.target.value);
});
const onChangeCol = useCallback((e) =>{
setCol(e.target.value);
});
const onChangeMine = useCallback((e) =>{
setMine(e.target.value);
});
const onClickButton = useCallback( () =>{
dispatch({ type:START_GAME, row, col, mine });
}, [row, col, mine]);
return(
<>
<input type="number" placeholder="가로칸 갯수" value={ row} onChange={onChangeRow} />
<input type="number" placeholder="세로칸 갯수" value={ col} onChange={onChangeCol} />
<input type="number" placeholder="지뢰 갯수" value={ mine} onChange={onChangeMine} />
<p><button onClick={onClickButton}>게임시작</button></p>
</>
);
}
export default Form;
Table.jsx
import React, { useContext } from 'react';
import Tr from './Tr';
import { TableContext } from './Mine';
const Table = () =>{
const { tableData } = useContext(TableContext);
return(
<table>
<tbody>
{Array(tableData.length).fill().map( (tr, i)=>(<Tr trIndex={i}/>) )}
</tbody>
</table>
);
}
export default Table;
Tr.jsx
import React, { useContext } from 'react';
import Td from './Td';
import { TableContext } from './Mine';
const Tr = ({trIndex}) =>{
const { tableData }= useContext(TableContext);
//console.log( tableData[0]);
return(
<tr>
{ tableData[0] && Array(tableData[0].length).fill()
.map( ( td, i )=><Td trIndex={trIndex} tdIndex={i}/> ) }
</tr>
);
}
export default Tr;
Td.jsx
import React ,{ useContext, useCallback }from 'react';
import { TableContext, TD_STATE, OPEN_TD , OPEN_MINE, SET_QUESTION, SET_NORMAL, SET_FLAG} from './Mine';
const tdStyle = ( stateCode ) =>{
switch( stateCode ){
case TD_STATE.NORMAL:
case TD_STATE.MINE:
return{ background:'#6b6b6b'}
case TD_STATE.OPENED:
return{ background: '#fff' }
case TD_STATE.OPENED_MINE:
return{ background:'darkRed'}
case TD_STATE.FLAG_BUT:
case TD_STATE.FLAG:
return{ background:'gold'}
case TD_STATE.QUESTION:
return{ background:'#af97e8'}
}
};
const tdText = ( stateCode ) =>{
switch(stateCode){
case TD_STATE.NORMAL:
return '';
case TD_STATE.MINE:
return 'X';
case TD_STATE.OPENED_MINE:
return '펑!';
case TD_STATE.FLAG_BUT:
case TD_STATE.FLAG:
return '!~'
case TD_STATE.QUESTION:
return '?'
default:
return stateCode || '';
}
}
const Td = ({trIndex, tdIndex}) =>{
const{ tableData , dispatch , gameOver } = useContext(TableContext);
const stateCode = tableData[trIndex][tdIndex]; //-1, -7
const onClickTd = useCallback(() =>{
if(gameOver){
return;
}
switch( tableData[trIndex][tdIndex] ){ //0, -1 ,-7 ...
case TD_STATE.NORMAL : //그냥칸이면(-1) -열리게
dispatch({ type:OPEN_TD, trIndex, tdIndex });
return;
case TD_STATE.MINE : //마인칸이면(-7) -open_mine액션
dispatch({ type:OPEN_MINE, trIndex, tdIndex });
console.log('왜')
return;
default : //이미열린칸, 깃발, 깃발-지뢰, 물음표, 물음표-지뢰 는-동작안하게
return;
}
},[ tableData[trIndex][tdIndex] , gameOver ]); //계속바뀌는배열이니까 넣어주는것!
const onClick_RightTd =(e)=>{
e.preventDefault();
if(gameOver){
return;
}
switch( tableData[trIndex][tdIndex] ){
case TD_STATE.NORMAL :
case TD_STATE.MINE : // 지뢰, 기본칸이면 깃발로만들어줌.
dispatch({ type:SET_FLAG, trIndex, tdIndex });
return;
case TD_STATE.FLAG_BUT:
case TD_STATE.FLAG:
dispatch({ type:SET_QUESTION, trIndex, tdIndex });
return;
case TD_STATE.QUESTION_BUT:
case TD_STATE.QUESTION:
dispatch({ type:SET_NORMAL, trIndex, tdIndex });
return;
default :
return;
}
}
return(
<td onClick={onClickTd} onContextMenu={onClick_RightTd} style={tdStyle(stateCode)}>
{tdText(stateCode)}
</td>
);
}
export default Td;
'React > basic' 카테고리의 다른 글
14. (4)context API (0) | 2020.07.31 |
---|---|
14 (2)context API (0) | 2020.07.29 |
14. context API (0) | 2020.07.29 |
13. (3) useReducer (0) | 2020.07.29 |
13. (2) useReducer (0) | 2020.07.29 |