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

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

【将棋盤 第2回】駒を並べる

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

使用技術

  • Vue.js3
  • Vite
  • SCSS

今回は、駒を並べる機能を作成します。

型定義

ほぼ初めてTypeScriptを使ってみます。

駒の種類を型として定義します。
union型を使っていますが、ググるenumよりをこちらを使えと出てきたからです。理由は追い追い理解していきます。

export type PieceType =
  'king' // 王将・玉将
  | 'rook' // 飛車
  | 'bishop' // 角行
  | 'gold' // 金将
  | 'silver' // 銀将
  | 'knight' // 桂馬
  | 'lance' // 香車
  | 'pawn'; // 歩兵

クラス定義

駒一枚一枚の状態などを表現するクラスを作成します。

export class Piece {
  id: number;
  type: PieceType; // 駒の種類
  isFirst: boolean; // true: 先手, false: 後手
  isPromoted: boolean; // true: 成り
  column: number; // 列
  row: number; // 行

  constructor(type: PieceType, isFirst: boolean, column: number, row: number) {
    this.type = type;
    this.isFirst = isFirst;
    this.isPromoted = false;
    this.column = column;
    this.row = row;
    this.id = autoIncrementId;
    autoIncrementId += 1;
  }
  ...
}

このPieceインスタンスの配列を用意すれば、画面機能が良い感じに表示してくれる、という想定です。

画面表示

Pieceクラスの情報を元に、position: absoluteで駒を画面配置します。

  methods: {
    pieceStyle(piece) {
      return {
        right: (21 + 51 * (piece.column - 1)) + 'px',
        top: (21 + 51 * (piece.row - 1)) + 'px',
        transform: 'rotate(' + (piece.isFirst ? 0 : 180) + 'deg)',
      }
    },
  },

画面に並べます。

      <div
        v-for="p in pieces"
        class="piece"
        :style="pieceStyle(p)"
        :key="p.id"
      >
        {{ p.name }}
      </div>

Pieceインスタンス作成

いい感じの関数を作りました。
トリッキーなので良し悪しは半々です。

/**
 * @param name 駒の名前
 * @param positions 先手の駒配置の配列 [[column, row], [column, row], ...]
 * @return 先手後手両方分のPieceのconstructorの引数
 */
const splitFirstAndSecond = (name, positions) => positions
  .flatMap((position) => ([
    // 先手
    [true, position[0], position[1]],
    // 後手
    [false, 10 - position[0], 10 - position[1]],
  ]))
  .map((position) => [name, ...position])
  methods: {
    initPieces() {
      this.pieces = [
        ...splitFirstAndSecond('king', [[5, 9]]),
        ...splitFirstAndSecond('rook', [[2, 8]]),
        ...splitFirstAndSecond('bishop', [[8, 8]]),
        ...splitFirstAndSecond('gold', [[4, 9], [6, 9]]),
        ...splitFirstAndSecond('silver', [[3, 9], [7, 9]]),
        ...splitFirstAndSecond('knight', [[2, 9], [8, 9]]),
        ...splitFirstAndSecond('lance', [[1, 9], [9, 9]]),
        ...splitFirstAndSecond('pawn', [[1, 7], [2, 7], [3, 7], [4, 7], [5, 7], [6, 7], [7, 7], [8, 7], [9, 7]]),
      ]
        .map((params) => new Piece(...params))
  }

完成した画面

f:id:yushi0:20210221173807p:plain

ソースコード

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

まとめ

ベースとなるクラス定義と画面表示ができました。

TypeScriptを使えたのは嬉しいです。少しずつ理解していきたいです。

次回以降は駒を動かしていきます。