TicTacToe bauen

Ich bin zwar schon den ganzen Tag müde, aber versuche es trotzdem. Ist aber rein VHIDT und basiert nicht auf deinen bisherigen Sources.

Java:
public class ComputerStep
{
	private static final byte DIRECTORY_EAST = 0;
	private static final byte DIRECTORY_SOUTH = 1;
	private static final byte DIRECTORY_DIA_SOUTH_EAST = 2;
	private static final byte DIRECTORY_DIA_SOUTH_WEST = 3;

	private static final Dimension[] DIRECTORY_STEPS = {
		new Dimension(1, 0),
		new Dimension(0, 1),
		new Dimension(1, 1),
		new Dimension(-1, 1);
	};

	private static final Step[] STEPS = {
		new Step(new Point(0, 0), DIRECTORY_EAST),
		new Step(new Point(0, 0), DIRECTORY_SOUTH),
		new Step(new Point(0, 0), DIRECTORY_DIE_SOUTH_EAST),
		new Step(new Point(1, 0), DIRECTORY_SOUTH),
		new Step(new Point(2, 0), DIRECTORY_SOUTH),
		new Step(new Point(0, 1), DIRECTORY_EAST),
		new Step(new Point(0, 2), DIRECTORY_EAST),
	};

	private GameButton[][] buttons;
	private Point foundetFreeField;

	public static void start()
	{
		boolean bool = false;
		for(byte b = 0; b < STEPS.lenght && !bool; b++)
		{
			foundetFreeField = null;
			Step step = STEPS[b];
			bool = computing(step.getPoint(), step.getDirectory(), 1, 0, 0);
		}
	}
	private static boolean computing(Point point, byte dir, byte stepCount, byte foundetFree, byte foundetEnemy)
	{
		boolean b = false;
		if(stepCount != 3)
		{
			GameButton gameButton = buttons[point.x][point.y];
			if(gameButton.getPlayerStone() == null)
			{
				foundetFree++;
				foundetFreeField = point;
			}
			else if(gameButton.getPlayerStone().getPlayer == Stone.HUMAN)
				foundetEnemy++;

			Dimension dirSteps = DIRECTORY_STEPS[dir];
			b = computing(new Point(point.x + dirSteps.width, point.y + dirSteps.height), dir, stepCounter + 1, foundetFree, foundetEnemy);
		}
		else
		{
			if(foundetFree == 1 && foundetEnemy == 2)
				b = true;
		}
		return(b);
	}

	private static class Step
	{
		private Point p;
		private byte dir;

