yucatio@システムエンジニア

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

スタートボタンの用意 (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

KATAMINOを解くのをスタートさせるボタンを用意します。

ボタンの種類と実装方針

作成するプログラムでの、ボタンの状態は以下の4つです。

  • 押せる状態のスタートボタン
  • 押せない状態のスタートボタン
  • "つかうピースをもっとおいてください"と書いてある、押せないボタン
  • "ピースをえらびなおす"と書いてある、押せるボタン

f:id:yucatio:20191008084618p:plain

ボタンの状態の切り替えを実現する際に、以下の2つの方法が考えられます。

  1. 1つボタンを用意しておいて、色や内容を切り替える
  2. ボタンを複数用意しておいて表示を切り替える

どちらの実装でも問題ないですが、今回は2つ目の方法を主に採用します。 JavaScript内に文言を書かないようにするためです。(文言を書くと複数言語に対応できないので)

スタートボタンの押せる・押せないの切り替えはJavaScript内で行います。

実装

ボタンを用意します。bootstrapのbuttonコンポーネントを使用します。

index.html

<!-- 前略 -->
        <div class="card-footer">
          つかうピース
        </div>
      </div><!-- end of card for used-piece -->
      
      <!-- 追加ここから -->
      <button type="button" id="start-button" class="btn btn-warning btn-lg btn-block my-3">スタート</button>
      <button type="button" id="more-piece-button" class="btn btn-warning btn-lg btn-block my-3" disabled>つかうピースをもっとおいてください</button>
      <button type="button" id="reset-button" class="btn btn-danger btn-lg btn-block my-3">ピースをえらびなおす</button>
      <!-- 追加ここまで -->
    </div><!-- end of container -->
<!-- 後略 -->

ここまでの実行結果

実行結果です。ボタンが3つ表示されました。

f:id:yucatio:20191007112723p:plain

ボタンを非表示にする

"つかうピースをもっとおいてください"ボタンと"ピースをえらびなおす"ボタンを非表示にします。

main.css

#more-piece-button, #reset-button {
  display: none;
}

実行結果

実行結果です。スタートボタンのみ表示されました。

f:id:yucatio:20191007112739p:plain

以上でボタンの準備が完了しました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com

ピースをドラッグ&ドロップさせる(jQuery-UI使用) (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

前回までで、選択用のピースを画面に表示させることができました。今回はピースをドラッグ&ドロップさせる処理を追加します。

draggableとdroppableの設定

jQuery-UIのdroppableのページを参考に、ピースをドラッグ&ドロップするコードを書いていきます。 draggable-pieceクラスを付与したピースをドラッグ可能にします。 ドロップ可能な範囲にドロップされない場合には、元の位置に戻したいので、revert: "invalid"を指定しています。

unused-piece-droppableused-piece-droppableをドロップ可能にします。 hoverClassプロパティにそれぞれドロップ領域に重なった時のクラスを記載します。used-piece-droppablehoverClass: "hover"は後で定義します。

js/mian.jsの以前のコードは全て削除します。

js/main.js

$( function() {
  initializer.setEvent()
})

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

    $("#unused-piece-droppable").droppable({
      hoverClass: "bg-light",
      accept: ".draggable-piece",
    })

    $("#used-piece-droppable").droppable({
      hoverClass: "hover",
      accept: ".draggable-piece",
    })
  },
}

js/main.jsを読み込みます。

index.html

<!-- 前略 -->
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
    <!-- 追加 -->
    <script src="js/main.js"></script>
  </body>
</html>

main.css#used-piece-droppable.hoverの設定を追加します。こうすることで、ドロップされるときオレンジが少し濃くなります。

css/main.css

#used-piece-droppable.hover {
  background-color: #ffecb3;
}

ここまでの動作確認

実行結果です。ピースがドラッグできるようになっています。

f:id:yucatio:20191007110948p:plain

しかし、使わないピースを使うピースにドラッグしていくと、使うピースのcardの後ろにピースが隠れてしましました。

f:id:yucatio:20191007111001p:plain

z-indexで重なりの順番を調整する

ピースがcardの後ろに隠れてしまう現象を解消するために、draggable-piecez-indexの設定を追加します。z-indexはhtmlの要素の重なり順を調整するパラメータです。今回は10にしています。

css/main.css

.draggable-piece {
  z-index: 10;
}

動作確認

実行結果です。ドラッグしてもピースが隠れずに移動できました。

f:id:yucatio:20191007111012p:plain

以上でjQuery-UIを使用してピースをドラッグ&ドロップさせることができました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com

