LoginSignup
KLB686
@KLB686

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【将棋】「持ち駒を使用する」挙動を実現したい。後手番のみ挙動を再現できない【javascript】

解決したいこと

【codepen】5*5将棋の挙動について
修正点①を解決したい

【codepen】

See the Pen Untitled by kmb686 (@kmb686) on CodePen.

修正点

①持ち駒を盤上に置くことができない(後手番のみ)
・持ち駒を選択し、動かすことはできる
・持ち駒を盤上に置くことができない。

※※補足※※
先手番(player = 0)は正しい挙動をしている
※※※※※※

背景

・html/jsにて5*5将棋を作成している
・「駒を動かす」まで実装
・「持ち駒」「成り駒」の処理は他サイトを参考にした
・知識不足もあり、全てのコードを理解できる水準に至っておらず、
 修正点について自力での解決に至らなかった

自分で試したこと/整理したこと

盤上の駒は正しく動かすことができ、持ち駒を選択することはできていることから
・駒を選択する
・移動可能先を表示する
は正しいものと考えた。

持ち駒について表記したのは「144-170L」の為、
下記のどこかに不備があると考えたが、発見に至っていない

【144-170L 概要】
isinside関数で盤内の処理であるかどうか判定
⇒ニ歩判定
⇒打ち込み可能位置を判定
⇒打ち込み可能位置をピンクにする

まとめ

投稿者の知識不足からの質問となり申し訳ございません。
ヒントや方針のみのアドバイスでもいただければ大変助かります。

質問内容、分かりづらい箇所あれば厳しくご指摘いただければ幸いです。
何卒よろしくお願い申し上げます。

0

2Answer

-          y = ofsy + (player * 6) + margin[id] * flip; //y で打ち込み可能な範囲を示す
+          y = ofsy + (player * 4) + margin[id] * flip; //y で打ち込み可能な範囲を示す

ではないでしょうか
(このゲームでは打ち歩詰めは禁じ手ではない、という前提があるのだろうという推測の下ですが)

個人的に、先手・後手が絡む処理を、1つの関数・処理で表現することにこだわって、複雑になりすぎてしまっているのではないかと思います。

上の部分も、私は実際には、周辺の変数をデバッグ出力しつつ、

          if (player == 0) {
            // 先手:盤面上端から下方向へ走査
            y = 3 + margin[id];
            flip = 1;
          } else  {
            // 後手:盤面下端から上方向へ走査
            y = 7 - margin[id]
            flip = -1;
          }

というコードでうまく動くことを確認してから、質問者さんの元のコードの形になるように導いたものです。(flipという変数で何をやってるのか、marginという配列の意味するところは、というところで1分くらい止まりました)

たとえば1つ1つの処理をもっと細かく関数に分けてもよいのではないでしょうか。
また式についても、短くするとスマートに見えるかもしれませんが、挙動がわかりにくくなるくらいなら、もっと愚直な形でもよいと思います。

0Like

Comments

  1. @KLB686

    Questioner
    Qnoir 様

    ご回答、ありがとうございます。
    ご指摘の通り「打ち歩詰め」については除外して考えておりました。

    処理について、短く書くことに固執しているとのご指摘、ありがとうございます。
    レビュー時によく指摘される点で改善ができていない点だと反省する限りでございます。

    コメントいただきました通り、自分でも変数の出力、整理をしてみました。
    「 (player * 4) 」の部分が今回の原因であった点、自分でも腑に落ちた次第です。

    改めまして、ご指摘ありがとうございます。
    書いた自分でも把握できていない属人性の強いものになっていたようでございます。

    折角のアドバイスをムダにしないよう、もう少し分かりやすいコードを書けるようがんばってみようと思います。

    Qnoir 様。ご回答、また率直な意見をお聞かせいただき改めまして感謝申し上げます。
    ありがとうございました!

元のコードの意図を残したまま解決するのであればこんな感じでしょうか...

.js
// L160
y = (player == 0 ? ofsy : bh - ofsy - 1) + margin[id] * flip

ただ答えがわかってもこれだけでは意味がないので

変数・定数が多くなってしまって,各値のもたらす意味を把握できなくなっていたりしないでしょうか?
多分 player * 6 が何を目的に書いていたのかなども少し考えなければ難しいと思いますので,なるべく情報をシンプルにできると書くのも読むのもわかりやすいコードになっていくかと思います


具体的に今のコード全体を見て今後リファクタリングできそうなところをあげると,

.js
var board = [];
var bw = 13, bh = 11;
var ofsx = 4, ofsy = 3;

ここが結構難しくしてると思っていて,
将棋のロジックとしての盤面も,持ち駒を表示する場所を示す領域も board に含めてしまってるようですが,

.js
var board = [];
var bw = 5, bh = 5;

のようにすれば,将棋の盤面内のロジックはこの 5x5 の配列だけで完結して, ofsx, ofsy を使わずにかけるように成って各関数が持ってる引数も減らせるかと思います


とはいえ,一旦は将棋のシステム自体の完成を目指して,出来上がったら次へのステップアップとしてリファクタリングなどに挑戦してみるのも良いかもですね

0Like

Comments

  1. @KLB686

    Questioner
    @WGG_SH 様

    ご回答、ありがとうございます。
    ご指摘、アドバイスを全て読ませていただきました。

    変数・定数が多くなってしまって,各値のもたらす意味を把握できなくなっていたりしないでしょうか?
    ⇒ご指摘の通りでございます。
     今回、助言をいただき再度デバックをした上で把握できたくらいですので、自分の中でも整理が追い付いてところが大いにあると感じました。
     今後の大きな改善点であると痛感しております。アドバイス、ありがとうございます。

    具体的に今のコード全体を見て今後リファクタリングできそうなところ
    ⇒こちらもコメントありがとうございます。
     当初は「盤上と持ち駒を別で書いたら長くなってしまうだろうな…」という思いから
     ofs部分をまとめてしまおうという考えで作成したという経緯です。

     しかし、ご指摘の通り、ofs分を検算して数値を決める場面が多くなってしまったなという印象です。今回の一番の原因である「分かりづらさ」に直結してしまったなと大いに反省しております。

    今後について
    ⇒今後の方針についての助言、誠にありがとうございます。
     まずは、未実装の機能(「王手」機能や「打ち歩詰め」制限やゲーム開始と終了など)について考えつつ作成しようと思います。
     並行して、「各関数が持ってる引数を減らす」ことを意識することを大切さを今一度意識しようと思います。可読性の高いコードにも繋げる為にも励んでいきたいと思います。

    当質問、複数の回答社様のご協力で解決に至りましたが、自力で解決してしかるべき内容だったと反省するばかりです。

    改めまして、回答者様「Qnoir」「WGG_SH」に感謝申し上げます。
    誠にありがとうございました。

    質問に頼らず、今回いただいたアドバイス、ご指摘を活かせるよう頑張ろうと思います。
    ご回答者様、閲覧していただきました方、誠にありがとうございました!

    ※上記内容にて一旦クローズとさせていただきます
     ありがとうございました

Your answer might help someone💌