Spiel: TIC TAC TOE

Status
Nicht offen für weitere Antworten.

Underworld

Aktives Mitglied
Hi, da bin ich wieder :D

Ich hab heute aus Spaß versucht Tic Tac Toe zu programmieren. (bin eh krank, hab mich ein bisschen erkältet, da hab ich nichts zu tun *g*)

Java lerne ich erst seit ein paar Wochen im Grundkurs Informatik. Viele Möglichkeiten etwas zu "programmieren" kenne ich noch nicht, jedoch bin ich da offen und würde auch gerne etwas dazulernen.
Methoden die ich bis jetzt so durchgenommen hab: if-Bedingungen, Schleifen(For und while),
Konstruktoren, im Grafikfenster linien, kreis, rechtecke usw. zu zeichnen, oder auch zum Beispiel eine Klasse Stern aus den Klassen Dreieck zu programmieren.
Also eig Grundlegende Sachen, tiefer sind wir aber noch nicht in Java eingestiegen!

So sieht mein Code momentan aus:

Java:
import java.awt.*;
import javax.swing.*;

public class Oberfläche

{

	public  Oberfläche() {
		// Standard-Grafikoberfläche holen:
		Graphics2D g = GrafikFenster.gibGrafikFläche();

		for (int i = 125; i <= 1000; i += 250) {
			g.drawLine(125, i, 875, i);

			g.drawLine(i, 125, i, 875);
		}

		for (int a = 0; a <= 8; a += 1) {
			if (a <= 2) {
				g.drawString(String.valueOf(a + 1), 250 * a + 130, 140);
			}
			else {
				if (a <= 5) {
					g.drawString(String.valueOf(a + 1), 250 * (a-3) + 130, 390);
				}

				else {
					g.drawString(String.valueOf(a + 1), 250 * (a-6) + 130, 640);
				}
			}
		}
g.setColor(Color.GREEN);
g.setFont(new Font("Helvetica", Font.BOLD, 50));
g.drawString("TIC TAC TOE", 350,75);	
}
}

Java:
import java.awt.*;
import javax.swing.*;

public class Zeichen {
	private Oberfläche Gitter;

	public Zeichen() {
		Gitter = new Oberfläche();

	}

	public void zeichneX(int a) {
		// Standard-Grafikoberfläche holen:
		Graphics2D g = GrafikFenster.gibGrafikFläche();
		g.setColor(Color.BLACK);

		if ((a <= 3) & (a > 0)) {
			g.drawLine(175 + (a - 1) * 250, 175, 325 + (a - 1) * 250, 325);
			g.drawLine(175 + (a - 1) * 250, 325, 325 + (a - 1) * 250, 175);
		}
		else
			if ((a <= 6) & (a >= 4)) {
				g.drawLine(175 + (a - 4) * 250, 425, 325 + (a - 4) * 250, 575);
				g.drawLine(175 + (a - 4) * 250, 575, 325 + (a - 4) * 250, 425);
			}
			else
				if ((a > 6) & (a <= 9)) {
					g.drawLine(175 + (a - 7) * 250, 675, 325 + (a - 7) * 250,
							825);
					g.drawLine(175 + (a - 7) * 250, 825, 325 + (a - 7) * 250,
							675);
				}
				else
					if ((a < 0) | (a > 9)) {
						g.setColor(Color.RED);
						g.drawString("Du Idiot! Falsche Zahl!", 175, 175 + 500);

					}

		GrafikFenster.aktualisiereGrafik();
	}

	public void zeichneKreis(int a) {
		// Standard-Grafikoberfläche holen:
		Graphics2D g = GrafikFenster.gibGrafikFläche();
		if ((a <= 3) & (a > 0)) {
			g.drawOval(175 + (a - 1) * 250, 175, 150, 150);

		}
		else
			if ((a <= 6) & (a >= 4)) {
				g.drawOval(175 + (a - 4) * 250, 425, 150, 150);
			}
			else
				if ((a < 0) | (a > 9)) {
					g.drawOval(175 + (a - 7) * 250, 675, 150, 150);
				}
				else
					if ((a < 0) | (a > 9)) {
						g.setColor(Color.RED);
						g.drawString("Du Idiot! Falsche Zahl!", 175, 175 + 500);

					}

		GrafikFenster.aktualisiereGrafik();
	}
}


Eig kann man da schon ganz gut Tic Tac Toe spielen. Ist zwar nen bisschen umständlich und es gibt auch noch keine Überprüfungen etc.

Um das zu verbessern habe ich einige Fragen.

1. Wie kann ich abfragen, ob ein "Feld" schon belegt ist?

2. Wenn ich das weiß, wie kann ich dann abfragen ob sich drei X oder drei O in einer Reihe befinden?

3. Ist es möglich einfach die Eingabe des Feldes über die "Maussteuerung" zu generieren? Wenn ihr meinen Code lest, werdet ihr schnell verstehen, wie ich das momentan gelöst habe!

viele Dank fürs lesen und hoffentlich auch fürs Antworten

lg Flo
 

0din

Bekanntes Mitglied
Ich blick net ganz durch den code aber ich habn au nur ganz knapp überflogen weil wegn wenig zeit... ^^

1. Bau dir ne int variable in dein Feld; -1 = frei; 0 = belegt player1; 1 = belegt player2
2. Nach jedem zug die felder abfragen lassen un wenn sich auf den entsprechenden stellen gleiche zahlen befinden haste nen sieger
sowas in die richtig
Java:
for(each feld)
{
arraylist.add(feld)
}
dann kannste auf die entsprechenden positionen vergleichen bzw zusammen addieren
3.kp, die gui sachn habsch mir bei dir net angesehn... ^^
 

Marco13

Top Contributor
Wenn ihr meinen Code lest, werdet ihr schnell verstehen, wie ich das momentan gelöst habe!

NEIN

Sorry, das wollte ich gerade mal so deutlich sagen :D Erstens fehlt die Klasse "Grafikfenster" (die habe ich glaube ich sogar noch aus einem früheren Thread...), es gibt keinen Hinweis auf irgendwas, was mit der Maus zu tun hat, aber viel wichtiger: Man versteht fremden Code nicht einfach durch durchlesen. Beispiel gefällig?
Java:
class _{public static void main(String I[]){int i=5,í[][]=new int[i][i];_(i,1,i
/2,i-1,í);î(í);}static int _(int ì,int i,int í,int î,int ï[][]){return i>ì*ì?i-
1:(ï[í][î]=_(ì,i+1,(í+(i%ì==0?0:1))%ì,(î+(i%ì==0?-1:1))%ì,ï))-1;}static void î(
int î[][]){for(int i=0;i<î.length;i++){for(int í=0;í<î[i].length;í++)System.out
.print((î[í][i]<10?" ":"")+î[í][i]+" ");System.out.println();}}}
:D

Man versteht ihn bestenfalls durch nachvollziehen. Und das kostet Zeit.

Wie auch immer. Ein TicTacToe zu schreiben, und das Spiel ausschließlich durch Linien auf einem Bild repräsentieren zu wollen, ist ... ein falscher Ansatz. Überlege dir, was man mit einem Tic-Tac-Toe-Spiel machen können will. Und schreibe das als Methoden in eine Klasse (die Methoden können erstmal leer sein - erst überlegen, welche Methoden man braucht) :
Code:
class TicTacToe
{
    public void setzeZeichen(char zeichen, int zeile, int spalte)
    {
    }

    .... // Was noch?
   ...
}
Dann überlege dir, welche Dinge du brauchst, um das Spielfeld zu repräsentieren. (Als Tipp: Ein array - und wenn ihr das "noch nicht gelernt habt", dann ... lies es dir in einem Tutorial durch :rtfm: :) )

Das GUI ... kommt ganz am Ende.
 

Underworld

Aktives Mitglied
Hi,

sorry, ich habe gedacht man kann meinen Code schnell verstehen :oops:
Kurz zum erklären der Funktionsweise:
1 Klasse: Oberfläche in ein Grafikfenster zeichnen(ein Gitter mit 9 Fenstern)
2 Klasse: Sie beinhaltet 2 Methoden. Eine Methode zeichnet das "X", die andere das "O". Um das "X" oder das "O" zu zeichnen, muss ich nur eine Variable eingeben (von 1-9) und das Programm weiß auf welcher Position das "Zeichen" zu setzen ist

Aus mehr besteht, das Programm momentan noch nicht. Weil ich nicht genau weiß ich wie weiter machen soll *g*

Zu den Arrays, diese habe "ich noch nicht gelernt".
Ich werde wieder kommen, wenn ich mir die Funktionsweise von Arrays angeeignet habe!

Zu der Mauseingabe. Da kann man momentan auch noch gar nichts finden. Ich habe nämlich keine Ahnung wie ich die einsetzen kann. Wenn dass aber für meinen Kenntnisstand noch zu schwierig ist, kein Problem. Ich habe mich wohl "falsch" ausgedrückt.


Und jetzt schon mal an Marco13 und seinen Code:
Java:
 public void setzeZeichen(char zeichen, int zeile, int spalte)

