★前回の記事
一時停止、再開機能を実装します。
一時停止機能は、solver.solve
で実行したsetTimeout
をキャンセル(clearTimeout
)することで実現します。
timerの保存
setTimeout
をキャンセルするには、setTimeouot
の戻り値が必要になります。solver
のプロパティに保存するように変更しましょう。
js/solver.js
const solver = { solverStack : [], // 追加 timer: null, init : (targetPiece) => { const kataminoField = new Array(5).fill().map(() => ( new Array(targetPiece.length).fill(-1) )) solver.solverStack = [] // 追加 timer = null // 中略 }, solve : (options) => { // 中略 if (! solver.isAllEmpty(kataminoField, spin, offset)) { // フィールドの外か、すでにピースが置かれている console.log("フィールドの外か、すでにピースが置かれている") // 変更前 // setTimeout(() => solver.solve(options), 0) // 変更後 solver.timer = setTimeout(() => solver.solve(options), 0) return } console.log("ピースが置ける") // 中略 if (! solver.hasAllFiveTimesCells(nextField, nextEmpty)){ console.log("フィールドが5の倍数以外で分断されている") // 変更前 // setTimeout(() => solver.solve(options), 300) // 変更後 solver.timer = setTimeout(() => solver.solve(options), 300) return } // 中略 // 変更前 // setTimeout(() => solver.solve(options), 300) // 変更後 solver.timer = setTimeout(() => solver.solve(options), 300) }, // 後略 }
timerのキャンセル
timerのキャンセルをする関数をsolver
に定義します。clearTimeoutを使用します。
js/solver.js
const solver = { // 前略 // 追加ここから stop: () => { clearTimeout(solver.timer) }, // 追加ここまで }
ここまででKATAMINOを解くのをストップさせる準備が整いました。
停止・再開機能のactionへの登録
停止・再開ボタンにactionを登録します。(action.pause
とaction.resume
はまだ実装されていません)
js/main.js
// 前略 const initializer = { setEvent: () => { // 中略 // 追加ここから $("#pause-button").on("click", () => { action.pause() }) $("#resume-button").on("click", () => { action.resume() }) // 追加ここまで }, }
停止・再開actionの登録
停止アクションでは、solverをストップさせ、pause
の状態へ遷移します。
再開アクションでは、solverをスタートさせ、solving
の状態へ遷移します。
js/action.js
const action = { // 中略 // 追加ここから pause: () => { solver.stop() stateManager.setSolverState("pause") }, resume: () => { solver.solve({ onUpdatePieces: (placedPieces) => stateManager.setPlacedPieces(placedPieces), onSolved: () => stateManager.setSolverState("solvedSuccess"), onNotSolved: () => stateManager.setSolverState("solvedFailed"), }) stateManager.setSolverState("solving") }, // 追加ここまで }
displayの実装
停止ボタンは画面の状態がsolving
のときのみ押せるようにします。
再開ボタンは画面の状態がpause
のときのみ押せるようにします。
js/display.js
const display = { // 前略 // 追加ここから updatePauseResumeButton: ({solverState}) => { $("#pause-button").prop("disabled", solverState !== "solving") $("#resume-button").prop("disabled", solverState !== "pause") }, // 追加ここまで }
stateManagerへの登録
solverState
が変わったときにupdatePauseResumeButton
を呼び出します。
js/stateManager.js
const stateManager = { setSolverState: (solverState) => { state.solverState = solverState display.updateDraggablePieces(state) display.updateStartButtons(state) display.updateResultMessage(state) // 追加 display.updatePauseResumeButton(state) }, // 後略 }
実行結果
実行結果です。 KATAMINOを解いている間は、停止ボタンが有効になり、押すと解いている途中で止まります。再開ボタンを押すと再び動き出します。再開ボタンは停止中のみ有効になっています。
リファクタリング
action
のなかで、solver.solve
を、startSolve
とresume
で2回同じパラメータで呼び出しているので、1つにまとめましょう。
js/action.js
const action = { // 中略 startSolve: () => { solver.init(state.targetPieces) // 変更前 // solver.solve({ // onUpdatePieces: (placedPieces) => stateManager.setPlacedPieces(placedPieces), // onSolved: () => stateManager.setSolverState("solvedSuccess"), // onNotSolved: () => stateManager.setSolverState("solvedFailed"), // }) // 変更後 action.solve() stateManager.setSolverState("solving") }, // 中略 resume: () => { // 変更前 // solver.solve({ // onUpdatePieces: (placedPieces) => stateManager.setPlacedPieces(placedPieces), // onSolved: () => stateManager.setSolverState("solvedSuccess"), // onNotSolved: () => stateManager.setSolverState("solvedFailed"), // }) // 変更後 action.solve() stateManager.setSolverState("solving") }, // 追加ここから solve: () => { solver.solve({ onUpdatePieces: (placedPieces) => stateManager.setPlacedPieces(placedPieces), onSolved: () => stateManager.setSolverState("solvedSuccess"), onNotSolved: () => stateManager.setSolverState("solvedFailed"), }) }, // 追加ここまで }
以上で一時停止、再開機能が実装できました。
★次回の記事
★目次