yucatio@システムエンジニア

趣味で作ったものいろいろ

使うピースの選択を実装する (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

プログラミングをしていきます。まずは使うピースの選択です。

状態の追加

選択中のピースをstateに追加します。 初期値はpieceIdが1, 2, 9, 5, 10ですので、これを追加します。

js/state.js

const state = {
  // One of "selectPiece", "solving", "solvedSuccess", "solvedFailed", "pause"
  solverState: "selectPiece",
  // 追加
  targetPieces: [1, 2, 9, 5, 10],
}

state.targetPiecesの初期値は、初期化処理でhtml要素から取得した方がよいのですが、今回は簡易的にstateに直接書き込みました。

actionの登録

ピースがドロップされたときの動作を実装します。各エリアにドロップされたときに使うピースを更新します。

ドロップされたときの動作はdroppable関数のdropプロパティに記載します。使わないピースのエリア#unused-piece-droppableにドロップされたときは、ドロップされたピースを使うピースから削除するaction.removeFromTargetPieces(まだ定義していません)を呼び出します。同様に使うピースのエリア(#used-piece-droppable)にドロップされたときは、ドロップされたピースを使うピースに追加するaction.addToTargetPieces(まだ定義していません)を呼び出します。

ピースのIDは、 <span id="piece_0" class="draggable-piece m-2 p-0" data-piece-id="0">のように書いたhtmlタグの、data-piece-id="0"の部分から取得します。取得した際は文字列型なので、数値型に変換します。

js/main.js

// 前略

const initializer = {
  setEvent: () => {
    $(".draggable-piece").draggable({
      revert: "invalid"
    })

    $("#unused-piece-droppable").droppable({
      hoverClass: "bg-light",
      accept: ".draggable-piece",
      // 追加ここから
      drop : ((e, ui) => {
        const pieceId = ui.draggable.data("piece-id")
        action.removeFromTargetPieces(parseInt(pieceId, 10))
      }),
      // 追加ここまで
    })

    $("#used-piece-droppable").droppable({
      hoverClass: "hover",
      accept: ".draggable-piece",
      // 追加ここから
      drop : ((e, ui) => {
        const pieceId = ui.draggable.data("piece-id")
        action.addToTargetPieces(parseInt(pieceId, 10))
      }),
      // 追加ここまで
    })
  },
}

actionの実装

ドロップされたピースを使うピースから削除するaction.removeFromTargetPiecesとドロップされたピースを使うピースに追加するaction.addToTargetPiecesを実装します。

先にaction.removeFromTargetPiecesを実装します。受け取ったpieceIdが、使うピース(state.targetPieces)に含まれているか判定します。ピースが含まれていれば、そのピースの番号を使うピースのリストから削除します。新しいリストをstateManagerに渡します。 受け取ったpieceIdが、使うピースに含まれているかはindexOfの値が0以上かどうかで判定します。選択したピースのリストからの削除にはfilterを使用しています。 stateManager.setTargetPiecesはまだ実装していません。

ja/action.js

// 追加ここから
const action = {
  removeFromTargetPieces: (pieceId) => {
    if (state.targetPieces.indexOf(pieceId) >= 0) {
      const newPieces = state.targetPieces.filter(id => id !== pieceId)
      stateManager.setTargetPieces(newPieces)
    }
  },
}
// 追加ここまで

次に、action.addToTargetPiecesを実装します。受け取ったpieceIdが、使うピース(state.targetPieces)に含まれているか判定し、含まれいなければ、pieceIdを追加した配列をstateManager.setTargetPiecesに渡します。(この関数はまだ定義していません)

js/action.js

const action = {
  // 中略
  // 追加ここから
  addToTargetPieces: (pieceId) => {
    if (state.targetPieces.indexOf(pieceId) < 0) {
      stateManager.setTargetPieces([...state.targetPieces, pieceId])
    }
  },
  // 追加ここまで
}

stateManagerの実装

stateManager.setTargetPiecesを実装します。stateを書き換えます。(stateManagerのみがstateを書き換えることができます。) 書き換えたあとは画面を更新するのですが、一旦ここでコンソールに表示してここまでの動作を確認しましょう。

js/stateManager.js

// 追加ここから
const stateManager = {
  setTargetPieces: (targetPieces) => {
    state.targetPieces = targetPieces

    // TODO displayの呼び出し
    console.log("state.targetPieces", state.targetPieces)
  },
}
// 追加ここまで

ここまでの実行結果

実行結果です。"使うピース"の中にあるピースがstate.targetPiecesと同期しているのが分かります。

使わないピースを使うピースのエリアにドロップする↓ 6番のピースをドロップすると、targetPiecesの末尾に番号が追加されました。

f:id:yucatio:20191013131857p:plain

使うピースを使わないピースにのエリアにドロップする↓ 5番ののピースをドロップすると、targetPiecesから番号が削除されました。

f:id:yucatio:20191013131918p:plain

ボタンの表示の切り替え

ボタンの表示を切り替えます。選択されたピースの個数が3未満の場合には"つかうピースをもっとおいてください"のボタンを表示します。3以上の場合はスタートボタンを表示します。ボタンの表示の切り替えはtoggle関数で行います。

js/display.js

const display = {
  // show プロパティは削除

  // 追加ここから
  updateStartButtons: ({targetPieces}) => {
    $("#start-button").toggle(
      targetPieces.length >= 3
    )
    $("#more-piece-button").toggle(
      targetPieces.length < 3
    )
  },
  // 追加ここまで
}

使うピースが更新されたときに、ボタンの更新を呼び出すようにstateManagerを更新します。

js/stateManager.js

const stateManager = {
  setTargetPieces: (targetPieces) => {
    state.targetPieces = targetPieces

    // console.log("state.targetPieces", state.targetPieces) は削除してもよい
    // 追加
    display.updateStartButtons(state)
  },
}

実行結果

実行結果です。

使うピースが3個以上の場合↓

f:id:yucatio:20191013132123p:plain

使うピースが3個未満の場合↓

f:id:yucatio:20191013132140p:plain

以上で使うピースの選択を実装ができました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com