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

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

【将棋盤 第5回】動けるマスの表示と制限【修正】

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

使用技術

  • Vue.js3
  • Vite
  • SCSS

yushi-dev.hatenablog.com

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

前回は失敗したのですが...今回はその修正です。

yushi-dev.hatenablog.com

駒の動けるマスの、定義し直し

香車、飛車、角行はある方向に無限に動ける駒ですが、この扱い方を前回は失敗しました。

前回は、全マスを動けるマスとして登録しました。

      '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]),

修正版では、単にInfinityで登録しておきます。

      'rook': [
        [+Infinity, 0],
        [-Infinity, 0],
        [0, +Infinity],
        [0, -Infinity],
      ],

盤上の駒が動けるマスのリスト

修正版では、ここでInfinityを元にした算出をします。

    currentMovableList() {
      if (!this.selected) {
        return []
      }
      // 先手なら+1, 後手なら-1をかける
      const sign = this.selected.isFirst ? 1 : -1
      return this.selected.movableList
        // 移動量に、手番を反映する.
        .map(([column, row]) => [sign * column, sign * row])
        // 現在のマスから見た移動可能マスに変換
        .flatMap(([column, row]) => {
          if (isFinite(column) && isFinite(row)) {
            return [[this.selected.column + column, this.selected.row + row]]
          }
          // 無限に進める駒.
          // Infinity -> 1, -Infinity -> -1, 0 -> 0.
          const columnSign = Math.sign(column)
          const rowSign = Math.sign(row)
          const res = []
          for (let i of [...Array(8).keys()].map(i => i + 1)) {
            // 移動先のマス.
            const nextBlock = [this.selected.column + i * columnSign, this.selected.row + i * rowSign]
            // 当該マスに今いる駒.
            const existPiece = this.getPiece(nextBlock[0], nextBlock[1])
            if (existPiece) {
              // 当該マスにすでに駒がある場合.
              if (existPiece.isFirst !== this.selected.isFirst) {
                // 敵の駒なら取れる.
                res.push(nextBlock)
              }
              // これ以上先には移動できない.
              break
            }
            res.push(nextBlock)
          }
          return res
        })
        // 番外のマスを除く
        .filter(([column, row]) => column >= 1 && column <= 9 && row >= 1 && row <= 9)
    }

Infinityに対しては、forループを回し、他の駒があるマスではループを終了します。

ゴリ押しの解決ですが、これが限界かなと思っています...。

完成した画面

無事に、駒を飛び越えなくなりました。

相手の駒はちゃんと取れそうです。

f:id:yushi0:20210320183813p:plain

Pull Request

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

まとめ

無事解決できてよかったです。

Board.vueにロジックが溜まりすぎたので、ここは解決したいです。