TicTacToe KI

Gnoccy

Mitglied
Nabend,

Habe da gerade ein kleines Problem, und zwar arbeite ich zur Zeit an einer KI für TicTacToe. Mein bisheriger Code dazu sieht wie folgt aus:

Java:
public class KI 
{
	int gibZug(Feld f, boolean spieler1AmZug)
	{
		Feld kifeld = new Feld();
		
		
		String spieler;
		if (spieler1AmZug == true)
		{
			spieler = "X";
		}
		else
		{
			spieler = "O";
		}
		
		
		int zug = -1;
		int bZugWert = 0;
		int aZugWert = 0;
		
		//Feld übertragen
		for(int i = 0; i < 2; i++)
		{
			for(int j = 0;j < 2; j++)
			{
				kifeld.setField(i, j, f.getField(i, j));
			}
		}
		
		for (int z1 = 0;z1 < 8; z1++)
		{
			
			int x1 = z1 % 3;
			int y1 = (z1 - x1) / 3;
			
			if(kifeld.isValidMove(z1))
			{
				System.out.println(z1);
				kifeld.setField(x1, y1, spieler);
				if(kifeld.gewonnen())
				{
					aZugWert =+ 1;
					if(aZugWert >= bZugWert)
					{
						bZugWert = aZugWert;
						zug = z1;
					}
					kifeld.setField(x1, y1, "__");
				}
				else
				{
					for(int z2 = 0; z2 < 8; z2++)
					{
						int x2 = z2 % 3;
						int y2 = (z2 - x2) / 3;
						
						if(kifeld.isValidMove(z2))
						{
							kifeld.setField(x2, y2, spieler);
							if(kifeld.gewonnen())
							{
								aZugWert =- 1;
								if(aZugWert >= bZugWert)
								{
									bZugWert = aZugWert;
									zug = z1;
									kifeld.setField(x2, y2, "__");
								}
								
							}
							else
							{
								for (int z3 = 0;z3 < 8; z3++)
								{
									
									int x3 = z3 % 3;
									int y3 = (z3 - x3) / 3;
									
									if(kifeld.isValidMove(z3))
									{
										kifeld.setField(x3, y3, spieler);
										if(kifeld.gewonnen())
										{
											aZugWert =+ 1;
											if(aZugWert >= bZugWert)
											{
												bZugWert = aZugWert;
												zug = z1;
												kifeld.setField(x3, y3, "__");
											}
										}
										else
										{
											for(int z4 = 0; z4 < 8; z4++)
											{
												int x4 = z4 % 3;
												int y4 = (z4 - x4) / 3;
												
												if(kifeld.isValidMove(z4))
												{
													kifeld.setField(x4, y4, spieler);
													if(kifeld.gewonnen())
													{
														aZugWert =- 1;
														if(aZugWert >= bZugWert)
														{
															bZugWert = aZugWert;
															zug = z1;
															kifeld.setField(x4, y4, "__");
														}
														
													}
													else
													{
														for (int z5 = 0;z5 < 8; z5++)
														{
															
															int x5 = z5 % 3;
															int y5 = (z5 - x5) / 3;
															
															if(kifeld.isValidMove(z5))
															{
																kifeld.setField(x5, y5, spieler);
																if(kifeld.gewonnen())
																{
																	aZugWert =+ 1;
																	if(aZugWert >= bZugWert)
																	{
																		bZugWert = aZugWert;
																		zug = z1;
																		kifeld.setField(x5, y5, "__");
																	}
																}
																else
																{
																	for(int z6 = 0; z6 < 8; z6++)
																	{
																		int x6 = z6 % 3;
																		int y6 = (z6 - x6) / 3;
																		
																		if(kifeld.isValidMove(z6))
																		{
																			kifeld.setField(x6, y6, spieler);
																			if(kifeld.gewonnen())
																			{
																				aZugWert =- 1;
																				if(aZugWert >= bZugWert)
																				{
																					bZugWert = aZugWert;
																					zug = z1;
																					kifeld.setField(x6, y6, "__");
																				}
																				
																			}
																			else
																			{
																				for (int z7 = 0;z7 < 8; z7++)
																				{
																					
																					int x7 = z7 % 3;
																					int y7 = (z7 - x7) / 3;
																					
																					if(kifeld.isValidMove(z7))
																					{
																						kifeld.setField(x7, y7, spieler);
																						if(kifeld.gewonnen())
																						{
																							aZugWert =+ 1;
																							if(aZugWert >= bZugWert)
																							{
																								bZugWert = aZugWert;
																								zug = z1;
																								kifeld.setField(x7, y7, "__");
																							}
																						}
																						else
																						{
																							for(int z8 = 0; z8 < 8; z8++)
																							{
																								int x8 = z8 % 3;
																								int y8 = (z8 - x8) / 3;
																								
																								if(kifeld.isValidMove(z8))
																								{
																									kifeld.setField(x8, y8, spieler);
																									if(kifeld.gewonnen())
																									{
																										aZugWert =- 1;
																										if(aZugWert >= bZugWert)
																										{
																											bZugWert = aZugWert;
																											zug = z1;
																											kifeld.setField(x8, y8, "__");
																										}
																										
																									}
																									else
																									{
																										for (int z9 = 0;z9 < 8; z9++)
																										{
																											System.out.println(aZugWert);
																											int x9 = z9 % 3;
																											int y9 = (z9 - x9) / 3;
																											
																											if(kifeld.isValidMove(z9))
																											{
																												kifeld.setField(x9, y9, spieler);
																												if(kifeld.gewonnen())
																												{
																													System.out.println(aZugWert);
																													aZugWert =+ 1;
																													if(aZugWert >= bZugWert)
																													{
																														bZugWert = aZugWert;
																														zug = z1;
																														kifeld.setField(x9, y9, "__");
																													}
																												}
																											}
																										}
																									}
																								}
																							}
																						}
																					}
																				}
																			}
																		}
																	}
																}
															}
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		
		
		
		
		
		
		return zug;
	}
	
	

}

Ich weiss, das ginge sicherlich noch schöner und eleganter, aber da habe ich gerade keine Lust zu 😉

Die Idee dahinter is, dass ein Zug simuliert wird und danach geprüft wird, ob der Spieler gewonnen oder verloren hat. Hat er gewonnen, wird eine Variable um eins erhöht, hat er verloren um eins verringert. Trifft keines von beiden zu wird der nächste Zug simuliert.
Gleichzeitig wird der Zug mit der bisher höchsten "Punktzahl" gespeichert und am ende zurückgegeben. Mein Problem ist nun, das immer -1 zurückgegeben wird, was zu fehlern im weiterem verlauf des Programms führt.
Kann mir da wer helfen? Oder habe ich da eventuell einen völlig falschen Ansatz und mein ganzer Code ist quatsch?
Würde mich auf jeden Fall über hilfe freuen.

MFG:Gnoccy
 
Ich weiss, das ginge sicherlich noch schöner und eleganter, aber da habe ich gerade keine Lust zu
Und ich für meinen Teil habe keine Lust mich durch den "Code" durcharbeiten :bahnhof:
Da irgendwas nachzuvollziehen ist beinah unmöglich. Schreib den vernünftig um, dann wirst du auch mit Sicherheit selber den Fehler finden.
 
Java:
                                                                                                                    }
                                                                                                                }
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Allein diese Einrückung, krass :rtfm:
Da kann ich XHelp nur zustimmen, schreib den Code mal so um dass den auch außenstehende gut lesen können.
 
Java:
                                                                                                                    }
                                                                                                                }
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Allein diese Einrückung, krass :rtfm:
Da kann ich XHelp nur zustimmen, schreib den Code mal so um dass den auch außenstehende gut lesen können.

:lol: 28 Zeilen

Ich weiss, das ginge sicherlich noch schöner und eleganter, aber da habe ich gerade keine Lust zu
Jo, dazu hätt ich auch keine lust 😀
 
hhhmmm, ist das nicht so, dass der Zug am besten wäre, der mit den wenigsten Zügen zu 4 gleichen führen würde? Wenn bis dahin mehrere Zugmöglichkeiten möglich sind, um 4 gleiche zu bekommen, wäre der Zug dann entsprechend besser? Muss gestehen, dass ich auch keinen Plan habe, wie die Strategie sein sollte... Vielleicht erklärt XHelp oder EikeB die Strategie/Taktik!? Bin mir fast sicher, dass das einer weiß 😉
 
ich bin eben mal über den Code gefolgen und mir fielen sofort Zeilen dieser Art ins Auge, massenhaft:
aZugWert =+ 1;
aZugWert =- 1;
und da fragte ich mich, was dabei wohl herauskommen wird .....???:L
und was da eigentlich beabsichtigt war....:shock: .... vielleicht
aZugWert ++; (aZugWert += 1; )
aZugWert --; (aZugWert -= 1; )
😛feif:😛feif:
 
Zuletzt bearbeitet von einem Moderator:
Naja, ist doch im Grunde egal, was sich einer aussucht, um sich auszutoben.
Und dann gibt es ja in der Softwareentwicklung auch mehrere Stufen, nichtwahr.
Zuerst kommt es mal darauf an, dass das Ding läuft.
Make it nice kommt zuletzt :lol:
 
Ich weiss nicht, ob das eben evtl etwas falsch rübergekommen ist, aber das Problem ist, dass ich einfach keine Idee habe, wie man das ganze umschreiben könnte. Da immer wieder relativ ähnliche Elemente wiederholt werden, gehe ich mal davon aus, dass man das ganze auch mit einer (for?) Schleife realisieren kann, nur wie gesagt, ich komme nicht drauf wie.
Grundsätzlich sollen alle Schleifen das selbe tuen:
Sie Simulieren mit jedem durchlauf einen der (theoretisch) 9 möglichen Züge in TicTacToe. Danach wir überprüft, ob der Spieler mit einem dieser Züge gewonnen hat, und falls ja, wird die variable aZugWert um eins erhöht.
Hat er nicht gewonnen, wird der nächste Zug simuliert. Da es sich ja hierbei um den Zug des Gegners handelt, wird aZugWert, wenn der Spieler mit diesem Zug gewinnt um eins verringert.
Das geht so weiter, bis alle möglichen Züge durchgegangen sind, also 9 mal, dabei wechselt der Spieler der zieht immer hin und her, also wird zu aZugWert entweder addiert, oder subtrahieren.

Wie gesagt, ich denke mal, dass man anstatt der 9 Schleifen auch eine der Schleifen 9 mal wiederholen könnte, allerdings weiss ich gerade nicht, wie ich das dann mit den Punkten und dem wechsel zwischen +/- hinbekommen soll. Aber darum geht es ja auch gar nicht.

Was ich damit sagen will ist, dass es nicht nötig ist, sich alle neun Schleifen durchzulesen, ich gebe zu, dass das verdammt unübersichtlich wird. Die ersten zwei sollten reichen, um das Prinzip zu verstehen, und außerdem sollte da auch schon der Fehler erkennbar sein und sich in den restlichen Schleifen wiederholen.

Sollte trotzdem jemand einen Tipp für mich haben, wie ich alles in einer Schleife zusammenfassen kann, wäre ich natürlich auch dafür sehr dankbar.
 
Hallo ?
Ich hatte doch schon geschrieben:
aZugWert =+ 1;
ist eine einfache Zuweisung eines Wertes und KEIN Inkrement.
Anders gesagt, wenn du hier den Wert von aZugWert erhöhen wolltest, dann wird das nichts.
Das gleiche gilt für:
aZugWert =- 1;
Das macht das gleiche wie
aZugWert = -1;
Du wolltest vermutlich dekrement, also
aZugWert -= 1;
Schreib da besser
aZugWert --;
 
Ok, das hätte ich vielleicht sage sollen, das habe ich schon ausprobiert, ändert aber nichts. Als ich deinen post gelesen habe, ist mir auch klar geworden, was ich da gemacht habe, aber wie gesagt, ame Ergebniss ändert sich letztendlich nichts.
 
Beim Stichwort MiniMax ist man sicherlich gut aufgehoben. Es gibt auch bestimmt einige Implementierungen in Java für TicTacToe, die man sich angucken könnte.
Aber welche Strategie da oben verwendet wird - keine Ahnung

MiniMax kannte ich auch noch nicht, aber es läuft auf eine Bewertung der Spielsituation hinaus, stimmts? Und wie sollte ein Spielsituation bewertet werden? Mir fällt bei 4Gewinnt nur gewonnen oder verloren ein. Sollte die Anzahl gleicher in einer "Reihe/Spalte/Diagonale" mit einfließen? Jedenfalls erst mal Danke für die Verlinkung. Muss das an anderer Stelle nochmal nachlesen.

Aber unabhängig davon: Nach einem MiniMax-Algorithmus sieht die "Idee" oben aber nicht aus oder?
 
Sollte aber ein MiniMax Algorithmus sein...😳

Naja, ich hab den ganzen Code jetzt noch mal über den Haufen geworfen und mit einem deterministischem Ansatz von vorne angefangen. Läuft auch einigermaßen, auch wenn es sicher noch Verbesserungsmöglichkeiten gibt.

Trotzdem danke an alle, die mir helfen wollten.
 
...wollte auch helfen, aber du kannst na nicht erwarten, dass sich das bei dieser "verschachtelung" jemand durchliest ^^
 
Jep, is mir auch klar, nur hatte ich echt keine Idee, wie ich das anders lösen sollte.
Das war auch der Grund, weshalb ich das nochmal beschrieben habe, damit man sich das nicht komplett durchlesen muss um das zu verstehen.
 

Zurück
Oben