ピースの選択エリアの作成 (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

ピースの選択エリアを作成します。ドラッグアンドドロップでピースを選択できるようにします。 jQuery-UIのDraggableDroppableを使用します。

使用するbootstrapのコンポーネントは以下のようにContainerAlertCardを使用します。

f:id:yucatio:20191007095431p:plain

使うピースと使わないピースの配置

ピースを選択する画面を作成しましょう。まずはピースを置く枠を作成します。cardコンポーネントを使用します。

text-centerでテキストを中央寄せしています(参考: Text · Bootstrap)。 my-4my-2はマージンの設定です(参考: Spacing · Bootstrap)。

index.html

<!-- 前略 -->
  <body>
    <nav class="navbar navbar-expand-md navbar-light shadow-sm mb-5">
      <img class="navbar-brand" src="img/logo/Primary_logo_on_transparent_400x63.png" />
    </nav>
    <!-- <h1>Hello, world!</h1> は削除 -->
    <!-- 追加ここから -->
    <div class="container">
      <div class="alert alert-warning text-center my-4">
        つかうピースを ドラッグアンドドロップで したのわくに いれてから スタートボタンをおしてね
      </div>
      <div id="unused-piece" class="card text-center my-2">
        <div id="unused-piece-droppable" class="card-body">
        </div>
      </div><!-- end of card for unused-piece -->
      <div id="used-piece" class="card text-center border-warning my-2">
        <div id="used-piece-droppable" class="card-body">
        </div>
        <div class="card-footer">
          つかうピース
        </div>
      </div><!-- end of card for used-piece -->
    </div><!-- end of container -->
    <!-- 追加ここまで -->
<!-- 後略 -->

ピースを配置していきます。ピース番号1, 2, ,9, 5, 10のピースは使うピースに配置しておきましょう。 各ピースには、draggable-pieceというクラス名を付与しています。これはドラッグ対象を指定するために使用されます。data-piece-idの属性も付与します。これは、どのピースが選択されたかを判断するために使用されます。

index.html

<!-- 前略 -->
  <body>
    <nav class="navbar navbar-expand-md navbar-light shadow-sm mb-5">
      <img class="navbar-brand" src="img/logo/Primary_logo_on_transparent_400x63.png" />
    </nav>
    <div class="container">
      <div id="unused-piece" class="card text-center my-2">
        <div id="unused-piece-droppable" class="card-body">
          <!-- 追加ここから -->
          <span id="piece_0" class="draggable-piece m-2 p-0" data-piece-id="0">
            <img src="img/piece/piece_0_1.png" width="25px" />
          </span>
          <span id="piece_3" class="draggable-piece m-2 p-0" data-piece-id="3">
            <img src="img/piece/piece_3_5.png" width="50px" />
          </span>
          <span id="piece_4" class="draggable-piece m-2 p-0" data-piece-id="4">
            <img src="img/piece/piece_4_2.png" width="75px" />
          </span>
          <span id="piece_6" class="draggable-piece m-2 p-0" data-piece-id="6">
            <img src="img/piece/piece_6_1.png" width="50px" />
          </span>
          <span id="piece_7" class="draggable-piece m-2 p-0" data-piece-id="7">
            <img src="img/piece/piece_7_0.png" width="75px" />
          </span>
          <span id="piece_8" class="draggable-piece m-2 p-0" data-piece-id="8">
            <img src="img/piece/piece_8_0.png" width="75px" />
          </span>
          <span id="piece_11" class="draggable-piece m-2 p-0" data-piece-id="11">
            <img src="img/piece/piece_11_0.png" width="75px" />
          </span>
          <!-- 追加ここまで -->
        </div>
      </div><!-- end of card for unused-piece -->
      <div id="used-piece" class="card text-center border-warning my-2">
        <div id="used-piece-droppable" class="card-body">
          <!-- 追加ここから -->
          <span id="piece_1" class="draggable-piece m-2 p-0" data-piece-id="1">
            <img src="img/piece/piece_1_5.png" width="50px" />
          </span>
          <span id="piece_2" class="draggable-piece m-2 p-0" data-piece-id="2">
            <img src="img/piece/piece_2_5.png" width="50px" />
          </span>
          <span id="piece_9" class="draggable-piece m-2 p-0" data-piece-id="9">
            <img src="img/piece/piece_9_0.png" width="75px" />
          </span>
          <span id="piece_5" class="draggable-piece m-2 p-0" data-piece-id="5">
            <img src="img/piece/piece_5_3.png" width="50px" />
          </span>
          <span id="piece_10" class="draggable-piece m-2 p-0" data-piece-id="10">
            <img src="img/piece/piece_10_0.png" width="75px" />
          </span>
          <!-- 追加ここまで -->
        </div>
        <div class="card-footer">
          つかうピース
        </div>
      </div><!-- end of card for used-piece -->
<!-- 後略 -->

使うピースの背景色を変更します。

css/main.css

#used-piece-droppable {
  background-color: #fff8e1;
}

