KI für 4 gewinnt
-
Hallo alle,
ich versuche jetzt seit einiger Zeit meine KI zum laufen zu kriegen, aber es funktioniert einfach nicht.
Evtl könnte jemand drüberschauen und mir sagen wo ich den Fehler mache...
Hier sind meine Klassen:
TreeElement-Klasse: Soll einen Knoten im (Min-Max)Baum represäntieren.
Die chars 'b' (Computer) und 'r' (Spieler) zeigen wessen Ebene gerade dran ist.
Globals::play_slot_rec() wirft den entsprechenden Stein in den Slot, und Globals::remove_slot entfernt ihn wieder (sollte).Globals::isSlotFull() überprüft nur ob nicht eh schon 7 Steine in dem Slot sind.
Als heuristik verwende ich folgende Funktion:
500+10*result.p_anz_2+40*result.p_anz_3+50000*result.p_anz_4 - 10*result_opponent.p_anz_2-5000000*result_opponent.p_anz_3-5000000*result_opponent.p_anz_4;Wobei in result (bzw result_opponent) die jeweiligen 2er,3er und 4er Kombinationen stehen.
#include "Tree_Element.h" #include <limits> TreeElement::TreeElement() { for(int i=0;i<7;i++) { childs[i]=NULL; } } TreeElement::TreeElement(short move, int i_currentDepth, int maxDepth) { for(int i=0;i<7;i++) { childs[i]=NULL; } this->maxDepth = maxDepth; currentDepth = i_currentDepth+1; my_move = move; } TreeElement::~TreeElement() { for(int i=0;i<7;i++) { if(childs[i]!=NULL) { delete childs[i]; } } } // builds recursion and returns the best value int TreeElement::getCalc() { // save results int res[7]; char c; if(currentDepth%2==1) c='b'; else c='r'; // make the play int line = Globals::play_slot_rec(my_move, c); // Check for remaining moves int possible_moves = 0; for(int i=0;i<7;i++) { if(!Globals::isSlotFull(i)) { ++possible_moves; break; // Break since at least 1 possible move left } } if(currentDepth == maxDepth || possible_moves == 0) // recursion end reached, return { Globals::Anz_all result; result.p_anz_2=0; result.p_anz_3=0; result.p_anz_4=0; Globals::Anz_all result_opponent; result_opponent.p_anz_2=0; result_opponent.p_anz_3=0; result_opponent.p_anz_4=0; result = Globals::getAllCounts('b'); result_opponent = Globals::getAllCounts('r'); Globals::remove_slot(my_move,line); // Heuristik int ret_best = 500+10*result.p_anz_2+40*result.p_anz_3+5000*result.p_anz_4 - 10*result_opponent.p_anz_2-40*result_opponent.p_anz_3-5000*result_opponent.p_anz_4; return ret_best; } // still not deep enough else { // build nodes + call recursion for(int i=0;i<7;i++) { // only make childs for possible plays if(!Globals::isSlotFull(i)) { childs[i] = new TreeElement(i, currentDepth, maxDepth); res[i] = childs[i]->getCalc(); } } } // at the end, undo the play Globals::remove_slot(my_move,line); // Get the best result int best_res = 0; bool first=true; for(int i=0;i<7;i++) { if(childs[i]!=NULL) { if(first) { best_res = res[i]; first=false; } // player returns min else if(c=='r') { if(res[i]>best_res) best_res = res[i]; } // CPU returns max else { if(res[i]<best_res) best_res = res[i]; } } } return best_res; } int TreeElement::startFromRoot() { // this will save the index of the best play int best_res = -1; int res[7]; // build nodes + call recursion for(int i=0;i<7;i++) { // only make childs for possible plays if(!Globals::isSlotFull(i)) { childs[i] = new TreeElement(i, currentDepth, maxDepth); res[i] = childs[i]->getCalc(); } } // try to figure the result int max=INT_MIN; for(int i=0;i<7;i++) { if(childs[i]!=NULL) { if(res[i]>=max) { max=res[i]; best_res = i; } } } return best_res; }
Aufruf passiert dann im Main mit:
TreeElement *t = new TreeElement(1, 0, 7); int ki_play = t->startFromRoot(); Globals::play_slot(ki_play, 'b');
Ich hoffe jemand von euch kann mir hier helfen, ich stehe atm ziemlich auf der Leitung...
Edit:
Ich hab jetzt ein paar Fehler gefunden (neuer Code is oben eingefügt), jedoch beginne ich daran zu zweifeln dass meine Heuristik gut ist ...Kennt jemand eine Seite (oder hat schon selbst so eine KI gemacht) wo eine gute heuristik beschrieben wird?