★前回の記事
前回までで解けた場合のフィールドを表示しました。今回は途中の経過も表示します。 ピースが置けた時にフィールドを更新します。
途中経過の表示方法
途中経過を表示します。ピースが置けたときに画面を更新します。
画面を一定時間ごとに更新したいので、処理を待たせるコードを入れたいのですが、
JavaScriptにはsleep
のような関数はありません。
代わりに、setTimeout
(
WindowOrWorkerGlobalScope.setTimeout() - Web API | MDN
)
を使用します。setTImeout
の引数に、現在実行しているsolver.solve
関数を指定し、繰り返し処理を行います。
そのため、while
によるループは不要になります。
実装
はじめに、フィールドの再描画を行うための準備をします。
現在display.js
内で、テーブルをhtmlの最後の要素として追加していますが、div
の内容を書き換えるように変更します。
index.html
<!DOCTYPE html> <html> <head> <!-- 中略 --> </head> <body> <!-- 追加ここから --> <div id="katamino-field"> <table id="katamino-table"> <tr> <td> </td> </tr> </table> </div> <!-- 追加ここまで --> <!-- 中略 --> </body> </html>
次に、katamino-field
の中の、katamino-table
を置き換えるように変更します。
js/display.js
const display = { show : (kataminoField) => { const table = document.createElement("table") table.setAttribute("id","katamino-table") kataminoField.forEach((fieldRow) => { // 中略 }) // 変更ここから const old = document.getElementById("katamino-table") document.getElementById("katamino-field").replaceChild(table, old) // 変更ここまで }, }
準備が整ったので、js/solver.js
を、setTimeout
を使用するように書き換えます。
solver.solve
のはじめに、スタックが空かどうか判定するロジックを入れています。
ピースがフィールドの外か、すでにピースが置かれているので置けない場合は、次の処理をすぐ実行するように、
setTimeout(solver.solve, 0)
を実行します。continue
をreturn
に変更します。
ピースが置けたときはdisplay.show(nextField)
を実行し、表示を更新します。また、関数の一番最後でsetTimeout(solver.solve, 300)
を実行して次のループを300ミリ秒後に行うように設定します。
KATAMINOが完成した場合の、break
はreturn
に変更します。
js/solver.js
const solver = { // 中略 solve : () => { // 追加ここから if (solver.solverStack.length <= 0) { console.log("解けなかった") return } // 追加ここまで // while (solver.solverStack.length > 0) { 削除 const {kataminoField, minEmpty, pieceId, spinId, spin, unPlacedPiece} = solver.solverStack.pop() console.log("pieceId", pieceId) console.log("spinId", spinId) const offset = {x: minEmpty.x, y: minEmpty.y - spin[0].y} if (! solver.isAllEmpty(kataminoField, spin, offset)) { // フィールドの外か、すでにピースが置かれている console.log("フィールドの外か、すでにピースが置かれている") setTimeout(solver.solve, 0) // 追加 return // 変更 } console.log("ピースが置ける") const nextField = util.copyArrayOfArray(kataminoField) solver.placeSpin(nextField, spin, offset, pieceId) console.log("nextField", nextField) const nextUnPlaced = unPlacedPiece.filter(id => id !== pieceId) console.log("nextUnPlaced", nextUnPlaced) display.show(nextField) // 追加 if (nextUnPlaced.length <= 0) { console.log("完成") // display.show(nextField) は削除 return // 変更 } const nextEmpty = solver.findNextEmpty(nextField, minEmpty) console.log("nextEmpty", nextEmpty) nextUnPlaced.forEach((nextPieceId) => { KATAMINO_ARR[nextPieceId].forEach((nextSpin, nextSpinId) => { solver.solverStack.push({kataminoField: nextField, minEmpty: nextEmpty, pieceId:nextPieceId, spinId:nextSpinId, spin: nextSpin, unPlacedPiece: nextUnPlaced,}) }) }) setTimeout(solver.solve, 300) // 追加 // } 削除 }, }
動作確認
実行結果です。ピースを置いていく過程がアニメーションされました。
★次回の記事
★目次