Problem mit MinimaxFunktion



  • Hallo Leute,
    bin ziemlicher Einsteiger was C++ betrifft, deshalb ist mein Stil auch gewöhnungsbedürftig, wollte aber ein Konsolenbasiertes Vier-Gewinnt mit Computergegner programmieren.
    Nun wollte ich mit Hilfe des Minimax-Algorithmus den Computer die Züge durchrechnen lassen. Aber irgendwo ist der Wurm drin.
    Ich will euch nicht mit zuviel (zugegebenermaßen viel funktionalem code, ja, 1. Sprache war Scheme) quälen, deshalb poste ich mal den Teil, wo ich denke, der ist für das ganze Verantwortlich.

    Die Quelle der Algorithmus-Implementierung ist:
    http://philemon.cycovery.com/site/part1.html
    (siehe NegaMax)

    Nun sieht meine Implementierung so aus:

    int val=0;
    int letzterzug=0;
    
    int explore(int sfeld[6][7], int tiefe)
    {
    	int alpha=-2147483647;
    	if(tiefe<=0)
    		return -bewertung(sfeld);
    	for(int zug=0; zug<=6; zug++)
    	{
    		if(zugpruefen(sfeld,zug)==false)
    			continue;
    		else
    		{
    			spielzug(sfeld,1,zug);
    			letzterzug=zug;
    		}
    		val = -explore(sfeld, tiefe-1);
    		spielzugzurueck(sfeld,letzterzug);
    		if(val>alpha)
    			alpha=val;
    	}
    	return alpha;
    };
    

    Alle Funktionen sind vorhanden, und geben keinen Fehler zurück.

    Zu meinem Problem:

    Wenn ich direkt nach der Spielfeldinitialisierung diese explore Funktion aufrufe , passiert nichts und die Konsole gibt nur aus: Press any key to continue.
    Alle Befehle, nach dem Funktionsaufruft werden ignoriert. Selbst ein einfaches cout wird nicht ausgeführt. Das Programm stoppt irgendwie. Fehler oder Warnungen gibt es keine (MS VSC++).

    Erkennt ihr in der Funktion selber einen Grund für das Verhalten. Ich selbst habe leider keine Idee.

    Danke fürs lesen und mitdenken 😉
    Gruß Sascha



  • kannst du mal die zugehörige main() dazugeben? Ansonsten kann es immer hilfreich sein, in einer scheinbar fehlerhaften Funktion einige Debug-Ausgaben (cerr oder clog) einzubauen, um die Arbeit zu verfolgen.



  • Oh, du willst die main() sehen, da geht das Chaos schon los 🙂
    Also hier:

    #include "stdafx.h"
    #include <iostream.h>
    
    int main()
    {
    	//initialisierung
    	int spielfeld[6][7] = {
    		{0,0,0,0,0,0,0},
    		{0,0,0,0,0,0,0},
    		{0,0,0,0,0,0,0},
    		{0,0,0,0,0,0,0},
    		{0,0,0,0,0,0,0},
    		{0,0,0,0,0,0,0}   };
    
            // Genau dies ist mein Test, "Hallo" wird nicht ausgegeben"
    	cout<<explore(spielfeld,2);
    	cout<<"Hallo";
    
    	int dransein=2;
    	while(true)
    	{
    		if(pruefe_ob_gewonnen(spielfeld,dransein))
    			break;
    		else
    		{
    			dransein=nichtdransein(dransein);
    			zugermitteln(spielfeld,dransein);
    			spielfeldzeigen(spielfeld);
    			if(spielende(spielfeld))
    			{
    				cout<<" Unentschieden!";
    				break;
    			}
    		}
    	}
    	cout<<"  Spieler "<<dransein<<" hat gewonnen!";
    	return 0;
    };
    

    Die Tips mit den Debug-Funktionen werd ich mal auspobieren wenn genug Zeit. Leider kenn ich mich damit noch gar nich aus (wie mit vielem).

    Gruß
    Sascha



  • die Fehler-Streams clog (gepuffert) und cerr (ungepuffert) dienen normalerweise zur Ausgabe von Fehlermeldungen und ähnlichem - die kannst du genauso einsetzen wie cout (die reguläre Ausgabe).

    Achja, sehe ich das richtig, daß val und letzterzug globale Variablen sind? Wenn ja, könnte das die Aufräumarbeiten in der Rekursion behindern.



  • danke danke danke!
    Also (konnte gerade erst deinen Beitrag lesen und) habe es mal ausprobiert ohne die "globalen Variablen". Und ja, genau daran lag es. Jetzt wird der ermittelte Wert zurückgegeben.
    Danke für den Tip, bzw. auch den mit cerr und clog (die ich unbedingt mal testen werde).

    Ich verstehe zwar nicht warum der Compiler Probleme hat, und warum das nicht erkannt wird, aber ich merks mir, dass es so ist.

    Ganz schnell noch:
    Wenn ich aus den globalen, lokale Variablen mache, gibts eine einfache Möglichkeit die "global" zu machen (nach der Auswertung), so das andere Funktionen die aufrufen können?
    Normalerweise kann ich ja einfach 2 globale anlegen und dann beim Ende der Funktion die überschreiben, dürfte keine Probleme machen. Globale Variablen in einer Funktion erzeugen ist nicht möglich oder?

    Danke
    Sascha



  • Du kannst schon globale Variablen anlegen - nur solltest du die nicht während der Rekursion verändern (lokale Variablen hat jede Instanz der Funktion eigene, globale Variablen gibt es nur einmal). Also wenn du es wirklich benötigst, kannst du nach allen Berechnungen die globalen Variablen setzen (oder du verwendest Referenz-Parameter zur Rückgabe von Endewerten).



  • Danke für alle Tips. Vorerst genug Wissen getankt.
    Gruß Sascha


Anmelden zum Antworten