Warum benutzt du int zeile und int spalte? Du kannst doch nur durch die Angabe von 1-9 schon die Position des Zeichen berrechnen. Zumindest in meiner Lösung. Die wird dir wahrscheinlich aber nicht zussagen *g*

Vielen Dank für die Antworten. Die helfen mir schon ein bisschen!

lg Flo
 

Ark

Top Contributor
Warum benutzt du int zeile und int spalte? Du kannst doch nur durch die Angabe von 1-9 schon die Position des Zeichen berrechnen.

Etwas Wichtiges, das jeder Informatiker im Laufe seiner Karriere lernt: Unterscheiden zwischen der internen Repräsentation (z.B. eines Objekts) und seinem Verhalten nach außen (z.B. gegenüber dem Endanwender).

Einfaches Beispiel: Der Endanwender sieht ein leeres Feld, ein Kreuz oder einen Kreis. Das Programm verarbeitet diese Zeichen aber anders, es gibt ihnen Nummern (meistens natürliche Zahlen, z.B. 0, 1 und 2). Auf diese Weise werden die Zusammenhänge im Spiel für eine Rechenmaschine beschreibbar.

Noch ein Beispiel: die von dir beschriebene Signatur einer Methode beschreibt die Schnittstellen nach außen(!), normalerweise gegenüber anderen Objekten. Ob dieses Objekt jedoch intern(!) mit eindimensionalen oder zweidimensionalen Arrays oder mit einzelnen Variablen arbeitet, ist egal:
Java:
// Beispielimplementierung 1:
public void setzeZeichen(char zeichen, int zeile, int spalte){
	spielfeld[zeile][spalte] = zeichen;
}


// Beispielimplementierung 2:
public void setzeZeichen(char zeichen, int zeile, int spalte){
	spielfeld[zeile*3+spalte] = zeichen;
}
Beide Male sind die Koordinaten jeweils als Zahlen zwischen 0 und 2 anzugeben. Im ersten Fall wird intern ein zweidimensionales Array verwendet. Fall zwei bedient sich dagegen eines eindimensionalen Arrays und nimmt dazu eine Umrechnung vor. Intern, wie gesagt, lösen beide Implmentierungen das Problem auf verschiedene Weise, gegenüber anderen Objekten ist das Verhalten aber gleich.

Ich rate dringend dazu, die interne Repräsentation der Objekte jeweils so zu wählen, dass sie die Aufgaben, für die sie zuständig sind, so einfach wie möglich erledigen können.

Ark
 

Marco13

Top Contributor
sorry, ich habe gedacht man kann meinen Code schnell verstehen :oops:
Ja, in diesem Fall ging es ja noch :) ich wollte nur (übertrieben deutlich) darauf hinweisen, dass ein gewaltiger Unterschied besteht zwischen
- Code, den man selbst auf Basis von Wissen um das Problem, Kenntnis der Rahmenbedingungen und Selbst-Erarbeitung eines Lösungweges geschrieben hat und
- Code, den irgendjemand anderes (irgendein krankes Hirn :D ) aus nicht mehr nachvollziehbaren Gründen genau so hingeschrieben hat.

Bei sowas wie
Code:
for (int i = 125; i <= 1000; i += 250) {
            g.drawLine(125, i, 875, i);
stehen halt irgendwelche magischen Zahlen dort, die genau so sein müssen, weil das Grafikfenster genau die Größe hat, und du das genau so haben wolltest.

Das jetzt nicht als "Dämpfer" ansehen: Es ist genau das richtige wenn du dir Programme überlegst, die du im Rahmen deiner Möglichkeiten schreiben kannst, und damit Übung bekommst und Kenntnisse verbesserst (oder wie in einer Signatur hier im Forum: "Programmieren lernt man nur durch Programmieren").

BTW: Diese "Grafikfenster" Klasse soll eine Vereinfachung sein - an sich ist das nicht verkehrt: Es sorgt sicher für Motivation, wenn man mit ein paar einfachen Befehlen ein bißchen Grafik auf den Bildschirm zaubern kann. Aber wie ich ja schon im "Funktionsplotter"-Thread angedeutet habe: Das suggeriert vielleicht eine Einfachheit, die nicht immer gegeben ist - und spätestens, wenn man Dinge wie Mausinteraktion einbauen will, kann es sein, dass man mit solchen vereinfachenden Hilfsklassen an Grenzen stößt.
Ich würde dir DRINGEND empfehlen, dir mal Lesson: Performing Custom Painting (The Java™ Tutorials > Creating a GUI With JFC/Swing) durchzulesen. Dort wird beschrieben, wie man eine eigene Component entwickelt, auf die man zeichnen kann, und wie die Maus-Interaktion grundsätzlich funktioniert. Wenn du das durchgearbeitet hast, wirst du sicher leicht eine eigene Component erstellen können, namens "TicTacToeSpielfeld", die dein Spielfeld zeichnet, und durch die du mit der Maus dein TicTacToe bedienen kannst.
Aber nochmal: Das eigentliche Spiel (die angedeutete Klasse "TicTacToe") hat mit dem GUI (also das "TicTacToeSpielfeld") nichts zu tun. Das GUI wird nur verwendet, um das Spiel anzuzeigen und zu steuern, aber das Spiel selbst könnte auch ohne GUI laufen.

Das
public void setzeZeichen(char zeichen, int zeile, int spalte)
hat Ark ja schon schön erklärt.
Aber nochmal zum Prozess an sich: Ich hatte ja gesagt, dass du diese Methoden erstmal leer lassen kannst, und erstmal nur überlegen sollst, WELCHE Methoden es gebe muss. Dieses Konzept wird in der Praxis oft konsequenter gemacht, indem man interfaces verwendet. In einem Interface stehen NUR die Methoden, und man plant einen großen Teil seines Programmes allein damit. Tatsächlich ist es so, dass oft schon der größte Teil der Arbeit dafür aufgewendet wird, sich die Interfaces zu überlegen.

Du erinnerst dich vielleicht an das "interface Function", aus dem Funktionsplotter: Man konnte den eigentlichen Plotter schon schreiben, obwohl man nur dieses leere Interface defniert hatte. Ob das dann später mit "f(x)=x*x" gefüllt wurde, oder mit "f(x)=0.5*x-2" spielte keine Rolle...
 

Underworld

Aktives Mitglied
Hi,

habe mich heute ein wenig in die Arrays reingelesen.

Habe jetzt zumindest verstanden für was sie da sind und hab auch schein "kleinere" Anwendungen verstanden.

Als Hilfe diente mir vor allem diese Seite:
Java/Array ? ZUM-Wiki

Jetzt sehe ich auch schon viel klarer, wie ich das TicTacToe gestalten kann!
2 Dimensionale Arrays muss ich noch nachvollziehen, ich denke, die könnten ganz hilfreich sein, sowie Ark das beschrieben hat.

Java:
// Beispielimplementierung 1:
public void setzeZeichen(char zeichen, int zeile, int spalte){
    spielfeld[zeile][spalte] = zeichen;
}
 
 
// Beispielimplementierung 2:
public void setzeZeichen(char zeichen, int zeile, int spalte){
    spielfeld[zeile*3+spalte] = zeichen;
}


Das zweite Beispiel sagt mir zwar momentan noch mehr zu, aber das gibt sich hoffentlich, wenn ich weiß ich die mehr dimensionalen Arrays benutzen kann!

Ich wollte mich nur noch mal melden, damit ihr wisst, dass ich eure Hilfe zu schätzen weiß und dass ich immer noch versuche das "Spiel" zu programmiere und nicht aufgegeben habe :D

lg Flo


EDIT: Hab grad noch die Übungsaufgaben, der Seite gemacht. Arrays sind bis jetzt das interessanteste was ich bisher gemacht hab. Da zeigen sich ja aufeinmal nen Vielfaches von neuen Möglichkeiten :eek:
 
Zuletzt bearbeitet:

0din

Bekanntes Mitglied
beim ersten bsp. sparst du dir das rum rechnen un das macht den code leichter zu lesen

was ich vllt anmerken sollte, in deinen bsps müsste dein spielfeld ein zweidimensionales char array sein ;)
also sowas
Java:
char[][] spielfeld = new char[3][3];

es wär also vllt sinniger deine "feld" klasse so zu gestallten das man se mim char füttern kann
Java:
public class Feld
{
private char token;

public void setToken(char zeichen)
{
this.token = zeichen;
}

public char getToken()
{
return token;
}
}
 

Underworld

Aktives Mitglied
eine Frage zu char

Das haben wir noch nicht durchgenommen und im Internet steht, dass char ein Buchstabe ist!

kann man char ungefähr so ansehen wie ein String nur mit einem einzelnem Buchstaben?
 
U

unregistriert

Gast
Char steht für ein Zeichen. Das kann auch eine Zahl sein.
 

Ark

Top Contributor
Und nicht nur ASCII, sondern eher Unicode. ;)

