終盤を読み切る

ゲームの終盤を読み切って勝利に導きます。
20手先まで読み切れたら鬼に金棒なのですが?

前田稔(Maeda Minoru)の超初心者のプログラム入門

終盤を読み切るプログラム

  1. 「残り4手を読み切る」プログラムを作成して下さい。
    これが作成できれば「何手先でも読み切れる」プログラムはもうそこです。
  2. 良く似た関数が沢山でてきましたが、まとめて整理して下さい。
    手番をパラメータとして渡すと、すぐにでも関数の個数を半分ぐらいには出来るでしょう。
    最終的には、これらの関数を一個にまとめることが可能で、しかも Think2 や Think3 と同じぐらいの ステップ数で完成するのですが?
  3. この考え方を発展させれば、論理的には何手先でも読み切ることが可能です。
    何十手先までも読み切るには、再起処理が必要でプログラムも一段と難しくなるのですが、不思議なことに 出来上がったプログラムは嘘のように短くなります。
    私が作成した再起関数のパラメータです。
        //★ コンピュータが考える再帰関数
        //  lev=      再帰のレベル(最初は0で、最大20)
        //  c=        手番(黒=1, 白=-1)
        //  *pos=     lev==0 のとき最善手(Y<<4|X)を格納する
        //  ST[8][8]= 評価する盤面(Object Class area)
        //  Return=   最善手の評価値
        long  Think(OseroApp *App, short lev, short c, BYTE *pos)
        {
        
  4. コンピュータは処理が速いので何手でも先が読めると思われるでしょうが、考慮時間やメモリ容量の関係で 十数手が限界でしょうが、それでも終盤に関しては無敵になります。
    最後の十手ぐらいは読みきるルーチンを完成させて、強力な思考 DLL を作成して下さい。
  5. 残り4手(コンピュータの手番○)で、局面を設定してみました。
    評価はコンピュータ側(○)から見た値です。
    ○の手番では、評価値が最も大きい手を選択します。
    ●の手番では、評価値が最も小さい手を選択します。
    下図の場合には最終的にAの手が選択されます。

再起関数の作成

  1. 関数(Think)の中から自分自身(Think)を呼び出す関数を再起関数と呼びます。
    再起関数では「自分自身が多重に呼ばれる」と考えると思考が混乱するので「自分と同じような関数」が幾つもあって、 その関数が次々と呼び出されると考えて下さい。
  2. 再起処理の考え方とループの考え方は同じで、ループで行う処理は全て再起で行うことができます。
    ループの時と同じように次のことを考慮して下さい。
  3. 最後に他人が組んだ再起プログラムをデバッグするほど難解なものはありません。
    うまく組まれた再起プログラムは「理論整然と芸術的と言えるほど実にスマート」なのですが、作成者自身が デバッグ出来ないような再起プログラムはデバッグ不能と思って下さい。
    再起プログラムではプログラムのトレースが非常に困難で、論理の流れを確かめることが不可能に近いのです。

再起の限界

  1. 終盤を20手先まで読み切れたら鬼に金棒なのですが、私がテストした結果では13手ぐらいが限界で、 これを超えると数十分単位の考慮時間が必要になります。
    さらに一手進めると、数十分が数百分に、もう一手進めると数千分かかるのですから話になりません。
    局面にもよりますが、残り16手ぐらいで大勢が決していることが少なく無く、終盤だけでは どうしようもありません。
  2. 終盤の13手ぐらいしか読み切れないとなると、まだまだ弱くて強い人の相手は務まりません。
    そこで終盤まで対等に(出来れば有利に)プレイすることを考えなければなりません。

[Next Chapter ↓] 強い関数を作成する
[Previous Chapter ↑] 残り3手を読み切る

超初心者のプログラム入門(Win32API C++)