Gra w kółko i krzyżyk - minimaks nie działa poprawnie

0

Chciałem sobie napisać grę w kółko i krzyżyk. Ściągnęłem sobie skądś pracę magisterską o szachach i implementuje algorytmy minimaksowe na tej grze. Jednak nie do końca mnie to wychodzi:

[code]
#include "person.h"
#include "board.h"
#include "game.h"

int humanperson::getMove (board b)
{
cout << b;
cout << "Ruch człowieka: " << endl;
int nr = 0;
cout << "Podaj nr ruchu: ";
cin >> nr;
if (nr<1 || nr>9) throw new except(FILE,FUNCTION, LINE, "Nieprawidłowy zakres ruchu");
return nr;
}

int machineperson::getMove (board b)
{

int bestmove = 0;
int bestvalue = -1000000;
thinking_time = time(0);
max_thinking_time = 10000;
try
{
for (int i = 1; i<=9; i++)
    {
        if (b[i] == NO_FIGURE)
            {
                // analizuje tylko puste pola
                int price = getValueMove(i, 1, b);

                if (price>bestvalue)
                {
                    bestmove = i;
                    bestvalue = price;
                }
            }
    }

if (bestmove < 1 || bestmove > 9)
    {

        throw new except(__FILE__,__FUNCTION__, __LINE__, "Nie znalazlem kandydata na ruch");
    }
}
catch (except *e)
{
    cout << *e << endl;
    delete e;
}
catch (...)
{
   except e(__FILE__, __FUNCTION__, __LINE__, "Blad systemowy");
   cout << e << endl;
}

return bestmove;

}

std::istream& operator>> (std::istream& c, person& p)
{
std::cout << "Podaj nazwe gracza: ";
std::cin >> p.name;
return c;
}

figurestype humanperson::getType () { return CIRCLE; }
figurestype machineperson::getType () { return HASH; }

int machineperson::getValueMove (int cont, int nr, board bo)
{
const int WON = 100000;
const int LOSE = -WON;
const int DRAW = 0;
int bestmove = 0;
int bestprice = 0;
board t(bo);
t[cont] = getType();
switch (t.check())
{
case GAME_WON:
if (nr%2 == 1) return WON; else return LOSE;
break;

    case GAME_END:
        return DRAW;
        break;

    case GAME_CONT:

        for (int i = 1; i<=9; i++)
        if (t[i] == NO_FIGURE)
        {
            int price = getValueMove (i, nr+1, t);
            if (bestmove == 0)
            {
                bestmove = i;
                bestprice = price;
            } else
            {
                if (nr%2 == 1) // computer
                {
                    if (price>bestprice)
                    {
                        bestprice = price;
                        bestmove = i;
                    }
                }
                else
                { // human

                    if (price<bestprice)
                    {
                        bestprice = price;
                        bestmove = i;
                    }

                }
            }
        }


        break;

    default: throw new except(__FILE__,__FUNCTION__, __LINE__, "Nieoczekiwany stan");

};

return bestprice;

}

[/code]
Objawia się niepoprawność przez to, że czasami nie wykrywa przegranej, nie widzi możliwości wygranej itd.
Co robie nie tak w funkcj getValueMove?

0

Poprawiłem na trochę lepszy (mniej błędów popełnia). Jednak nadal nie gra tak jak trzeba:

[code]
#include "person.h"
#include "board.h"
#include "game.h"

int humanperson::getMove (board b)
{
cout << b;
cout << "Ruch człowieka: " << endl;
int nr = 0;
cout << "Podaj nr ruchu: ";
cin >> nr;
if (nr<1 || nr>9) throw new except(FILE,FUNCTION, LINE, "Nieprawidłowy zakres ruchu");
return nr;
}

int machineperson::getMove (board b)
{

int bestmove = 0;
int bestvalue = -1000000;
thinking_time = time(0);
max_thinking_time = 10000;
try
{
for (int i = 1; i<=9; i++)
    {
        if (time(0)-thinking_time>max_thinking_time) return bestmove;
        if (b[i] == NO_FIGURE)
            {
                // analizuje tylko puste pola
                int price = getValueMove(i, 1, b);

                if (price>bestvalue)
                {
                    bestmove = i;
                    bestvalue = price;
                }
            }
    }

if (bestmove < 1 || bestmove > 9)
    {

        throw new except(__FILE__,__FUNCTION__, __LINE__, "Nie znalazlem kandydata na ruch");
    }
}
catch (except *e)
{
    cout << *e << endl;
    delete e;
}
catch (...)
{
   except e(__FILE__, __FUNCTION__, __LINE__, "Blad systemowy");
   cout << e << endl;
}

return bestmove;

}

std::istream& operator>> (std::istream& c, person& p)
{
std::cout << "Podaj nazwe gracza: ";
std::cin >> p.name;
return c;
}

figurestype humanperson::getType () { return CIRCLE; }
figurestype machineperson::getType () { return HASH; }

int machineperson::getValueMove (int cont, int nr, board bo)
{
const int WON = 100000;
const int LOSE = -WON; // im szybciej wygramy tym lepsza wygrana
const int DRAW = -100; // im pozniej przegramy tym lepsza przegrana
int bestmove = 0; // remis nie jest taki neutralny
int bestprice = 0;
if (time(0)-thinking_time>max_thinking_time) return 0;
board t(bo);
if (nr%2 == 1) t[cont] = getType(); else t[cont] = CIRCLE;
switch (t.check())
{
case GAME_WON:
if (nr%2 == 1) return WON+(9-cont)3; else return LOSE+3cont;
break;

    case GAME_END:
        return DRAW;
        break;

    case GAME_CONT:

        for (int i = 1; i<=9; i++)
        if (t[i] == NO_FIGURE)
        {
            int price = getValueMove (i, nr+1, t);
            if (bestmove == 0)
            {
                bestmove = i;
                bestprice = price;
            } else
            {
                if (nr%2 == 1) // computer
                {
                    if (price>bestprice)
                    {
                        bestprice = price;
                        bestmove = i;
                    }
                }
                else
                { // human

                    if (price<bestprice)
                    {
                        bestprice = price;
                        bestmove = i;
                    }

                }
            }
        }


        break;

    default: throw new except(__FILE__,__FUNCTION__, __LINE__, "Nieoczekiwany stan");

};

return bestprice;

}

[/code]

--EDIT--

Jak zauważyłem bawiąc się debuggerem. To gdy komputer zaczyna to przewiduje, że na każdym kroku będzie wygrywać. A jeżeli to gracz zaczyna to uważa, że cały czas przegrywa (i odrobinę lepiej gra)

1 użytkowników online, w tym zalogowanych: 0, gości: 1