beim ersten bsp. sparst du dir das rum rechnen un das macht den code leichter zu lesen
Jein. Die Umrechnung ist nur nötig, wenn tatsächlich Zeile und Spalte angegeben werden. Ändert man jedoch die Schnittstelle, so ergibt sich ein ganz anderes Bild:

Java:
// Beispielimplementierung 1:
public void setzeZeichen(char zeichen, int position){
	spielfeld[position/3][position%3] = zeichen;
}


// Beispielimplementierung 2:
public void setzeZeichen(char zeichen, int position){
	spielfeld[position] = zeichen;
}
Nun gibt man nicht mehr Zeile und Spalte getrennt, sondern eine Position (0 bis 8) an, die beide Angaben in sich vereint. Ergebnis dieser Änderung: die eindimensionale Variante ist nun einfacher als die zweidimensionale. Die Frage ist eben, welche der beiden internen Darstellungen in den meisten Fällen von Vorteil ist. Dabei steht nach wie vor die interne Verarbeitung im Vordergrund, dies zu entscheiden: die Umrechnung von der externen Darstellung in die interne Darstellung macht man für gewöhnlich seltener, als die Daten anschließend (in der internen Darstellung) zu verarbeiten. Deswegen ist es nicht besonders klug, sich bei den internen Angelegenheiten eines Objekts zu verrenken, nur damit das Rein und Raus der Daten "schön" aussieht.

Ich persönlich vermute, dass z.B. das Überprüfen auf Gewinnen mit einem eindimensionalen Array einfacher zu bewerkstelligen sein wird, und bevorzuge deshalb diese Variante. Daraus ergibt sich auch schon, sich auf die einfachere Implementierung (siehe oben) zu stützen; erst bei Bedarf kann man dann auch die anderen Schnittstellen zur Verfügung stellen. Das eindimensionale Array hat weiterhin den Vorteil, dass die einfachere Positionsangabe gut mit einer möglichen Art der Eingabe seitens des Benutzers einhergeht: Gibt der Benutzer eine Zahl zwischen 1 und 9 an, so braucht der Aufrufer der Methode nur ein "minus Eins" an den Wert hängen, und schon ist die Eingabe in die interne Sicht überführt.

was ich vllt anmerken sollte, in deinen bsps müsste dein spielfeld ein zweidimensionales char array sein ;)
Auch hier eher jein. Sauberer ist es wohl, [c]int[/c] statt [c]char[/c] zu benutzen und Konstanten zu verwenden, ungefähr so:
Java:
public static final int NOTHING = 0, PLAYER1 = 1, PLAYER2 = 2;
Die beiden [c]PLAYER[/c]-Konstanten sind wahrscheinlich sowieso obsolet. Zugegeben, das ist kein echtes Argument gegen [c]char[/c], jedoch kommt man bei [c]int[/c] in diesem Spiel nicht so schnell auf die Idee, die externe Sicht (' ', 'X', 'O') mit der internen Sicht (0, 1, 2) zu vermischen. Falls jemand nämlich auf die Idee kommt, statt X und O etwas anderes zu verwenden, wäre bei einer strikten Trennung von interner und externer Darstellung (also die Verwendung von [c]int[/c]) keine einzige Änderung in dieser Klasse nötig.

Ob der Einsatz von [c]enum[/c]s sinnvoll ist, lasse ich mal dahingestellt.

Ark
 

Marco13

Top Contributor
Dabei steht nach wie vor die interne Verarbeitung im Vordergrund, dies zu entscheiden: die Umrechnung von der externen Darstellung in die interne Darstellung macht man für gewöhnlich seltener, als die Daten anschließend (in der internen Darstellung) zu verarbeiten. Deswegen ist es nicht besonders klug, sich bei den internen Angelegenheiten eines Objekts zu verrenken, nur damit das Rein und Raus der Daten "schön" aussieht.

*einhak* Das sehe ich ... ziemlich anders. Was man ... eigentlich programmiert, bzw. was man entwirft und als (nicht zuuu verwobenes ;) ) Geflecht von interagierenden Entitäten zusammenfügt, und womit man versucht, die Wirklichkeit nachzumodellieren, sind eigentlich die Interfaces. TicTacToe besteht aus einem Feld der Größe 3x3. Daraus folgt (für mich) direkt, dass man eine Methode [c]get(int x, int y)[/c] hat. Dass es jetzt für eine spezielle KI vielleicht "praktischer" wäre, einen 1D-Array zu haben, sollte bei dieser Entscheidung keine Rolle spielen.

Man sollte die mögliche interne Darstellung natürlich idealerweise schon im Hinterkopf haben. Und im Idealfall wählt man eine Darstellung nach außen, die "schön" ist, und trotzdem "vollständig" (also keine potentiell wichtigen Informationen weglassen, um die Schnittstelle "schöner" zu machen).

Am konkreten Beispiel ist vielleicht schwierig zu verdeutlichen, was ich meine... Aber... stell' dir vor, du willst MineSweeper programmieren - mit unterschiedlichen Feldgrößen. Jemand klickt auf einem Feld an die Position (3,5). Man (der Aufrufer) weiß nicht, welchen Array-Index er dort übergeben muss. Er muss erst abfragen, wie breit das Feld ist, und den index dann selbst ausrechnen. Oder muss er vielleicht abfragen, wie hoch das Feld ist? Das weiß er nicht. Wenn das Feld die Größe (4,4) hat, kann er problemlos auf die Position (6,1) zugreifen, und er wird den Fehler u.U. nicht unmittelbar bemerken.

Ja, nur ein Beispiel.

Ich wollte nur betonen: Die interne Darstellung sollte beim Entwurf der Schnittstelle IMHO keine Rolle spielen.
 

Underworld

Aktives Mitglied
Hi,
habe nen bisschen an der "Spielengine" oder wie man es nennen möchte, gecodet

Prinzip hinter dem Code ist ein 2-dimensionales Array.
Kurzer Überblick über meine Methoden: (Damit ihr die auch verstehen könnt)
1. Erst eine Beispielmethode in der das Feld gefüllt wird, damit ich meine Methoden ausprobieren kann.

2. Dann eine "Setter" Methode, um die Sachen "variabel" zu füllen. Die Getter Methode natürlich gleich dazu.

3. Eine Methode um die Anzahl der Zeichen zu berechnen (gelöst über 2 in sich verbundene for-Schleifen, funktioniert so ganz gut :toll: )

4. Zuletzt die "Wer ist drann"-Methode, die mir ausgibt wer den nächsten Zug ausführen soll.
Hier muss ich noch ein paar Sachen verbessern, vor allem für den Fall wenn die Anzahl X = Anzahl Kreise ist.
Das werde ich aber so lösen, indem ich eine "WerFängtAn" Methode schreibe, die angibt wer gestartet hat. So kann ich relativ einfach die "WerIstDrann" Methode vervollständigen.

Als nächstes kommt, dann der etwas kompliziertere Teil, in dem ich ausgeben muss, ob jemand gewonnen oder unentschieden gespielt gespielt.
Das sollte zumindest dank 2-Dimensionaler Arrays ziemlich simpel gehen. Wenn einfach ein Array mit dem gleichen Wert (X oder O) dreimal den gleichen Index von einen der beiden "Arrayarten" hat, ist dies eine Reihe. (Das konnte ich jetzt leider nicht einfacher ausdrücken, da fehlt mir leider das Fachvokabular :( )
Und natürlich für die beiden Sonderfälle, wenns diagonal ist, aber da gehe ich jetzt nicht drauf ein!


Java:
public class Spielengine {

	int anzahlX = 0;
	int anzahlO = 0;
	char zeichenX = 'X';
	char zeichenKreis = 'O';
	char untentschieden = 'U';

	public Spielengine() {
		spielFeld = new char[3][3];
	}

	char[][] spielFeld = new char[3][3];

	public void setzeBeispielFelder() {
		spielFeld[0][0] = 'X';
		spielFeld[1][0] = 'O';
		spielFeld[2][0] = 'O';
		spielFeld[0][1] = 'O';
		spielFeld[1][1] = 'X';
		spielFeld[2][1] = 'O';
		spielFeld[0][2] = 'X';
		spielFeld[1][2] = 'O';
		spielFeld[2][2] = 'X';

	}

	// Mögliche Zeicheneingabe soll noch programmiert werden: Zeichen: O , X
	public void setCharinFeld(int spalte, int zeile, char zeichen) {
		spielFeld[spalte][zeile] = zeichen;
	}

	public char getCharInFeld(int spalte, int zeile) {
		return spielFeld[spalte][zeile];
	}

	public void anzahlDerZeichen() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (spielFeld[i][j] == 'X') {
					anzahlX++;
				}
				if (spielFeld[i][j] == 'O') {
					anzahlO++;
				}
			}
		}
	}

	public char werIstDrann() {
		// HIER UMBEDINGT NOCH EINE LÖSUNG FINDEN! Am besten mit Method: Wer hat angefangen!
		if (anzahlX == anzahlO) {
			System.out
					.println("Das ist noch problematisch, hierfür habe ich noch keine Lösung");
		}

		if ((anzahlX + anzahlO) > 9) {
			System.out
					.println("Das Spiel ist längst vorbei, warum führst du diese Methode noch aus?");
		}

		if (anzahlX > anzahlO) {
			return zeichenKreis;
		}
		else {
			return zeichenX;
		}
	}

	public void gewinner() {
	}

}

