地雷捜索器の作成(7)


Step 7


地雷を踏むと、他の地雷が現れます。


MineSearch.jsx
case CLICK_MINE: {
		const tableData = [...state.tableData];
		tableData[action.row] = [...state.tableData[action.row]];
		tableData[action.row][action.cell] = CODE.CLICKED_MINE;
		for(let i = 0 ; i < state.gameData.row; i++) {
		    for(let j = 0 ; j < state.gameData.cell; j++) {
		        if (tableData[i][j] === CODE.MINE || tableData[i][j] === CODE.FLAG_MINE) {
		            tableData[i][j] = CODE.CLICKED_MINE;
		        }
		    }
		...
}

に飾りを付ける


FontAwesomeの使用
npm i --save @fortawesome/fontawesome-svg-core
npm install --save @fortawesome/free-solid-svg-icons
npm install --save @fortawesome/react-fontawesome
isWinという新しい状態を作成しfalseに初期化
const initialState = {
    tableData: [],
    timer: 0,
    result: '',
    halted: true,
    gameData: {
        row: 0,
        cell: 0,
        mine: 0,
    },
    isWin: false,
}
OPEN CELL動作中
勝ちの条件としてisWinをtrueに変換
そして結果はそうなります.
if (openCount === state.gameData.row*state.gameData.cell-state.gameData.mine) {
    halted = true;
    result = <div>You won in {state.timer} seconds!!</div>;
    isWin = true;
}
レンダー部分cssクラスを使用して、使用条件が勝つか負けるかを区別します.
return (
        //value = {{ tableData: state.tableData, dispatch }} 원래는 이렇게 들어가지만 useMemo로 캐싱해줌
        <TableContext.Provider value = {value}>  
            <Form />
            <div class="timer"><FontAwesomeIcon icon={faStopwatch} /> {timer}</div>
            <Table />
            
            {state.isWin?<div class="result-win"><FontAwesomeIcon icon={faSmileWink} /> {result}</div>:<div class="result-fail">{result}</div>}
        </TableContext.Provider>
    )
Tdのスタイルとテキスト置換関数の変更
const getTdStyle = (code) => {
    switch (code) {
        case CODE.NORMAL:
        case CODE.MINE:
            return {
                background: '#444',
            };
        case CODE.CLICKED_MINE:
            return {
                background: 'red',
            };
        case CODE.OPENED:
            return {
                background: 'white',
            };
        case CODE.QUESTION_MINE:
        case CODE.QUESTION:
            return {
                background: 'yellow',
            }
        case CODE.FLAG_MINE:
        case CODE.FLAG:
            return {
                background: 'green',
            }
        default:
            return {
                background: 'white',
            };
    }
};

const getTdText = (code) => {
    switch (code) {
        case CODE.NORMAL:
            return '';
        case CODE.MINE:
            return '';
        case CODE.CLICKED_MINE:
            const boom = <FontAwesomeIcon icon={faBomb} />
            return boom;
        case CODE.FLAG_MINE:
        case CODE.FLAG:
            const flag = <FontAwesomeIcon icon={faFlag} />
            return flag;
        case CODE.QUESTION_MINE:
        case CODE.QUESTION:
            const question = <FontAwesomeIcon icon={faQuestion} />
            return question;
        default:
            return code || '';
    }

};
最後にcssを変更すると
App.css
.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.result-fail {
  font-size: 30px;
  font-weight: bold;
  color: #b52020;
}

.result-win {
  font-size: 30px;
  font-weight: bold;
  color: #000000;
  color: orange;
}

.result-win .fa-smile-wink {
  font-size: 50px;
}

.svg-inline--fa {
  font-size: 23px;
}

.fa-bomb {
  font-size: 28px;
}

table {
  border-collapse: collapse;
  margin: 50px auto;
}

td {
  border: 5px solid black;
  width: 40px;
  height: 40px;
  text-align: center;
  font-weight: bold;
  font-size: 24px;
}

.fa-skull-crossbones {
  font-size: 60px;
}

.timer .svg-inline--fa {
  font-size: inherit;
}

.timer {
  margin-top: 30px;
  font-size: 40px;
}

.set-option {
  display: flex;
  margin: 30px auto 0;
  justify-content: center;
}

.set-option input[type="number"] {
  width: 9%;
  height: 30px;
  font-size: 22px;
  margin-right: 22px;
  /* padding: 0 10px; */
  text-align: center;
  border: 0;
  /* text-indent: 17px; */
  border-bottom: 4px solid #000;
}

.set-option button {
  width: 10%;
  font-size: 17px;
  font-weight: bold;
}