6

私は、反復アルファ-ベータ プルーニングを使用して三目並べをプレイしようとしています。移動には 1 秒の制限がありますが、何らかの理由でうまく機能しません。

通常の alpha-beta コードを変更して、alpha または beta を返す代わりに状態 (次の動きのあるボード) を返すようにしました。

子を作成するたびに、深さを更新します。

しかし、何らかの理由で私は負け続けており、私のアルファベータは最善の動きを見ていないことがわかりました.

これが私のコードです:

外側のループ:

while (watch.get_ElapsedMilliseconds() < 900 && d <= board.length * board[0].length - 1)
        {
            s = maxiMin(beginSt, d, watch);
            if (s.getNextMove().getIsWin() == true)
            {
                break;
            }
            d++;
        }
        return new location(s.getNextMove().getRow(), s.getNextMove().getCol());

アルファベータ:

public State maxiMin(State s, int depth, Stopwatch timer)
    {
        if (s.getDepth() == 7)
        {
            Console.WriteLine();
        }
        if (timer.get_ElapsedMilliseconds() > 850 || s.getDepth() == depth || goalTest(s.getBoard()) != 0)
        {
            s.evaluationFunc(line_length, PlayerShape);
            s.setAlpha(s.getEvaluation());
            s.setBeta(s.getEvaluation());
            return s;
        }
        LinkedList<State> children = createChildren(s, true);
        // No winner, the board is full
        if (children.get_Count() == 0)
        {
            s.evaluationFunc(line_length, PlayerShape);
            s.setAlpha(s.getEvaluation());
            s.setBeta(s.getEvaluation());
            return s;
        }
        while (children.get_Count() > 0)
        {
            State firstChild = children.get_First().get_Value();
            children.RemoveFirst();
            State tmp = miniMax(firstChild, depth, timer);
            int value = tmp.getBeta();
            if (value > s.getAlpha())
            {
                s.setAlpha(value);
                s.setNextMove(tmp);
            }
            if (s.getAlpha() >= s.getBeta())
            {
                return s;
            }
        }
        return s;
    }

    public State miniMax(State s, int depth, Stopwatch timer)
    {
        if (s.getDepth() == 7)
        {
            Console.WriteLine();
        }
        if (timer.get_ElapsedMilliseconds() > 850 || s.getDepth() == depth || goalTest(s.getBoard()) != 0)
        {
            s.evaluationFunc(line_length, PlayerShape);
            s.setAlpha(s.getEvaluation());
            s.setBeta(s.getEvaluation());
            return s;
        }
        LinkedList<State> children = createChildren(s, false);
        // No winner, the board is full
        if (children.get_Count() == 0)
        {
            s.evaluationFunc(line_length, PlayerShape);
            s.setAlpha(s.getEvaluation());
            s.setBeta(s.getEvaluation());
            return s;
        }
        while (children.get_Count() > 0)
        {
            State firstChild = children.get_First().get_Value();
            children.RemoveFirst();
            State tmp = maxiMin(firstChild, depth, timer);
            int value = tmp.getAlpha();
            if (value < s.getBeta())
            {
                s.setBeta(value);
                s.setNextMove(tmp);
            }
            if (s.getAlpha() >= s.getBeta())
            {
                return s;
            }
        }
        return s;
    }

何かが間違っているかどうか誰かが私に教えてくれれば、大いに感謝します。評価を返す通常のアルファベータの代わりに「s」を返していることに関係があるのではないかと思いますが、エラーを見つけることができませんでした。

前もって感謝します、

レナ

4

1 に答える 1

5

まず、三目並べは非常に単純なゲームであり、より単純なコードで解決できると思います。これは主に、常に同点のオプションがあり、状態の総数が 3^9 未満であることを知っているためです (対称および対称を含む)。多くの不可能な状態)。

あなたのコードに関しては、あなたの問題の1つは、再帰呼び出しの深さを増やさないように見えることだと思います。

また、コードに悪いスタイルの問題がたくさんあります。基本的に同じですが、miniMax と MaxiMin を 2 つの関数に分けました。for-each または反復子 (または int 反復子) を使用するのではなく、コレクションから要素を削除することによって、コレクションを反復処理します。

于 2010-02-16T19:16:26.173 に答える