TicTacToe mit MFC - Problem bei bestimmung eines gewinners.

Stay Tuned

Grünschnabel
Hallo,


Wir haben vor ein paar Wochen mit MFC angefangen und sind grade dabei das Spiel "TicTacToe" zu programmieren.

Wir sind nun so weit das 9 Felder und ein kleines Feld, welches bestimmt welcher spieler dran ist, angezeigt werden.

Nun haben wie eine Aufgabe vom Lehrer bekommen bis Montag das Programm soweit zu erweitern, dass das Programm erkennt wann ein Spieler gewonnen hat.

Wenn Sie mit der vorangegangenen Aufgabe und der Anzeige der aktuellen Spielfarbe (kleines Rechteck neben dem Spielfeld) fertig sind, erweitern Sie die Logik in OnLButtonDown so, dass festgestellt werden kann, wenn ein Spieler gewonnen hat.

Der Gewinnzustand soll in einer Variablen CTTTView::m_win festgehalten werden:

Gewinn...................m_win

Noch keiner................0
Spieler rot...................1
Spieler blau................2

Wo deklarieren Sie m_win? Wo initialisieren Sie m_win?


Mein OnLButtonDown sieht at the moment noch so aus.

Code:
void CTTTView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
	
	for(int i=0; i<3; i++){
		for(int j=0; j<3; j++){

			if(m_feld[i][j].PtInRect(point)&&m_feld[i][j].m_farbe == RGB ( 100,100,100)){

				if(m_player == 1 ){
						m_feld[i][j].m_farbe = RGB ( 0,0,255);
						m_mini.m_farbe = RGB ( 255,0,0);
						m_player = 2;
				}
			
				else{
						m_feld[i][j].m_farbe = RGB ( 255,0,0);
						m_mini.m_farbe = RGB ( 0,0,255 );
						m_player = 1;
				}
			}
			
			this->Invalidate();
		}
	}
			
	CView::OnLButtonDown(nFlags, point);
}

m_feld[ i ][ j ] sind die 9 Felder und m_mini ist das kleine Feld.

Mein Gedankengang war jetzt m_feld[ i ][ j ].m_farbe so zu vergleichen das ich sehen kann ob z.B. m_feld[0][0], m_feld[0][1] und m_feld[0][2] die selbe Farbe haben.

Jedoch finde ich keine möglichkeit dies so zu realisieren und die Aufgabenstellung des Lehrers ist mir persönlich auch nicht grade schlüssig.

Bin kein Programmier-Ass und mühe mich mit dem ganzen noch etwas ab und bräuchte deswegen etwas unterstützung von Leuten die sich damit besser auskennen. ( Leider ist unser Lehrer da keine besondere Hilfe, er lehrt uns nach dem Motto "erfinde das Rad selbst neu"... )


Hoffe jemand kann mir sagen wie ich überprüfen kann, wann welcher Spieler gewonnen hat und eventuell auch, wie ich dies ausgeben könnte.

Wenn ihr dazu noch irgendwas von mir wissen müsst, sagt es mir und ich werde den Thread einfach editieren.


Mit freundlichen Grüßen

Stay Tuned
 

langer1801

Erfahrenes Mitglied
Hi,

es gibt 8 Möglichkeiten, eine Gewinn-Reihe zu haben, 3 mal waagerecht, 3 mal senkrecht und die beiden Diagonalen. Also muß man nach jedem Zug prüfen, ob eine der Möglichkeiten erreicht ist. Dazu würde ich nach dem if-else-Zweig die Abfrage einfügen
Code:
if (m_feld[0][0].m_farbe == RGB ( 0,0,255)&&m_feld[0][1].m_farbe= = RGB ( 0,0,255)&&m_feld[0][2].m_farbe= = RGB ( 0,0,255))
    m_win=2;
else if(m_feld[1][0].m_farbe == RGB ( 0,0,255)&&m_feld[1][1].m_farbe == RGB (0,0,255)&&m_feld[1][2].m_farbe= = RGB ( 0,0,255))
   m_win=2;

usw. für jede Möglichkeit und beide Spieler. Allerdings gibt es noch die Möglichkeit, wenn beide Spieler optimal spielen, dass keiner gewinnt. Man müßte also auch noch prüfen, ob alle Felder belegt sind und ein Unentschieden vorliegt.
Als Anmerkung noch:
Natürlich kann man den obigen Code noch optimieren, wenn man die senkrechte oder waagerechte Prüfung in einer Schleife durchführt.

Mfg

langer
 
Zuletzt bearbeitet:

Stay Tuned

Grünschnabel
Aha okay, verstehe.

Lag ich im Prinzip gar nich mal so weit daneben.


Die CTTTView::m_win dient dann zur erzeugung eines neuen Fensters, in dem dann Methoden wie z.B.:

Code:
if( win == 2 ){
... //ausgabe Spieler 2 hat gewonnen
}
enthalten sind.

Oder hab ich da etwas falsch verstanden? ( denn eig. werden Fenster doch in der OnDraw erzeugt, oder nicht )


Und noch etwas:

mit this->invalidate(); flackert das Bild immer wenn es neu "geladen" wird. Wie kann ich dies umgehen?

MfG
 
Zuletzt bearbeitet:

langer1801

Erfahrenes Mitglied
Hi,
was das Flackern betrifft: In der OnDraw-Methode wird der Hintergrund neu gezeichnet. Das ist in der Regel der Grund für das Flackern. Umgehen kann man das, indem man OnEraseBkg() überschreibt und dann False zurückgibt. Das setzt aber voraus, dass man den Hintergrund selbst zeichnet. Eine andere Möglichkeit ist, statt Invalidate() die Funktion InvalidateRect() zu verwenden und als neu zu zeichnenden Bereich das Spielfeld-Rect anzugeben.
Und mit deiner Idee lagst du wirklich schon richtig. Wichtig ist eben, alle Varianten zu prüfen.
Und zu den eigenen Fenstern: In OnDraw() werden keine Fenster erzeugt, sondern es wird in das aktuelle Fenster gezeichnet. Wenn du dann eine andere Ausgabe willst, solltest du einen Dialog oder noch einfacher eine MsgBox verwenden.

Mfg

langer