		private Step(Point p, byte dir)
		{
			this.p = p;
			this.dir = dir;
		}
		private Point getPoint()
		{
			return(p);
		}
		private Point getDirectory()
		{
			return(dir);
		}
}
 
Zuletzt bearbeitet:
Okay, die Rekursion ist mir jetzt klar, aber deine Info war auch ziemlich hilfreich.

Wenn Mitte als erster Zug nicht belegt, dann Mitte belegen. Sonst zufällig belegen.

Hmm.. und jetzt versuche ich mich an den Rest, aber da werde ich mir schon wieder unsicher. Weil... man muss doch für jede Richtung und jeden Fall eine IF-Abfrage machen. Ich verstehe den Sinn der Rekursion irgendwie nicht, weil ich doch einfach eine For-Schleife benutzen kann?
 
Nein, das wäre Iterativ (wiederholend) und nicht rekursiv (selbstbezüglich).
Warum brauchst du ifs? Zwar bezweifel ich, dass das was ich geschrieben habe wirklich so funktioniert (wäre das Erste mal, das eine Klasse von mir auf Anhieb funktioniert), aber ich habe ja auch nur 2 ifs. Eine prüft ob das geprüfte Feld eine Menschlichen oder keinen Spielstein (bzw. auch indirekt ob es ein Computer-Stein) enthält, und eine prüft, ob er das Ende des Spielfeldes und damit der Rekursion erreicht wurde.
 
Na brauche ich nicht IFs, um zu gucken welches Feld belegt werden soll? Ich muss doch die Strategie des PC-Gegners festlegen.
 
Warum? Du willst doch hoffentlich nicht jede mögliche Kombination einzeln eintragen.
Du musst auf jeden Fall einen Zufallsaspekt einbauen. Sonst wird der Computer zu berechenbar, was es langweilig werden lässt. (Gut, bei Tic Tac Toe ist da nichts zu verlieren, aber allgemein).
Andererseits muss der Rechner natürlich mögliche Kombinationen blocken. Also kannst du durch die Rekursion mögliche 3er-Reihen blocken, und wenn es keine gibt zufällig platzieren, damit bei den gleichen menschlichen Zügen nicht immer das genau gleiche Endergebnis rauskommt.
 
Nee, "wollen" möchte ich bestimmt nicht, aber ich kann mir gerade einfach nicht ausmalen wie es in Java aussehen würde mal so einen Fall zu definieren, dass er bei der und der Belegung, so und so entscheidet.
Und von deinem (riesigen) Code wurde ich ehrlich gesagt nicht so wirklich schlauer. Tut mir Leid. Das ist nicht böse gemeint. Ich will es ja verstehen, aber es fällt mir so schwer. :(
Wenn ich einfach wüsste wie ich das Code-technisch anstelle, dass er z.B. bei 0 dann 2 belegt, usw.

Ich denke da irgendwie nur an die IF-Bedingungen... aber das liegt auch daran, dass ich eben noch eine Anfängerin bin in Java und bisher eher nur PHP kann und selbst das nicht so super...
 
Die 81 Zeilen findest du riesig? (34 für die eigendlichen Methoden). oo"
Beginne bei der start() und gehe einfach zeilenweiße durch. Dann wirst du sicher schnell verstehen, wie es funktioniert. (Oder von mir zumindest geplant war).
 
Hey mir ist aufgefallen, dass es hier noch Probleme zu geben scheint, was den Spielalgorithmus für die KI angeht.
Es gibt einen "Allgemeinen Spielalgorithmus" (so hat ihn jedenfalls mein früherer Lehrer genannt) der rekursiv arbeitet. Dieser ist mit folgender Anleitung beschrieben:
1*. Bestimme ein Maß für die Qualität der aktuellen Spielstellung aus der Sicht des Spielers
--> In der Regel int als "Bewertungsnote"
2*. Teste für den Spieler, der gerade am Zug ist, alle möglichen Züge. Für jeden dieser Züge teste rekursiv alle möglichen Reaktionen des Gegners, für jeden dieser Reaktionen teste rekursiv alle möglichen Gegnerreaktionen usw.
--> Zusätzlich ist es hier möglich eine Maximalanzahl für die Rekursionsebenen anzugeben, wodurch die KI-Stärke bestimmt werden kann. Es gibt maximal 9 Ebenen, wodurch es auch zu keinen Problemen mit Rekursion kommen sollte.
3*. Wähle als besten Zug denjenigen, der bei entsprechender Reaktion des Gegners im Endeffekt zur größten Verbesserung der eigenen Stellung führt.
--> Der Zug mit der höchsten "Bewertungsnote".




*zitiert aus "Algorithmen kompakt und verständlich" von Markus von Rimscha
 
Ja, aber

Code:
³ Wir stellen bei dieser Gelegenheit auch fest, dass Tic-Tac-Toe tatsächlich nicht zu
gewinnen ist, wenn der Gegner keinen Fehler begeht.

Ein Computer könnte heutzutage leicht die "paar" Möglichkeiten, die Tic Tac Toe hat durchzurechnen, und würde zu den Entschluss kommen, dass er, wenn der Gegner in die Mitte setzt, er niemals in die Mitte einer Kante setzen darf.

Beispiel:

Code:
---
-x-
---

---
-xo
---

x--
-xo
---

x--
-xo
--o

x-x
-xo
--o

Falls er das macht, wird das Spiel sogar noch einseitiger, und er wird nicht mehr schlagbar.
Und ich denke nicht, das irgendjemand CnC lange gespielt hätte, wenn der Gegner vom Beginn an eine Basis gebaut hätte (wenn er in den Missionen keine vorgegebene hätte), die der Spieler mit dem zu ihm zur Verfügung gestellten Geldmitteln nicht durchdringen könnte.

Deshalb bin ich der Meinung, man darf ein Spiel nicht so ohne weiteres durchrechnen lassen, denn wenn man das macht hat der Spieler gegen einen Rechner mit heutzutage min. 12 GFlops nicht den Hauch einer Chance.
 
Zurück