フィールドにピースが置けるかどうかの判定 (KATAMINOを解くプログラムを作成する)
★前回の記事
前回まででスピンをどこに移動するか求めることができたので、今回はその位置に置けるかどうかを判定する関数を作成します。
ピースがフィールドに置ける条件は、以下の2点を満たすことです。
- ピースがフィールドの外に出ていないこと
- 置こうとする場所にすでに他のピースが置かれていないこと
置ける例↓

置けない例↓

実装
フィールドにスピンが置けるかを判定する、isAllEmpty関数とisEmpty関数を定義します。isAllEmptyは、スピンが置かれるすべてのマスが、フィールドの範囲内でまだピースが置かれていないときにtrueを返す関数です。
isEmptyは、placeの位置がフィールドの外でなく、かつまだピースが置かれていないときにtrueを返す関数です。
はじめに呼び出し側の実装をします。isAllEmptyでスピンが置けるか判定し、置けなかった場合には処理を中断し、ループの先頭に戻ります。
js/solver.js
const solver = { // 中略 solve : () => { 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("フィールドの外か、すでにピースが置かれている") continue } console.log("ピースが置ける") // 追加ここまで } }, // 追加ここから isAllEmpty: (kataminoField, places, offset) => { // TODO 実装 return false }, isEmpty: (kataminoField, place) => { // TODO 実装 return false }, // 追加ここまで }
isAllEmptyからisEmptyを呼び出しましょう。Array.every
(
Array.prototype.every() - JavaScript | MDN
)
はコールバックに渡された関数が、配列のすべての要素に対して、true相当を返すかどうかを判定します。
isEmptyの引数には、スピンが実際に置かれるマスを渡すので、offsetをそれぞれ加算した値を渡しています。
isAllEmpty: (kataminoField, places, offset) => { return places.every((place) => ( solver.isEmpty(kataminoField, {x: place.x + offset.x, y: place.y + offset.y}) )) },
次に、isEmpty関数を実装します。まずはplaceの位置がフィールドの内のときにtrueを返すようにします。JavaScriptの場合は、配列の定義外の範囲を参照するとundefinedが返ってくるので、それで判定します。place.xもplace.yもundefinedでなければフィールドの範囲内です。
isEmpty: (kataminoField, place) => { return ( kataminoField[place.x] !== undefined && kataminoField[place.x][place.y] !== undefined ) },
次に、置こうとする場所にすでに他のピースが置かれていないことを判定します。フィールドにピースが置かれているときはそのピースの番号、置かれていないときは-1なので、ピースが置かれているかどうかは0より小さいかどうかで判定します。
isEmpty: (kataminoField, place) => { return ( kataminoField[place.x] !== undefined && kataminoField[place.x][place.y] !== undefined && kataminoField[place.x][place.y] < 0 ) },
動作確認
動作結果です。コンソールの出力はこのようになっています。

下記の図と対応させてみると、

(pieceId, spinId) = (9, 1), (9, 0), (2, 7), (2, 1), (1, 7), (1, 3), (1, 1)
が初期状態で置けることが分かり、コンソールの出力結果と一致していることが分かります。
★次回の記事
★目次