ピースを画面から選べるようにする (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

これまで、使用するピースはjs/main.jsで指定してきましたが、画面で選べるように変更します。

表示するピースの画像の準備

ピースを選択する際にどのピースの画像を表示させます。画像をダウンロードします。

KATAMINO-SOLVER/KATAMINO-SOLVER-main/img/piece at master · yucatio/KATAMINO-SOLVER · GitHub

ピース画像は上記リンクのpiece_0_0.png, piece_1_0.png, piece_2_0.png, piece_3_0.png, ... piece_10_0.png, piece_11_0.png を使用します。

img/pieceフォルダを作成し、piece_0_0.pngからpiece_11_0.pngまでをこのフォルダ内に保存します。

f:id:yucatio:20190808154351p:plain

入力フォームを作成します。フォームにチェックボックスと、それに対応するピースの画像、最後にボタンを作成します。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>KATAMINO SOLVER</title>
    <link rel="stylesheet" type="text/css" href="css/main.css">
  </head>
  <body>
    <!-- 追加ここから -->
    <form name="piece-selection">
      <fieldset>
        <input id="piece_0" type="checkbox" name="piece" value="0">
        <label for="piece_0">
          <img src="img/piece/piece_0_0.png" width="125px"/>
        </label>
        <input id="piece_1" type="checkbox" name="piece" value="1" checked>
        <label for="piece_1">
          <img src="img/piece/piece_1_0.png" width="100px"/>
        </label>
        <input id="piece_2" type="checkbox" name="piece" value="2" checked>
        <label for="piece_2">
          <img src="img/piece/piece_2_0.png" width="100px"/>
        </label>
        <input id="piece_3" type="checkbox" name="piece" value="3">
        <label for="piece_3">
          <img src="img/piece/piece_3_0.png" width="100px"/>
        </label>
        <input id="piece_4" type="checkbox" name="piece" value="4">
        <label for="piece_4">
          <img src="img/piece/piece_4_0.png" width="75px"/>
        </label>
        <input id="piece_5" type="checkbox" name="piece" value="5">
        <label for="piece_5">
          <img src="img/piece/piece_5_0.png" width="75px"/>
        </label>
        <input id="piece_6" type="checkbox" name="piece" value="6">
        <label for="piece_6">
          <img src="img/piece/piece_6_0.png" width="75px"/>
        </label>
        <input id="piece_7" type="checkbox" name="piece" value="7">
        <label for="piece_7">
          <img src="img/piece/piece_7_0.png" width="75px"/>
        </label>
        <input id="piece_8" type="checkbox" name="piece" value="8">
        <label for="piece_8">
          <img src="img/piece/piece_8_0.png" width="75px"/>
        </label>
        <input id="piece_9" type="checkbox" name="piece" value="9" checked>
        <label for="piece_9">
          <img src="img/piece/piece_9_0.png" width="75px"/>
        </label>
        <input id="piece_10" type="checkbox" name="piece" value="10">
        <label for="piece_10">
          <img src="img/piece/piece_10_0.png" width="75px"/>
        </label>
        <input id="piece_11" type="checkbox" name="piece" value="11">
        <label for="piece_11">
          <img src="img/piece/piece_11_0.png" width="75px"/>
        </label>
      </fieldset>
      <button type="button">スタート</button>
    </form>
    <!-- 追加ここまで -->

    <div id="katamino-field">
      <table id="katamino-table">
        <tr>
          <td>
          </td>
        </tr>
      </table>
    </div>

    <script src="js/util.js"></script>
    <script src="js/katamino-arr.js"></script>
    <script src="js/display.js"></script>
    <script src="js/solver.js"></script>
    <script src="js/main.js"></script>
  </body>
</html>

実行結果です。チェックボックスと対応するピースの画像が表示されました。まだボタンを押しても何も起こりません。

f:id:yucatio:20190808154747p:plain

ボタンが押されたときに呼び出される関数を作成します。先に選択されたピースを取得するところまで実装します。今までの実装は削除します。 選択されているピースの番号を取得し、 document.getElementsByName("piece")でピースのセレクトッボックスのhtmlノードを取得します。 このメソッドが返す値は、配列ではなく、配列風オブジェクトなので、mapfilterは呼び出せません。 Array.from(pieceInputs)( Array.from() - JavaScript | MDN ) で配列に変換します。filterでチェックがついている要素のみに絞り込み、さらにそれらの値を整数値に変換します。

js/main.js

// solver.init([1, 2, 9]) は削除
// solver.solve() は削除

function startSolve() {
  console.log("startSolve")

  const pieceInputs = document.getElementsByName("piece")

  const targetPiece = Array.from(pieceInputs).filter(pieceElement =>
    pieceElement.checked
  ).map(pieceElement =>
    parseInt(pieceElement.value, 10)
  )

  console.log(targetPiece)

}

KATAMINOはピースが3つ以上でないと解けないため、3以下の場合はreturnします。本来であれば画面にエラーメッセージを表示すべきですが、今回はコンソールのみに表示します。エラーメッセージはSTEP2で表示します。

チェックが終わったらsolverを初期化し、スタートします。

js/main.js

// solver.init([1, 2, 9]) は削除
// solver.solve() は削除

function startSolve() {
  console.log("startSolve")

  const pieceInputs = document.getElementsByName("piece")

  const targetPiece = Array.from(pieceInputs).filter(pieceElement =>
    pieceElement.checked
  ).map(pieceElement =>
    parseInt(pieceElement.value, 10)
  )

  console.log(targetPiece)

  // 追加ここから
  if (targetPiece.length < 3) {
    // TODO: エラーメッセージを表示
    console.log("選択されたピースの個数が3未満")
    return
  }

  solver.init(targetPiece)
  solver.solve()
  // 追加ここまで
}

最後にボタンが押されたときにstartSolve()を呼び出すように変更します。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>KATAMINO SOLVER</title>
    <link rel="stylesheet" type="text/css" href="css/main.css">
  </head>
  <body>
    <form name="piece_selection">
        <!-- 中略 -->
       <button type="button" onclick="startSolve()">スタート</button>  <!-- 変更 -->
    </form>
    <!-- 中略 -->
  </body>
</html>

動作確認

実行結果です。選択されたピースでKATAMINOを説いています。

解いている途中↓

f:id:yucatio:20190810210048p:plain

完成↓

f:id:yucatio:20190810210112p:plain

以上でピースを画面から選べるようになりました。考慮すべき点がもれているところはいくつかありますが、STEP2でカバーしていきます。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com