将棋をプログラミングする方法を考察

ゲームシステム分析

将棋 プログラミング

こんにちは。なおキーヌです。

ブログ毎日更新は302日目になります。

私の古くからの友人で将棋が好きがいるのですが、相手になりたいと思っても私自身が将棋を全然覚えられないのです。

流石に駒の動きや基本的なルールは覚えられたのですが、どうやって攻めていけばいいのかわかりません。

恐らく定石を覚えてしまえばある程度指せるのでしょうがいかんせん頭に入って来ません。

私は中世ファンタジー大好きの西洋かぶれなので恐らくその辺が壁になってそうな気がします。

例えばファイアーエムブレムのような見た目の将棋であれば恐らく必死になって覚えようと思います。

しかし意外と探しても将棋を元にしたファンタジーなゲームって出てないんですよね。

将棋の西洋版がチェスなんでしょうが、それはなんかちょっと違うんです(分かって!)

私はどちらも全然やってないので判断は付かないのですが、
将棋もチェスもやってる人は大抵将棋の方が面白いというんですよ。

調べてみるとどうやら海外の方も将棋の方が複雑で面白いという声も多いみたいですね。

今回はそんな将棋のプログラミングを考えてみました。

私が知っているのは

  • 駒の種類
  • 駒の動かし方
  • 駒の並べ方
  • 成駒
  • ゲームの終わらせ方

以上です!

一応これだけあればゲームをすることはできます。

攻め方は後から考えればいいでしょう……

とりあえずゲームを始めるまでの作り方を考えてみます。

  1. 駒を定義する
  2. 選択した駒を動かせるエリアを表示する
  3. 移動した先に相手の駒があれば獲得する
  4. 王を取ればゲームを終了させる

駒を定義する

まずは駒を定義しないと始まるものも始まらないですね。

そういえばプチコン4に将棋の駒画像があったので後で作っていくことを考えて、
言語はSmileBasicベースで考えてみましょう。

駒を管理するのは配列で良さそうですね。

自分用の配列と相手用の配列を用意すれば管理は楽そうです。

メモリを極限まで突き詰めたいという人は、1つの配列にまとめてしまうのもありですね。

プログラミングでは数値で管理していくのが基本になりますが、そこまで重たいプログラムにはならないので
文字列でやってしまってもいいのですが、この辺はお好みです。

私は文字列管理は好きではないので数値で管理していこうと思います。

例えば駒配列の0番目は王、1番目は金1、2番目は金2という感じで0と1で管理していくと楽そうです。

1が存在する。0が存在しない。

でよさそうですが……ちょっとまってください。

将棋は相手の取った駒を再利用することができるので単純に作ってしまっては破綻してしまいそうです。

とりあえず最低限初期の駒の配列は作っておいて問題なさそうですね。

それにプラスして同じサイズの配列を作り、相手の駒を取ったときに該当する場所に格納するといった感じでしょうか。

イメージ的には以下のようになります。

  • 王 = 0
  • 金1 = 1
  • 金2 = 2
  • 銀1 = 3
  • 銀2 = 4
  • 桂1 = 5
  • 桂2 = 6
  • 香1 = 7
  • 香2 = 8
  • 飛 = 9
  • 角 = 10
  • 歩x9 = 11-19
  • 玉 = 20
  • 予金1 = 21
  • 予金2 = 22
  • 予銀1 = 23
  • 予銀2 = 24
  • 予桂1 = 25
  • 予桂2 = 26
  • 予香1 = 27
  • 予香2 = 28
  • 予飛 = 29
  • 予角 = 30
  • 予歩x9 = 31-39

綺麗に配列数40で収まりましたね。

美しいです。

右の数値は配列の要素数になります。

取った駒はその値を保持しておいて配列に入れるときにその値を参照すれば処理も楽です。

駒定義に関してはこれでよさそうです。

後は同じようにスプライトを生成していけば見た目も問題なさそうです。

選択した駒を動かせるエリアを表示する

それぞれの駒スプライトを定位置に座標を指定して、選択カーソルスプライトを用意して動かせるようにします。

そして、カーソルが当たっている駒を取得するようにして選択したら、
その駒の動かせる範囲を描写すれば親切ですね。

この範囲描写はON出来ると親切です。

基本的には動かせる範囲しか置けないようにしとかないと、ゲームとして破綻しますし
もし例外な場所に置いたら強制で反則負けだとストレスがたまるのでやらないほうがいいですね。

移動した先に相手の駒があれば獲得する

将棋は9x9のグリッドに駒が居るか居ないかの判定を取ることができますので、
駒を動かしたときに相手の駒があればその駒のIDを元に配列に追加するという処理を行えばよさそうです。

そしてその際に取られた側の配列はマイナスしておかないと駒が重複してしまいますので、
このあたりの処理はしっかりと作っておかないとゲームが破綻してしまいます。

チェスであれば相手の駒は取れないので処理も楽なのですが、
将棋の場合は駒を取る、駒をある程度好きな位置におけるという処理が増えるので少しくむのが大変です。

その置ける置けないの処理も現在の駒の状況からみて計算しなければいけないので
意外と将棋のプログラムを作るのは難しいかもしれません。

王を取ればゲームを終了させる

後は王を取るもしくは王が詰み状態になったらゲーム終了をすればゲームとしては完成です。

恐らく後者が一般的な将棋のゲームですね。

今まで見てきた将棋ゲームの中で実際に王を取って終わるという処理をみたことはありません。

勝利判定は詰みだけが判定なのでその計算さえしてしまえば結果や経過は一切関係ないので処理づくりは楽そうです。

やはりAIが使われるだけあっておくところが可能なマスの計算が一番大変そうな感じがしました。

これをうまく組むことが出来れば意外と短いソースコードで基本的な仕組みは出来上がりそうですね。

プレイヤーvsプレイヤーの場合だとこれである程度ゲームは出来そうですが、
NPCと対局するときは相手のAIを作る必要があります。

ココが恐らく一番難しい所だと思いますね。

現在の状況に応じて計算する必要があるので、良いアルゴリズムでないと処理負荷が大きくなりそうです。

一番良いのはオープンソースとして公開している将棋ゲームのソースコードを読むのが良さそうですね。

でも初心者はソースコードが読むのが辛いと思うので今後私も勉強がてら将棋ゲーム作り講座をやっていこうと思います。

そのためには私が将棋の経験を積まないと色々と解説ができなさそうなので、
友人に協力してもらって将棋を覚えていこうと思います。

それでは。