Übrigens habe ich meine beiden Klassen "Oberfläche zeichnen" und "Symbole zeichnen" so vereinfacht, dass sie nun abhängig von der Höhe und Breite des Grafikfensters gemacht.
Ich habe einfach alle "komischen Werte" mittels der getBreite und getHoehe Methode ausgedrückt, die du (Marco13) für mich geschrieben hast. Danke nochmal :)

Naja, ich werd jetzt noch nen bisschen für Donnerstag lernen. Da schreib ich Informatikklausur und das Stoffgebiet ist da was ganz anderes als das, was ich hier so mache :D
Hinbekommen werd ich das schon, nur den ganzen Code auf nen Blatt zuschreiben wird ein riesen Spaß :shock:


EDIT: Habe eure beiden Posts noch nicht gelesen, als ich das abgeschickt habe.
Ich hab gleich wieder eine frage.

Was hat es mit diesem "Static" auf sich?
Davon habe ich noch nie was gehört und ich hab auch keine Ahnung wie ich damit umgehen soll!

EDIT2: Und von enum hab ich noch weniger gehört :autsch:

EDIT3: Und mit "Schnittstelle" in Informatik kann ich mir nicht wirklich was vorstellen. Ich kann mir das zwar ungefähr denken, was gemeint sein soll, aber in Worte könnte ich das jetzt grad auch nicht packen!
 
Zuletzt bearbeitet:

Ark

Top Contributor
TicTacToe besteht aus einem Feld der Größe 3x3. Daraus folgt (für mich) direkt, dass man eine Methode [c]get(int x, int y)[/c] hat. Dass es jetzt für eine spezielle KI vielleicht "praktischer" wäre, einen 1D-Array zu haben, sollte bei dieser Entscheidung keine Rolle spielen.
Jein. Mehr dazu unten.

Ich wollte nur betonen: Die interne Darstellung sollte beim Entwurf der Schnittstelle IMHO keine Rolle spielen.
Auch hier: jein. Was ich meine, erkläre ich mal mehr oder weniger am Beispiel Tic Tac Toe: Wenn ich weiß, dass ich intern ein 1D-Array nehmen werde, dann biete ich zunächst nur die (aus interner Sicht) "einfachere" Schnittstelle an, halte mir aber als Option offen, auch die "kompliziertere" zur Verfügung zu stellen, falls sie einmal gebraucht werden sollte (gewissermaßen das Gegenstück zu deprecated). Hintergedanke: Die einfache Schnittstelle ist schnell implementiert, die kompliziertere bedarf eines größeren Aufwands. (Okay, bei Tic Tac Toe wird das nicht so deutlich.) Aber warum sollte ich mir an der komplizierteren Schnittstelle schon die Zähne ausbeißen, wenn ich noch gar nicht weiß, ob sie jemals benötigt wird? Da biete ich zunächst lieber die einfachere mit dem Hinweis an, dass die kompliziertere nicht vergessen wurde, aber erst implementiert wird, wenn sie tatsächlich benötigt wird. (Ich sollte vielleicht dazu sagen, dass ich noch nicht an größeren Projekten in Java beteiligt war. Insofern fehlt mir die Erfahrung. *schäm*)

Ark
 

0din

Bekanntes Mitglied
static = statisch = wird beim erstellen der klasse schon erstellt
enum is ne seperate klasse, müssteste dir ma selbst aneignen ;)
schnittstelln können allesmögliche sein, vom messer schnitt :lol: bis zum get/set

zu deinem code:
für die gewinne() methode musste dir nen (mathematischen) zusammenhang suchen
also z.b.
if( 1 - 3 == 3 || 1 - 3 == 6)
if( 1, 4, 6 == 3 || 1, 4, 6 == 6)
das wär mein ansatz bei nem int array bei dem 1 und 2 die spieler bzw zeichen darstelln ;)

werIstDrann()
da kannste simpel nen boolean switchen lassen, true is spieler1 un false spieler2

un die sache,"läuft das spiel noch" zähl doch einmal nen counter bei deinem setzZeichen() hoch, wenn das ding == 9 is, is das game am ende
 

0din

Bekanntes Mitglied
Ich war mal so frei un hab selbst fix was zusammen gebastelt... obs tut weiß der teufel ^^ aber damit is dir vllt n wenig geholfen...

Java:
public class Brett
{

	private Feld[][] felder;
	private boolean spieler;
	private int anzahlZeichen;

	public Brett()
	{
		felder = new Feld[3][3];
		spieler = true;
		anzahlZeichen = 0;
	}
	
	public char getCharInFeld(int x, int y)
	{
		char ret = '-';
		
		if(felder[x][y].getZustand() == 1)
		{
			ret = 'X';
		}
		
		if(felder[x][y].getZustand() == 2)
		{
			ret = 'O';
		}
		
		return ret;
	}

	public void setZeichen(int x, int y)
	{
		anzahlZeichen++;
		spieler = !spieler;		
		
		if (spieler)
		{
			felder[x][y].setZustand(1);
		}
		else
		{
			felder[x][y].setZustand(2);
		}
		checkWinner();
	}

	public void checkWinner()
	{
		//abfrage ob irgendwie drei auf einer reihe liegen für spieler 1
		if ((felder[0][0].getZustand() + felder[1][0].getZustand() + felder[0][0].getZustand()) == 3 || (felder[0][1].getZustand() + felder[1][1].getZustand() + felder[2][1].getZustand()) == 3 || (felder[0][2].getZustand() + felder[1][2].getZustand() + felder[2][2].getZustand()) == 3 || (felder[0][0].getZustand() + felder[0][1].getZustand() + felder[0][2].getZustand()) == 3 || (felder[1][0].getZustand() + felder[1][1].getZustand() + felder[1][2].getZustand()) == 3 || (felder[2][0].getZustand() + felder[2][1].getZustand() + felder[2][2].getZustand()) == 3 || (felder[0][0].getZustand() + felder[1][1].getZustand() + felder[2][2].getZustand()) == 3 || (felder[0][2].getZustand() + felder[1][1].getZustand() + felder[2][2].getZustand()) == 3)
		{
			System.out.println("Wir haben einen sieger!");
			System.out.print("Es ist Spieler 1");
		}
		else
		{
			//das gleiche für spieler 2
			if ((felder[0][0].getZustand() + felder[1][0].getZustand() + felder[0][0].getZustand()) == 6 || (felder[0][1].getZustand() + felder[1][1].getZustand() + felder[2][1].getZustand()) == 6 || (felder[0][2].getZustand() + felder[1][2].getZustand() + felder[2][2].getZustand()) == 6 || (felder[0][0].getZustand() + felder[0][1].getZustand() + felder[0][2].getZustand()) == 6 || (felder[1][0].getZustand() + felder[1][1].getZustand() + felder[1][2].getZustand()) == 6 || (felder[2][0].getZustand() + felder[2][1].getZustand() + felder[2][2].getZustand()) == 6 || (felder[0][0].getZustand() + felder[1][1].getZustand() + felder[2][2].getZustand()) == 6 || (felder[0][2].getZustand() + felder[1][1].getZustand() + felder[2][2].getZustand()) == 6)
			{
				System.out.println("Wir haben einen sieger!");
				System.out.print("Es ist Spieler 2");
			}
			else
			{
				//wenns spiel zuende is, hamma keinen sieger
				//könnte man an nen bool knüpfen
				if (anzahlZeichen == 9)
				{
					System.out.println("Wir haben keinen Sieger.");
				}
			}
		}
	}
}

Vorteil des ganzen, die spieler werden automatisch gewechselt.
Die gewinner abfrage tut ;)
die mühselige abfrage ob jmd gewonnen hat is schon fertig getippt.

eben zur info, ich hab die zustände nich als extra chars gespeichert sondern als int.
hat den vorteil ich die werte in den if abfragen addieren kann ;) (der anfrangswert im Feld is -10 also fehler durch nen leeres feld sollts net geben)

Notiz: Feld hält nur die zustände bei... eig nur variable + getter/setter

Hoffentlich hilfts dir ^^
 

Ark

Top Contributor
@0din: Nichts für ungut, aber deine Lösung halte ich mal für ... verbesserungswürdig. ;)

  1. Der Test auf Sieg ist z.B. sehr redundant formuliert: einmal hätte auch gereicht.
  2. Erst eben habe ich groß und breit erklärt, dass man die interne und die externe Sicht trennen sollte. Jegliche 'X' und 'O' sollten also besser verschwinden.
  3. Es gibt zwar nur zwei Spieler, aber das sollte dennoch kein Grund sein, deswegen auf boolean zurückzugreifen.
  4. [c]checkWinner()[/c] sollte besser einen Wert zurückgeben, je nach Situation. sysouts sind an der Stelle eher unangebracht.
  5. Und das [c]checkWinner();[/c] am Ende von [c]setZeichen()[/c] hat da mal gar nichts verloren. Das ist ein ganz böser Fauxpas.

