スマレジエンジニアyushiのブログ

スマレジエンジニアのブログ

【将棋盤 第4回】動けるマスの表示と制限【失敗例】

引き続き将棋盤を作っていきます。

使用技術

  • Vue.js3
  • Vite
  • SCSS

yushi-dev.hatenablog.com

今回は、駒を動かせるマスの表示と制限をしていきます。

...のつもりでしたが、ミスりました

十分検討せずに実装を始めてしまうとどうなるのか、共有していきます。

駒ごとの、動けるマスの定義

駒ごとの、動けるマスを定義します。

今のマスから見て、右上が[-1, -1]、真下が[0, 1]といった具合で、動けるマスのリストとして定義します。

飛車、角行、香車は、一定方向にいくらでも進めるという特徴を持った駒です。

実現方法に少し迷いましたが、単に各方向の全マスを登録します(これが間違いだった...)。

 get movableList(): number[][] {
    return {
      'king': [
        [-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1],
      ],
      'rook': [
        ...[...Array(8).keys()].map((i) => [0, i]),
        ...[...Array(8).keys()].map((i) => [0, -i]),
        ...[...Array(8).keys()].map((i) => [i, 0]),
        ...[...Array(8).keys()].map((i) => [-i, 0]),
      ],
      'bishop': [
        ...[...Array(8).keys()].map((i) => [i, i]),
        ...[...Array(8).keys()].map((i) => [-i, -i]),
        ...[...Array(8).keys()].map((i) => [i, -i]),
        ...[...Array(8).keys()].map((i) => [-i, i]),
      ],
      'gold': [
        [-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [0, 1],
      ],
      'silver': [
        [-1, -1], [0, -1], [1, -1], [-1, 1], [1, 1],
      ],
      'knight': [
        [-1, -2], [1, -2],
      ],
      'lance': [
        ...[...Array(8).keys()].map((i) => [0, -i]),
      ],
      'pawn': [
        [0, -1],
      ],
    }[this.type];
  }

駒が、今のマスから動けるマス

次に、今のマスから動けるマスを取得できるようにします。

先手後手、現在マスを元に割り出します。

  get currentMovableList(): number[][] {
    // 先手なら+1, 後手なら-1をかける
    const sign = this.isFirst ? 1 : -1

    return this.movableList
      .map(([column, row]) => [sign * column, sign * row])
      // 現在のマスから見た移動可能マスに変換
      .map(([column, row]) => [this.column + column, this.row + row])
      // 番外のマスを除く
      .filter(([column, row]) => column >= 1 && column <= 9 && row >= 1 && row <= 9)
  }

動けるマスの表示と制限

今度はVue側で、表示と制限を行います。

現在選択中の駒が、移動可能なマスかどうかのメソッドを定義します。

    /**
     * 現在選択中の駒が、移動可能なマスかどうか.
     */
    isMovableBox(column, row) {
      if (!this.selected) {
        return false
      }
      if (
        !!this.pieces.find((piece) => piece.isFirst === this.isFirst
          && piece.column === column
          && piece.row === row)
      ) {
        // すでに自分の駒があるマスの場合
        return false
      }
      return !!this.selected.currentMovableList
        .find(([c, r]) => c === column && r === row)
    }
  },

移動可能なマスに、movable-boxというクラスを指定します。

    getBoxClass(column, row) {
      return {
        'movable-box': this.isMovableBox(column, row),
      }
    },

その他、isMovableBox === falseには移動できないように記述します。

完成した画面

動けるマス、かつ自分の駒がない駒だけ動ける表示(黄色マス)ができています。

f:id:yushi0:20210314143021p:plain

後手番でもうまく動いています。

f:id:yushi0:20210314143157p:plain

...おやおや?

f:id:yushi0:20210314143301p:plain

f:id:yushi0:20210314143308p:plain

はい、角も香車も飛車も、駒を飛び越えることができないんですが、その想定が漏れていました。

まだ考えて切れていないですが、今の想定でこの問題を解消するのは難しいような気がします。いったん考え直しか...。

Pull Request

https://github.com/nek0meshi/shogi-board/pull/4

まとめ

今回は、動けるマスの表示と制限...をしようとしたんですが、失敗してしまいました。

ちゃんと考えてから手は動かさないとダメですね。反省です。