ページ 11

オセロMinMax法の実装

Posted: 2008年9月10日(水) 21:32
by yujin
オセロプログラムを作っているのですが、MinMax(再帰関数)法の実装がうまくいきません。
管理人様のクイックソートアルゴリズムで再帰関数を勉強させていただきました。
とても分かりやすかったです。この場を借りてありがとうございますm(_ _)m
因みにオセロプログラムはここのサイトを参考に作っています。
http://javagame.skr.jp/index.php?AI%A4% ... 5%B9%CB%A1
コンピューターが打つと一手ではなく(探索レベル2の時で)三手ぐらい返してきます。
ちゃんと一手だけ返してほしい(ToT)
数日間プログラムとにらめっこしていますが、バグの原因がつかめず。
打った後に手を戻す辺りが怪しいのですが。
添付ファイルにソースプロジェクトがあるので、恐縮ではありますが解決策のアドバイスを
お願い致しますm(_ _)m


環境は
Windows XP HomeEdition sp2
VC++ 2005EE DXライブラリ使用 です。

Re:オセロMinMax法の実装

Posted: 2008年9月10日(水) 23:23
by Justy
 コードを精査したわけではないので、根本の原因と違うかもしれませんが。
miniMax()関数でおかしなところがあります。

 オリジナルのコードは [color=#d0d0ff" face="sans-serif]Undo undo = new Undo(x, y);[/color]の部分で関数内部に
undo変数としてデータを持っているので、再帰するたびに異なる undo変数が生成され
値を保持しますが、yujinさんのコードでは Undo()関数を呼び出した中で
グローバル変数を使って値を保持しているため、1つしか実体がありません。

 ここを直さないと、正しく Undo処理が行われないのではないでしょうか。

Re:オセロMinMax法の実装

Posted: 2008年9月11日(木) 13:51
by yujin
返信が遅くなりましたが、Justyさんアドバイスをありがとうございますm(_ _)m
やはり手を戻す機能が怪しいと言うか、おかしいですか。
オリジナルのプログラムでは手を戻す時の機能をクラスを使って表現しているので、
同じように実装してみようと思います。
ただクラスは一度も使ったことが無いので、うまくいくかどうか^^;

オリジナルのクラスはこの様になっているので、
public class Undo {
	// 石を打つ場所
	public int x;
	public int y;
	// ひっくり返った石の数
	public int count;
	// ひっくり返った石の場所
	public Point[/url] pos;

	public Undo(int x, int y) {
		this.x = x;
		this.y = y;
		count = 0;
		pos = new Point[64];
	}
}
C++風に書くなら、
class Undo {
	// 石を打つ場所
	int x;
	int y;
	// ひっくり返った石の数
	int count;
	// ひっくり返った石の場所
	int pos[/url];

	Undo(int x, int y) {
		this.x = x;
		this.y = y;
		count = 0;
		pos[64];
	}
};
こんな感じでしょうか?

Re:オセロMinMax法の実装

Posted: 2008年9月11日(木) 20:06
by Justy

>C++風に書くなら
>こんな感じでしょうか?

 いえ、それだと配列の宣言で要素数がないのでコンパイルエラーになりますし、
そもそも全部 private扱いになるのでコンストラクタが実行できずやはりエラーになります。


 Undoクラスは単純にこんな感じでいいかと思います。
[color=#d0d0ff" face="sans-serif]    struct Point
    {
        Point()                                 {}
        Point(int x_, int  y_)   : x(x_), y(y_) {}
        int x, y;
    };
    
    struct Undo
    {
        Undo(int x_, int y_)
        :   x(x_), y(y_), count()   {}
        
        int     x, y;
        int     count;
        Point   pos[64];
    };[/color]

 とりあえず一通り見てみました。
 
 Undo関連の処理は前に指摘した通りだったのですが、もう1つ MIN_VALUE値もなにやら
悪さをしていました。

 とりあえず正常に動いているように見えるところまでは手を入れてみたので、
変更点を見比べて自分なりに書き直してみて下さい。

Re:オセロMinMax法の実装

Posted: 2008年9月11日(木) 23:16
by yujin
>とりあえず一通り見てみました。

貴重な時間を裂いてまでありがとうございますm(_ _)m

しっかりと一手だけ返してくれる状態まで変更を加えていただいて大変恐縮です。
struct Point
    {
        Point()                                 {}
        Point(int x_, int  y_)   : x(x_), y(y_) {}
        int x, y;
    };
    
    struct Undo
    {
        Undo(int x_, int y_)
        :   x(x_), y(y_), count()   {}
        
        int     x, y;
        int     count;
        Point   pos[64];
    };
これは構造体の中の構造体ですね。(苦手意識^^;)
Reverse関数が
void Reverse(int x, int y, int vecX, int vecY) から
void Reverse(Undo &undo, int vecX, int vecY)  になった瞬間私の頭の中はパニックです(笑)
 実は、関数の引数に&や*が付くのが苦手で、ここら辺の理解がしっかりと
していないから今回の様なバグを発生させてしまった様な気がします。
 Justyさんが修正して下さったソースを参考にしてここら辺の理解も
しっかりと固めてようと思います。

Re:オセロMinMax法の実装

Posted: 2008年9月12日(金) 21:37
by yujin
解決マークを忘れていました。

Justyさん色々とアドバイスをしていただきありがとうございますm(_ _)m
 まだまだ未熟者なので能力の限界が来た時にまたここの質問サイトを利用させて頂く
のでその時は宜しくお願いいたします。
 早く色々な人にアドバイスが出来るよう精進していきます。