(Hoffentlich werde ich jetzt nicht gesteinigt. :D)

Ark
 

0din

Bekanntes Mitglied
Das ding is in vllt 15min gebastelt... das des net das optimum is, weiß ich ^^ daher lass ich die steine mal im garten

der sieger test is eig. nur fix zusammen gehaun, ich hat keine große lust mir was gescheites dabei auszudenken

seine gui scheint einen char zurück bekommen zu wolln, also geb ich ihm den char ^^

mit dem bool kannstes aber simpel merken, wie willstes sonst machn?

sys out reicht doch bei den kleinen progs un wenns wirklich inne gui soll is da au fix n return rein geschrieben

der fauxpas macht aber sinn ;) so weiß ich nach jedem zug ob wer gewonnen hat, sonst muss ich das ganze jedes ma extra aus der gui aufrufen
 

Marco13

Top Contributor
Oh je... (mehr sag' ich dazu nich ... außer vielleicht die Frage: Was soll "getZustand()" liefern?)

@Ark: ...dann biete ich zunächst nur die (aus interner Sicht) "einfachere" Schnittstelle an, halte mir aber als Option offen, auch die "kompliziertere" zur Verfügung zu stellen,

Ich glaube, zu erahnen, worauf du raus willst: Wenn man eine Schnittstelle hat, die extrem feine Kontrolle über alle möglichen Details bietet (und sehr direkt die internen Strukturen nach draußen zugreifbar macht), dann kann man dort eine Schnittstelle "drumwickeln", die weniger Zugriff auf die Details bietet, aber dafür vielleicht einfacher zu verwenden ist (und evtl. bei jeder Verwendung einen "einfachen", High-Level-Methodenaufruf ggf. in eine Folge von komplizierteren Low-Level-Methodenaufrufen übersetzen muss)
Teilweise hängt das mit dem zusammen, was ich meinte, als ich gesagt habe, die Schnittstelle wäre idealerweise "vollständig" (also keine potentiell wichtigen Informationen weglassen...

In diesem konkreten Fall ist es offentlichlich: Das Feld hat eine feste Größe, und man kann sowohl den (x,y)- als auch den (index)-Zuriff einfach in die jeweils andere Form umsetzen. Bei einer nicht-festen Feldgröße wäre die Umrechnung zwischen (x,y) und (index) nicht möglich, wenn man nicht noch die Breite oder Höhe des Feldes weiß (und WAS davon man braucht ist ein höchst-internes Implementierungsdetail - da kloppen sich die Fortran- und C-Programmierer ja schon seit Generationen ;) ).

Vielleicht ist es auch eine subjektive Frage, wahrscheinlich aber eine, die man je nach Anwendungsfall entscheiden muss. Trotzdem habe ich die allgemeine Tendenz, die Dinge möglichs pragmatisch so zu modellieren, wie sie sind.

Man könnte ja auch ein Spiel erstellen:
Gegeben sind 9 nebeneinander liegende Felder
[c]
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
[/c]
Ziel des Spiels ist es, die Felder abwechselnd zu füllen. Gewonnen hat der Spieler, der zuerst drei aufeinanderfolgende Felder belegt hat, oder drei Felder, die modulo 3 den gleichen Index haben, oder drei Felder, bei denen die Menge der Reste der Divisionen durch 3 die Menge {0,1,2} ist.

DANN wäre das natürlich ein 1D-Array :D
 

Underworld

Aktives Mitglied
Das ding is in vllt 15min gebastelt... das des net das optimum is, weiß ich ^^ daher lass ich die steine mal im garten

der sieger test is eig. nur fix zusammen gehaun, ich hat keine große lust mir was gescheites dabei auszudenken

seine gui scheint einen char zurück bekommen zu wolln, also geb ich ihm den char ^^

mit dem bool kannstes aber simpel merken, wie willstes sonst machn?

sys out reicht doch bei den kleinen progs un wenns wirklich inne gui soll is da au fix n return rein geschrieben

der fauxpas macht aber sinn ;) so weiß ich nach jedem zug ob wer gewonnen hat, sonst muss ich das ganze jedes ma extra aus der gui aufrufen

Hi Odin vielen Dank für den Code, aber sowas ähnliches hab ich mir auch schon zusammengeschustert.

Das mit dem Char war übrigens deine Idee:

beim ersten bsp. sparst du dir das rum rechnen un das macht den code leichter zu lesen

was ich vllt anmerken sollte, in deinen bsps müsste dein spielfeld ein zweidimensionales char array sein
also sowas
Java Code: Quelltext in neuem Fenster öffnen
1
char[][] spielfeld = new char[3][3];

Ich hab das ganze jetzt auch auf Integers umgeschrieben und so konnte ich ganz einfach die einzelnen Werte der Arrays aufaddieren überprüfen und so den Gewinner auslesen. Ähnlich wie du das gemacht hast, nur benötige ich keine Methode "getZustand"

lg Flo
 

Manuh

Mitglied
Bin selbst Java Anfänger und habs grade mal mit Swing und JFrame + JButtons probiert.
Hat mir 15 Minuten gekostet, ist auch bestimmt mit Abstand die schlechteste Version die hier nun im Forum zu finden ist, aber es funktioniert :p

Im Anhang hab ich das Grauen mal hochgeladen ;)

Gruß
Manuh!
 

Underworld

Aktives Mitglied
Bin selbst Java Anfänger und habs grade mal mit Swing und JFrame + JButtons probiert.
Hat mir 15 Minuten gekostet, ist auch bestimmt mit Abstand die schlechteste Version die hier nun im Forum zu finden ist, aber es funktioniert :p

Im Anhang hab ich das Grauen mal hochgeladen ;)

Gruß
Manuh!

Hi, leider kann ich deine "Version" nicht öffnen, poste es doch mal als Code!

Immerhin kennst du schon Begriffe wie "Swing", JFrame und JButtons, die mir momentan noch gar nichts sagen...
 

Manuh

Mitglied
Der Code ist im "src" Ordner des Zip Archivs.
Du kannst das Zip aber schon öffnen oder? Weil dann müsstest du eigentlich nur die .jar Datei ausführen. Sind alles Standardbibliotheken die normal vorhanden sein müssten.
 

Manuh

Mitglied
Kein Problem! ;)

Wollte erst die JButtons etc. in Arrays anlegen, aber das hat auf Anhieb nicht funktioniert, und weil es ja nur eine spielbare Version werden sollte die ratzfatz gemacht ist, hab ichs für demonstrative Zwecke eben so erstellt ;)

Tut mir leid, aber ich lerne noch =)

Gruß
Manuh
 

Underworld

Aktives Mitglied
eine Frage zu Arrays.

Gibt es eine Funktion die ein bestimmtes Array, sobald es einen Wert zugeteilt wurde, als fest deklariert?

Beispiel:
spielFeld[1][1]=1;

Wenn nun aber wieder spielFeld[1][1]=2; eingegeben wird, soll eine Fehlermeldung kommen.

so, nach ein bisschen überlegen, habe ich das nun so gelöst:

Java:
	int zeichenX = 1;
	int zeichenKreis = 2;
	int nothing = 0;

public Spielengine() {
		spielFeld = new int[3][3];
	}

	int[][] spielFeld = new int[3][3];


public void setIntinFeld(int spalte, int zeile, int zeichen) {
	if (spielFeld[spalte] [zeile] == 0)
	{	    
	    spielFeld[spalte][zeile] = zeichen;
	   }
	   else
	   {
	       System.out.println("Dieses Feld ist leider schon belegt. Versuchen sie es mit einem anderen Feld");
	   }
	}


Ist die Lösung gut und sollte ich sie so verwenden oder eher nicht?
 

Marco13

Top Contributor
EDIT: Siehe unten!


Das passt schon so. Statt 0,1 und 2 könnte man noch "sprechendere" Konstanten verwenden:
Code:
public static final int PLAYER_NONE = 0;
public static final int PLAYER_X = 1;
public static final int PLAYER_O = 2;
...

// Setzen:
if (feld[x][y] != PLAYER_NONE) fehlermeldung();
...


EDIT: Das hast du ja schon (fast) - bei dir heißt das eben "nothing"...
 

Underworld

Aktives Mitglied
sooooooo

Ich bin fast fertig mit dem Spiel.

Alle Methoden die für die "Spielengine" wichtig sind, habe ich geschrieben. (Bis jetzt sogar Bugfrei :D)

Durch einen Konstruktor gebe ich den Startspieler an.
Dann kann ich durch die Methode setSpielstein in der ich nur die die Feldwerte angeben muss einen Spielstein setzen. Welchen Wert der Spielstein hat, hängt ab wer gestartet hat und wer gerade drann ist.

