引き続き将棋盤を作っていきます。
使用技術
- Vue.js3
- Vite
- SCSS
駒を動かせるマスの表示と制限をしていきます。
前回は失敗したのですが...今回はその修正です。
駒の動けるマスの、定義し直し
香車、飛車、角行はある方向に無限に動ける駒ですが、この扱い方を前回は失敗しました。
前回は、全マスを動けるマスとして登録しました。
'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ループを回し、他の駒があるマスではループを終了します。
ゴリ押しの解決ですが、これが限界かなと思っています...。
完成した画面
無事に、駒を飛び越えなくなりました。
相手の駒はちゃんと取れそうです。
Pull Request
https://github.com/nek0meshi/shogi-board/pull/5
まとめ
無事解決できてよかったです。
Board.vueにロジックが溜まりすぎたので、ここは解決したいです。