ここまでの実行結果

ここまでの実行結果です。 枠の中にピースが表示されました。

f:id:yucatio:20191006224308p:plain

矢印の描画

上から下にピースを移動させるということがわかりやすいように、使用しないピースのcardから使用するピースのcardへ矢印を描きます。

【CSS】CSSのみで三角と矢印を作る方法 - bagelee(ベーグリー) のページを参考にし、CSSで矢印を描画します。

使わないピースと使うピースのcardの間に矢印を配置します。htmlに追記します。mx-autoでページの中央に表示されるようにしています。

index.html

<!-- 前略 -->
  <body>
    <!-- 中略 -->
        </div>
      </div><!-- end of card for unused-piece -->
      <!-- 追加ここから -->
      <div class="arrow-down mx-auto">
      </div>
      <!-- 追加ここまで -->
      <div id="used-piece" class="card text-center border-warning my-2">
        <div id="used-piece-droppable" class="card-body">
<!-- 後略 -->

CSSのみで三角と矢印を作る方法ページの内容を参考に、以下の内容を追加します。

css/main.css

.arrow-down {
  width: 0;
  height: 0;
  border-left: 80px solid transparent;
  border-right: 80px solid transparent;
  border-top: 30px solid #ffc107;
}

実行結果

実行結果です。使うピースと使わないピースの間に矢印が表示されました。

f:id:yucatio:20191006224343p:plain

以上でピースの選択エリアの、見た目の部分が完成しました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com