Und wenn jemand 3 in einer Reihe hat wird sofort der Gewinner ausgegeben!

Jetzt hab ich nur noch eine Aufgabe... Ich muss das ganze noch auf mein Spielfeld bringen. Aber ich glaube, dass im Gegensatz zu dem was ich schon habe, gar nichts mehr :D
 

Underworld

Aktives Mitglied
Hi,
hab jetzt eig alles, ich möchte nur noch einen "Schönheitsfehler korrigieren"

Die Frage ist an Marco13 gerichtet, du hast mir beim "Funktionsplotter" diese Funktion in die Grafikfenster klasse impletiert:

Java:
   public static int gibBreite()
    {
        if (singleton==null){singleton=new GrafikFenster("Das Zeichenfenster");}
        singleton.zeige();
        return singleton.canvas.getWidth();
    }
    public static int gibHoehe()
    {
        if (singleton==null){singleton=new GrafikFenster("Das Zeichenfenster");}
        singleton.zeige();
        return singleton.canvas.getHeight();
    }

Ich glaube, zumindest erscheint das bei mir, wird beim Aufruf von gibHoehe() aus einer anderen Klasse automatisch das Grafikfenster gezeichnet. Ist das irgendwie zu verhindern?

Mein Ziel ist es nur den Wert zu bekommen, das Fenster soll jedoch nicht geöffnet werden, weil das "unschön" aussieht.

lg Flo
 

Marco13

Top Contributor
Ich hätte mich (NOCH!?!) deutlicher von dieser Grafikfenster-Klasse distanzieren sollen. Sie ist eine Vereinfachung, um schnelle Erfolgserlebnisse zu haben, aber ... ... Dreijährige fahren aus dem gleichen Grund auf BobbyCars rum :bae: ;)

Man kann das erstmal nicht direkt verhindern: Der Canvas hat erst dann eine "echte" Breite, wenn er angezeigt wird (vorher hat er Breite -1). Aber ... in der Grafikfenster-Klasse, die du gepostet hattest, war die Größe ja ohnehin konstant 1000x1000 - man könnte das jetzt entsprechend direkt zurückgeben, aber ... vielleicht gibt es eine elegantere Lösung, wenn man weiß, wo das aufgerufen wird (und wo stattdessen, später das Grafikfenster sichtbar werden soll) - oder anders gefragt: Für was brauchst du die Breite, wenn du es dann nicht anzeigen willst? ???:L
 

Underworld

Aktives Mitglied
Ich hätte mich (NOCH!?!) deutlicher von dieser Grafikfenster-Klasse distanzieren sollen. Sie ist eine Vereinfachung, um schnelle Erfolgserlebnisse zu haben, aber ... ... Dreijährige fahren aus dem gleichen Grund auf BobbyCars rum :bae: ;)

Man kann das erstmal nicht direkt verhindern: Der Canvas hat erst dann eine "echte" Breite, wenn er angezeigt wird (vorher hat er Breite -1). Aber ... in der Grafikfenster-Klasse, die du gepostet hattest, war die Größe ja ohnehin konstant 1000x1000 - man könnte das jetzt entsprechend direkt zurückgeben, aber ... vielleicht gibt es eine elegantere Lösung, wenn man weiß, wo das aufgerufen wird (und wo stattdessen, später das Grafikfenster sichtbar werden soll) - oder anders gefragt: Für was brauchst du die Breite, wenn du es dann nicht anzeigen willst? ???:L

ich habe mein Spieloberfläche mitlerweile variabler gestaltet.

Wenn ich die breite verändere hat dies einerseits Einfluss auf das "ZeichenGitter" und auf die X und Kreise. Das alles habe ich mitlerweile mit der breite ausgedrückt.

Außerdem ist mein Grafikfenster nun immer quadratisch aufgebaut. Das macht das ganze leichter ^^

EDIT: Naja, die ganze Grafikfenster sache werde ich früher oder später eh verlassen. Aber vorerst häng ich noch ein bisschen an ihr :D
 

Underworld

Aktives Mitglied
Hi,
nächstes Problem. Ich bin grad dabei einen kleinen "Botgegner" zu schreiben. Insgesamt will ich das erstmal recht simpel aufbauen, indem ich die Felder einfach über Zufallszahlen belege :D

Der Code sieht vereinfacht so aus
Java:
public class KI{

public Tictactoe spiel;
private Spielengine engine;

public KI(int starter)
{
spiel = new Tictactoe(starter);
}


public void setzeBotSpielstein(){
int spalte =  1+ (int)(3* Math.random() );
int zeile = 1+ (int)(3* Math.random() );

while(engine.feldBelegt(spalte-1,zeile-1)!=false)
{
spalte =  1+ (int)(3* Math.random() );
zeile = 1+ (int)(3* Math.random() );

}
spiel.setzeSpielstein(spalte,zeile);
}
}

Leider gibt BlueJ mir hier einen Fehler aus.
Und zwar: "NulllpointerException: null"

Was macht macht mein Programn?
Es erstellt im Konstruktor die Klasse "Tictactoe". Das ist die Klasse die alle anderen Klassen steuert.

Über Referenzen kann ich ja auch auf die Methoden der Klasse Tictactoe zugreifen,
aber jetzt möchte ich auf eine methode zugreifen, die nicht aus der Klasse Tictactoe ist, sondern aus einer Klasse, die die Klasse Tictactoe erstellt.

In meinem Fall wäre dass die Klasse Spielengine, jedoch habe ich keine Ahnung wie ich das ausführen/ Coden soll.

Ich hoffe ihr versteht was ich meine. Bei Fragen/ Unklarheit versuche ich gerne, mein Problem noch genauer zu schildern
 

Marco13

Top Contributor
Ob die KI das TicTacToe erstelllen sollte?

Jedenfalls ist "engine==null", weil du keine Spielengine erstellst....
 

max40

Bekanntes Mitglied
Geht es um diesen Aufruf?
Code:
engine.feldBelegt(spalte-1,zeile-1)
Möglichkeit1: Du erzeugst deine Engin in der KI klasse und übergibst die dem Tictactoe
Möglichkeit2: Du hast eine get Methode in Tictactoe die dir die engine zurückgibt, und damit kannst du die Methode aufrufen
Möglichkeit3: Du machst dir eine Methode in Tictactoe die deine 2 Parmaeter emfpfängt und die dann
Code:
engine.feldBelegt()
aufruft

EDIT:
Möglichkeit4: Wie Marco andeutete, dein Aufbau überlegen, Tiactactoe hat glaub ich eigentlich nix in KI zu suchen
 
Zuletzt bearbeitet:

Underworld

Aktives Mitglied
Ob die KI das TicTacToe erstelllen sollte?

Jedenfalls ist "engine==null", weil du keine Spielengine erstellst....

Hi,
vielen Dank für die schnellen Antworten.

Du hast recht, die KI sollte TicTacToe eigentlich nicht erstellen. Ich sollte lieber TicTacToe weiterhin alles steuern lassen und nur die Werte von der KI abrufen lassen.

Das ganze hatte ich auch so vorgehabt, nur wollte ich die KI erstmal testen bevor ich das dann so einbaue!

zu max40:
Wie könnte ich deine erste Möglichkeit realisieren? Ich weiß leider nicht, wie ich die Enginge TicTacToe übergeben soll ^^
 

max40

Bekanntes Mitglied
Java:
class Tictactoe{

    private Spielengine  _engine;

    public Tictactoe(int starter, Spielengine  engine){
        this._engine = engine;
    }

}

Java:
public class KI{
 
  public Tictactoe spiel;
  private Spielengine engine;
 
  public KI(int starter){
     engine = new Spielengine  ();
     spiel = new Tictactoe(starter, engine);
  }

// ... der Rest von deinem Code
 

Underworld

Aktives Mitglied
Ob die KI das TicTacToe erstelllen sollte?

Jedenfalls ist "engine==null", weil du keine Spielengine erstellst....

Ach hier muss ich nochmal einhaken. Da verstehe ich nicht ganz was Java macht.

Ich erstelle erst die Klasse KI, die erstellt die Klasse Tictactoe, die Klasse Tictactoe müsste wiederrum aber wieder die Klassen Spielengine, Oberfläche und Zeichen erstellen.

Dem ist anscheinend aber nicht so, warum werden diese Klassen nicht miterstellt?
 

Marco13

Top Contributor
Also, bei dem das du gepostet hattest, gab es in der KI eine
private Spielengine engine;

Und der wurde nirgendwo ein Wert zugeweisen. (Wenn in der TicTacToe auch eine
private Spielengine engine;
existiert, kriegt die KI da erstmal nichts davon mit. Wenn die einge gemeinsame Instanz haben sollen, muss diese in der einen oder anderen Richtung weitergereicht werden...)
 

Underworld

Aktives Mitglied
Also, bei dem das du gepostet hattest, gab es in der KI eine
private Spielengine engine;

Und der wurde nirgendwo ein Wert zugeweisen. (Wenn in der TicTacToe auch eine
private Spielengine engine;
existiert, kriegt die KI da erstmal nichts davon mit. Wenn die einge gemeinsame Instanz haben sollen, muss diese in der einen oder anderen Richtung weitergereicht werden...)

Achso, ja, das klärt das ganze dann auf :D
 

Underworld

Aktives Mitglied
Hi,
die nächste Frage.

Ich werde, dass jetzt einfach so aufziehen wie ichs mir am Anfang gedacht habe und Marco13 es auch vorschlägt.

der Code
Java:
public class Tictactoe{
public KI bot;
public Spielengine engine;

public class Tictactoe(){
bot = new KI();
engine = new Spielengine();
}
public void setSpielstein(int spalte,int zeile){
...
}}

public class KI{
public void berechneeinpaarSachen(){
...
engine.führeEineMethodeausEngineaus();
int a = ..;
int b = ...;
Tictactoe.setSpielstein(a,b);

}
}

Das ganze Programm soll nur über Tictactoe gesteuert werden...

Die Frage ist jetzt, darf ich in der Klasse KI einfach so die Referenz
engine.führEineMethodeausEngineaus();
ausführen?
Und die andere Frage bei: Tictactoe.setSpielstein(a,b);
das darf ich ja auch nicht so machen (glaub ich zumindest). Ich habe ja noch kein Objekt erstellt, aber das möchte ich auch nicht.

Außerdem, noch ein Problem. Wenn ich in der Klasse "Tictactoe" bin und aus der Klasse "KI" Werte entnehmen möchte, sollte ich das ja über return-Werte machen.

Java:
public class KI{
public void setzeBotSpielstein(int spalte, int zeile){
return spalte;
return zeile;
}
}

Hier hätte ich nun das Problem, dass ich 2 Rückgabe Werte hätte. Das geht ja leider nicht. Wie müsste ich dieses Problem lösen?
Mir fällt spontan ein:

Java:
public class KI{
int spalte;
int zeile;
public void setzeBotSpielstein(int spalte, int zeile){
this.spalte = spalte;
this.zeile = zeile;
}

public int returnSpalte(){
return spalte;
}

public int returnZeile(){
return zeile;
}
}

Ich glaube aber nicht, dass diese Lösung gut ist. Gibt es für sowas besseres?
 

Marco13

Top Contributor
Was hab' ich denn vorgeschlagen? (Nur wenn ich einen Sachverhalte beschreibe ist das nicht unbedingt ein Vorschlag).

Niemand weiß genau, was bei dir die Klassen "Spieleengine" und "TicTacToe" und "KI" für Funktionen haben. Ob es eine Klasse "Player" gibt, weiß man auch nicht. Man könnte sich vorstellen, dass irgendeine zentrale Stelle das Spielbrett und zwei Spieler verwaltet, und sich von beiden Spielern abwechselnd einen Zug abholt, und den auf dem Spielbrett ausführt. (DAS war jetzt ein Vorschlag - aber auch nur ein unverbindlicher - das kann man ggf. auch anders machen).

Aber zur KI noch ein etwas "verbindlicherer" Vorschlag: So eine KI muss in den meisten Fällen Züge ausführen und rückgängig machen können. Genaugenommen braucht eine "gute" (und für TicTacToe im wahrsten Sinne des Wortes perfekte) KI nur folgende Möglichkeiten:
- Einen Zug ausführen
- Den Spielstand bewerten (erkennen, ob man gewonnen oder verloren hat)
- Einen Zug rückgängig machen
Damit kann man die bekanntesten Verfahren (Sirchwort: MinMax und AlphaBeta-Suche) schon implementieren. D.h. es könnte vorteilhaft sein, sich dafür etwas ... "sauberes" zu überlegen. Praktisch wäre eine Klasse, die einen Zug speichert (also nur ein x und ein y (und ggf. eine Spieler-ID) enthält) - praktisch, aber notwendig nicht unbedingt.
 

Underworld

Aktives Mitglied
so, ich bin eigentlich fertig. Alles weitere sind nur noch spielereien.

Jetzt habe ich nur noch ein Problem. Wie kann man das Programm ausführbar machen?

Mein Problem kann ich jetzt auch nicht genauer beschreiben, weil ich einfach keine Ahnung davon habe.
Ich habe mir schon eine Main erstellt:
Java:
public class Tictactoe {