KATAMINOピースの用意 (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

STEP 1では、KATAMINOのフィールドの1マスをテーブルの1セルに対応させていました。

f:id:yucatio:20190810210112p:plain

このままでは見栄えが良くないので改善します。

改善したいポイントとしては、1ピースの中ではボーターを表示せず、さらにピースとピースの境目は強調することです。テーブルの使用をやめ(そもそもこのような目的でテーブル使用すべきでない)、画像を用いるようにします。

ピースとスピンの組み合わせの画像を作成しましょう。画像エディタを開き、グリッドを表示します。各ピースの画像を描き、枠線も入れます。色は前回の配色のままにしました。

f:id:yucatio:20191005132219p:plain

回転、反転して各ピース(最大)8パターンのスピンを作成し、img/pieceフォルダの下にpiece_${pieceId}_${spinId}.png命名規則で登録します。登録したものは下のリンクからダウンンロードできます。

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

それぞれ以下の表に対応しています。

f:id:yucatio:20191005132316p:plain

フォルダ構成はこのようになっています。

f:id:yucatio:20191005132456p:plain

displayの変更

STEP 1ではsolverからdisplaykataminoFieldを渡していましたが、ピースの表示を画像に変更すると、kataminoFieldを渡しても、どこにどの画像を表示するのかわかりません。代わりに、どこにどの画像を表示するのかを渡す必要があります。その対応はもう少し先で行います。

以上でKATAMINOピースの用意が完了しました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com

ロゴの作成とbootstrapのnavbarの設定 (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

見た目を整える最初の1歩として、ロゴを作成して表示してみましょう。Webで無料でロゴが作れるサービスはいくつかありますが、今回はLOGASTER を利用しました。

会社名に"KATAMINO SOLVER"と入力して、次へを押すと、ロゴの候補が表示されるので、好きなロゴを選んでダウンロードします。

f:id:yucatio:20191005125849p:plain

f:id:yucatio:20191005125907p:plain

f:id:yucatio:20191005125920p:plain

imgフォルダの下に、logoディレクトリを作成し、使用したいロゴファイルをコピーします。 (今回は、1_Primary_logo_on_transparent_400x63.pngPrimary_logo_on_transparent_400x63.pngにリネームしています。サイズを表す400x63の部分はダウンロードしたファイルによって違います。)

f:id:yucatio:20191005125935p:plain

実装

ページ上部にナビゲーションバーを設置し、ロゴの画像を表示します。bootstrapのnavbarのページ ( Navbar · Bootstrap ) を参考に実装します。

shadow-smで影をつけています (参考: Shadows · Bootstrap)。 mb-5はbottomのマージンの指定です (参考: Spacing · Bootstrap)。

index.html

<!-- 前略 -->
  <body>
    <!-- 追加ここから -->
    <nav class="navbar navbar-expand-md navbar-light shadow-sm mb-5">
      <!-- ファイル名はダウロードしたファイルごとに違うので、適宜書き換えてください -->
      <img class="navbar-brand" src="img/logo/Primary_logo_on_transparent_400x63.png" />
    </nav>
    <!-- 追加ここまで -->
    <h1>Hello, world!</h1>
<!-- 後略 -->

今回はロゴの色に合わせて背景色を変更します。前回までのCSSの内容は全て削除します。

css/main.css

nav {
  /* 好きな色に変えてください */
  background-color: #fd9a29;
}

css/main.cssを読み込みます。

index.html

<!doctype html>
<html lang="ja">
  <head>
    <!-- 中略 -->

    <!-- 追加 -->
    <link rel="stylesheet" href="css/main.css">
    <title>KATAMINO SOLVER</title>
  </head>
<!-- 後略 -->

実行結果

実行結果です。ヘッダーが表示されました。

f:id:yucatio:20191005125949p:plain

以上でロゴの作成とbootstrapのnavbarの設定ができました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com

bootstrapとjQueryの設定 (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

はじめに、bootstrapとjQuery, jQuery-UIのライブラリを読み込んでおきましょう。 ひな形をbootstrapのページからコピーします。前回までの内容は一旦全て削除します。

Introduction · Bootstrap のページ内のStarter Templeteをコピーします。

index.html

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>

jQueryのライブラリとbootstrapのライブラリが読み込めました。

表示はこのようになりました。

f:id:yucatio:20191004225552p:plain

jQuery-UIも読み込んでおきましょう。バージョンは2019年8月時点での安定版の1.12.1にしています。ここで1つ注意点があります。boostrapで読み込んでいるのは、jquery-3.3.1.slim.min.jsです。slimと付いているのは、jQueryのコアな機能のみを提供しているためです。jQuery-UIを使用するには、slimの機能だけでは足りないので、jQueryの全ての機能が入ったjquery-3.3.1.min.jsを使用するように変更します。

<!-- 前略 -->

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <! -- 変更 -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <! -- 追加 -->
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
  </body>
</html>

最後に、lang="en"の部分を直しましょう。lang="en"は、"このページは英語で書かれている"という意味なので、日本語を表すlang="ja"に変更します。また、タイトルも"KATAMINO SOLVER"に変更しておきましょう。

<!doctype html>
<html lang="ja"><! -- 変更 -->
  <head>
    <!-- 中略 -->
    <title>KATAMINO SOLVER</title>
  </head>
<!-- 以下略 -->

画面とデベロッパーコンソールを表示して、エラーが出ていないことを確認します。

以上でbootstrapとjQuery, jQuery-UIの設定をしたhtmlファイルの準備が整いました。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com

STEP2での成果物 (KATAMINOを解くプログラムを作成する)

★前回の記事

yucatio.hatenablog.com

STEP2では見た目を整えてアプリを完成させます。 ページを開いた時の見た目はこのようになります。

f:id:yucatio:20191010231229p:plain

画面上部でピースを選択します。スタートボタンを押すと、解くのを開始し、解く過程が表示されます。

ピースの選択(ドラッグアンドドロップ)↓

f:id:yucatio:20191003082948p:plain

解いている過程。フィールドにピースの画像が表示されます↓

f:id:yucatio:20191003083016p:plain

解けたときにこのようなダイアログを表示します↓

f:id:yucatio:20191003083031p:plain

解けなかったときにはこのようなダイアログを表示します↓

f:id:yucatio:20191003083044p:plain

解き終わった後はピースを選び直すボタンを表示します↓

f:id:yucatio:20191003083056p:plain

また、以下の機能も実装します。

  • 選択したピースが3個未満の場合はスタートボタンを押せないようにする
  • フィールドに置かれたピースは選択エリアから消す
  • ピースを1つずつ選択エリアに戻す処理を追加する
  • 一時停止、再生機能を追加する
  • 解く速度を変更できるようにする

使用するライブラリ

2019年現在、フロントエンドのライブラリばReactやVueが使われていますが、 ドラッグ&ドロップ機能を使用したいので、jQueryを使用します。ドラッグ&ドロップjQuery UIの機能です。

CSSフライブラリにはbootstrapを使用します。

解説する内容について

この記事を書いているブログ主はデザインについては素人なのでデザイン面の解説はしません。 プログラムの部分のみ解説します。

それではSTEP 2を始めましょう。


★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com