       public static Tictactoe spiel;
    public static void main(String[] args) {

        spiel = new Tictactoe();
            }
.
.
.

So weit so gut, aber ich habe keine Ahnung wie ich mein Programm nun außerhalb von BlueJ öffnen soll.
Mein Ziel ist es, dass ich soetwas wie eine "Exe" anklicken muss und TIC TAC Toe dann gestartet wird.

Tut mir leid, dass ich dass so schwammige Wörter verwenden. Mir fehlt hier einfach das Fachvokabular...

lg Flo
 

Underworld

Aktives Mitglied
Hi,
mit BlueJ habe ich ein jar Archiv erstellt, jedoch kann ich es nicht aufrufen.

Habe Windows Vista 64 Bit und die aktuelle version von Java installiert...

Woran könnte es denn scheitern?
Wenn ihr noch mehr Informationen braucht, bitte fragen, ich weiß nicht was gebraucht wird!

EDIT: Ich habe das Problem gefunden,
Java öffnet irgendwie nur grafische Anwendungen.

Die Test Konsole, wo ich meine Werte eingebe usw, wird nicht mitgeladen. Kann ich die irgendwie mitladen?
Hier ist die Klasse mit der ich die texteingabe generiere:

Java:
import java.util.Scanner;
public class Eingabe
{
      public static String gibString(String promt)
    {
        Scanner scan = new Scanner(System.in);
        System.out.print(promt);
        return scan.nextLine();
    }
}
 
Zuletzt bearbeitet:

javimka

Top Contributor
Ist die "Test Konsole" die normale Konsole von Windows?
Dann müsstest du dein jar entweder von dieser Konsole aus starten oder du könntest eine bat-Datei schreiben, die die Konsole öffnet und sofort die jar startet. Der Inhalt der bat könnte so aussehen:
[c]java -jar TicTacToe.jar[/c]
 

Underworld

Aktives Mitglied
Ist die "Test Konsole" die normale Konsole von Windows?
Dann müsstest du dein jar entweder von dieser Konsole aus starten oder du könntest eine bat-Datei schreiben, die die Konsole öffnet und sofort die jar startet. Der Inhalt der bat könnte so aussehen:
[c]java -jar TicTacToe.jar[/c]
hi,

ups, warum habe ich die Test-konsole genannt? ???:L
Das ist natürlich keine Testkonsole sondern lediglich die Java/BlueJ konsole wo auch Sachenreinkommen wie:
"System.out.println("Dieser Text steht jetzt in der Konsole");

leider habe ich keine Ahnung, ob das die Konsole von Windows ist...
 

javimka

Top Contributor
Sie haben bestimmt dieselbe Funktionalität in Bezug auf dein Programm. Ehrlich gesagt, kenne ich BlueJ nicht, aber ich gehe davon aus, dass es nicht viel anders ist als bei anderen IDEs.
Die BlueJ Konsole ist doch bestimmt Bestandteil von BlueJ, die kannst du nicht einfach "mitnehmen". Aber wenn du es mit einer Bat-Datei in der Windows Konsole öffnest, gehen alle Input/Outputs über die Konsole, so wie vorher bei BlueJ.
 

Underworld

Aktives Mitglied
Sie haben bestimmt dieselbe Funktionalität in Bezug auf dein Programm. Ehrlich gesagt, kenne ich BlueJ nicht, aber ich gehe davon aus, dass es nicht viel anders ist als bei anderen IDEs.
Die BlueJ Konsole ist doch bestimmt Bestandteil von BlueJ, die kannst du nicht einfach "mitnehmen". Aber wenn du es mit einer Bat-Datei in der Windows Konsole öffnest, gehen alle Input/Outputs über die Konsole, so wie vorher bei BlueJ.

Hm,
in der cmd steht jetzt da:
C:\Users\EigeneDateien>
ich hab in eigene Dateien meine tictactoe.jar reinspeichert
jetzt müsste ich doch nur noch eingeben
"C:\User\EigeneDateien>" java -jar tictactoe.jar
Hier kommt dann aber:
"Der Befehl "java" ist entweder falsch geschrieben oder konnte nicht gefunden werden"

Was mache ich denn falsch? :autsch:
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
PrograJan Poker Spiel ruückfrage Java Basics - Anfänger-Themen 8
N Hey Leute und zwar versuche ich gerade ein 2D Spiel zu Programmieren aber die Figur will sich nicht nach links oder rechts bewegen :( Java Basics - Anfänger-Themen 12
I Threads Spiel gol Java Basics - Anfänger-Themen 6
N Java Spiel Figur auf dem Hintergrundbild bewegen. Java Basics - Anfänger-Themen 11
J ArrayList vergleichen im spiel Mastermind Java Basics - Anfänger-Themen 2
enesss tictactoe spiel Java Basics - Anfänger-Themen 5
K Java Lotto Spiel; ich komme nicht weiter Java Basics - Anfänger-Themen 15
Jxhnny.lpz TicTacToe Spiel vs Computer. (Probleme) Java Basics - Anfänger-Themen 7
httprt Probleme bei dem erstellen von leveln in meinem Spiel Java Basics - Anfänger-Themen 2
berserkerdq2 Habe ein Spiel entwickelt, dass immer in der 4 Runde einen cast-Fehler erhält Java Basics - Anfänger-Themen 3
berserkerdq2 Spiel hängt sich immer in der 4 Runde auf, obwohl ich jede Runde das gleiche mache Java Basics - Anfänger-Themen 1
Ekooekoo Hilfe spiel Java Basics - Anfänger-Themen 5
sserio Schwimmen als Spiel. Problem mit to String/ generate a card Java Basics - Anfänger-Themen 4
Kennewick Basketball Spiel Ergebnisse Java Basics - Anfänger-Themen 11
X Erste Schritte Hilfe bei einem kleinen Spiel. Java Basics - Anfänger-Themen 19
D Snake-Spiel ähnliche Aufgabe Hilfe Java Basics - Anfänger-Themen 3
R Hangman-Spiel-zufälliges Wort ermitteln Java Basics - Anfänger-Themen 4
JEP1 Java Dialog Fenster schließen Spiel Java Basics - Anfänger-Themen 0
I Simples Risiko-Spiel Java Basics - Anfänger-Themen 5
Hallolu Pong-Spiel: Schläger schneller werden lassen Java Basics - Anfänger-Themen 9
M Java Spiel wie Wer wird Millionär Java Basics - Anfänger-Themen 1
T Startbildschirm für ein Spiel erstellen Java Basics - Anfänger-Themen 0
Z Kein überprüfen des gesamten Arrays möglich.(Viergewinnt Spiel) Java Basics - Anfänger-Themen 6
G Ufo Spiel programmieren Java Basics - Anfänger-Themen 13
C Java Spiel Java Basics - Anfänger-Themen 3
J Spiel programmieren Java Basics - Anfänger-Themen 16
S Spiel-Programmieren. Wenn ein Objekt den anderen berührt. Java Basics - Anfänger-Themen 6
B Memory Spiel Java Basics - Anfänger-Themen 29
J Memory-Spiel Aktivierung der Methode mit Timer Java Basics - Anfänger-Themen 44
Kamy Ein einfaches "Vier Gewinnt" Spiel für Anfängerin Java Basics - Anfänger-Themen 51
A Breakout-Spiel , Ball mit Platten abprallen lassen Java Basics - Anfänger-Themen 1
S Spiel programmieren mit Java Java Basics - Anfänger-Themen 11
Olis Erste Schritte Simples Memory Spiel möglich? Java Basics - Anfänger-Themen 1
J Spiel mit Button klick starten Java Basics - Anfänger-Themen 9
C Rekursives Backtracking beim Spiel Peg Java Basics - Anfänger-Themen 22
M Spiel programmieren Java Basics - Anfänger-Themen 16
Spencer Reid Feedback zu kleinem Spiel Java Basics - Anfänger-Themen 4
kokojamboo92 Spiel programmieren Java Basics - Anfänger-Themen 1
R Kleines Java Spiel funktioniert nicht. Java Basics - Anfänger-Themen 2
I Spiel Java Basics - Anfänger-Themen 34
H ein einfaches Tic Tac Toe Spiel Java Basics - Anfänger-Themen 1
I Spiel programmieren. Java Basics - Anfänger-Themen 16
B Hilfe bei Escape - Spiel Java Basics - Anfänger-Themen 6
S Java-Spiel Java Basics - Anfänger-Themen 2
M Nim-Spiel geht in den negativen Bereich Java Basics - Anfänger-Themen 1
K Klassen Registrierungsseite für ein Spiel Java Basics - Anfänger-Themen 6
J Programmierung Quiz Spiel Java Basics - Anfänger-Themen 3
J Programmierung Quiz Spiel Java Basics - Anfänger-Themen 2
M Brauche Tipps für ein Spiel Java Basics - Anfänger-Themen 4
S Probleme mit GamGrid Spiel-Erstellung => Actor reagiert nicht auf Tastatur Java Basics - Anfänger-Themen 2
Mxxxt Mosaik Spiel - Steuerpanel wird nicht angezeigt Java Basics - Anfänger-Themen 5
M Erste Schritte Zufallszahl Spiel Problem Java Basics - Anfänger-Themen 7
Z Erste Schritte Kleines 2D. Spiel Objekt Bewegung funktioniert nicht Java Basics - Anfänger-Themen 2
H Spiel Kniffel: Gesamtes Array untersuchen. Java Basics - Anfänger-Themen 15
Tacofan Hangman als fertiges Spiel Java Basics - Anfänger-Themen 7
M Array und Objektorientierung? - TicTacToe Spiel Java Basics - Anfänger-Themen 43
C Klassen Sudoku-Spiel Werte werden nicht gesetzt Java Basics - Anfänger-Themen 4
K Kleines Spiel auf Java programmieren Java Basics - Anfänger-Themen 2
W Tic Tac Toe Spiel ohne Arrays Java Basics - Anfänger-Themen 7
S Im objektorientiertem "Spiel" kämpfen Java Basics - Anfänger-Themen 3
I Klassen Umsetzungsfrage zu Spiel "Zuul" Java Basics - Anfänger-Themen 3
F Mastermind Spiel Java Basics - Anfänger-Themen 9
H Liste ausgeben (Spiel Hey Fisch (software-challenge) ändern Anzahl Fische) Java Basics - Anfänger-Themen 1
F Game-Engine für textbasierendes Spiel: Architektur? Java Basics - Anfänger-Themen 9
K Erste Schritte Frage Antwort Spiel - Fragen zur Planung Java Basics - Anfänger-Themen 2
J Java Spiel Zufallsauswahl für Zugbeginn Java Basics - Anfänger-Themen 3
J Frage Antwort Spiel - Wie Zeitcountdown realisieren? Java Basics - Anfänger-Themen 2
L Erste Schritte Spiel: Glückliches Sieben Java Basics - Anfänger-Themen 3
T Hangman spiel Java Basics - Anfänger-Themen 5
J 2 Pc's - Spiel gegeneinander ?! Java Basics - Anfänger-Themen 3
V Spiel Programmieren Java Basics - Anfänger-Themen 9
P 2D-Spiel und Bildschirmgröße Java Basics - Anfänger-Themen 2
O Methoden Fehlermeldung(Illegal start of expression) bei 4-Gewinnt-Spiel Java Basics - Anfänger-Themen 5
T Blöcke für ein Jump and Run Spiel Java Basics - Anfänger-Themen 8
S 2D-Spiel mit Threads... Java Basics - Anfänger-Themen 3
S 2D-Spiel im Vollbild an größe anpassen? Java Basics - Anfänger-Themen 3
M hangman spiel Java Basics - Anfänger-Themen 1
K JTextField in ein Spiel einfügen Java Basics - Anfänger-Themen 2
S Mosaik Spiel Java Basics - Anfänger-Themen 19
pinar memory spiel Java Basics - Anfänger-Themen 10
T OOP Mein erstes Java-Spiel - Schiffe versenken! Java Basics - Anfänger-Themen 2
K Erste Schritte Wie mache ich weiter? (Spiel-Menü) Java Basics - Anfänger-Themen 9
C Java Applet in html. Pong - old school Spiel Java Basics - Anfänger-Themen 10
J Variablen Invalid Character - Error -> Spiel mit Variablenergebnissen Java Basics - Anfänger-Themen 8
K Schere Stein Papier Spiel Java Basics - Anfänger-Themen 3
A Feedback zum Spiel Java Basics - Anfänger-Themen 5
F Hilfe bei meinem Spiel Java Basics - Anfänger-Themen 3
C Lotto Spiel Java Basics - Anfänger-Themen 23
Jagson Dotcom Spiel - Dots Random setzen Java Basics - Anfänger-Themen 8
Dogge Farben-Spiel Java Basics - Anfänger-Themen 20
K Diverse Bugs in einem Snake Spiel Java Basics - Anfänger-Themen 4
2 Lotto-Spiel Java Basics - Anfänger-Themen 9
X Datentypen Probleme mit Char bei meinem 1. Spiel Java Basics - Anfänger-Themen 20
D Erste Schritte Einstieg in die Java Spiel Programmierung Java Basics - Anfänger-Themen 7
H kleines Spiel [Processing] Java Basics - Anfänger-Themen 7
P NullPointerException in Memory-Spiel Java Basics - Anfänger-Themen 5
R Server/Client für Spiel Java Basics - Anfänger-Themen 2
K Hilfe, komme nicht weiter in meinem JAVA-Spiel Java Basics - Anfänger-Themen 3
J Programm(Spiel) neustarten Java Basics - Anfänger-Themen 8
M Suche Beispiel-Spiel Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben