Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Frage dazu Variablen klassenübergreifend zu verändern
Hallo,
ich arbeite momentan an einem Projekt, bei welchem ich einen char in unterschiedlichen Klassen verwende und sobald er sich in einer Klasse ändert, sollte er sich auch in allen anderen Klassen ändern, jedoch tut er das nicht, obwohl ich mit static arbeite.
Code bitte immer in Code-Tags setzen, damit das lesbar wird: Die drei Punkte neben dem Smiley - Code - Java
Du kannst deinen Beitrag auch bearbeiten.
Beschreibe mal was du erreichen möchtest.
static bei einem Attribut bewirkt, dass sich alle Instanzen dieser Klasse das Attribut sozusagen teilen:
Java:
class Foo {
static int value;
}
Foo f1 = new Foo();
f1.value = 11; // value von f1.value ist jetzt 11
Foo f2 = new Foo();
f2.value = 42; // value von f1.value UND f2.value ist jetzt 42
Ich nehme allerdings an, dass das nicht ist, was du willst.
Wenn du eine Variable `a` auf den Wert einer anderen Variablen `b` setzt, dann propagiert sich eine Änderungen der anderen Variable `b` nicht automatisch zu `a`.
Eine Möglichkeit wäre (wie oben schon gesagt), Observer. Oder du referenzierst eben überall nur die eine (und nur die eine) Variable.
Eventuell solltest du das Programmdesign noch einmal überdenken, so dass das gar nicht notwendig ist. Aber dazu wissen wir zuwenig, um hier eine gute Lösung anbieten zu können.
Evtl. kannst du ja grob beschreiben, welche Klassen wie miteinander interagieren?
habe kein allzu großes Wissen über das, was ich hier mache, deswegen, tut mir leid, wenn das ein wenig... unprofessionell wird. Ich gebe mein Bestes.
Ich habe 9 Klassen, die jeweils ein Feld dessen steuern, was ich programmieren möchte. Diese sind sehr identisch aufgebaut, und nun muss ich sie für die nächsten Schritte mehr miteinander interagieren lassen.
Dazu habe ich eine Klasse, die das Grafische Interface steuert und eine, die Methoden für die 9 bereits erwähnten Klassen beinhaltet.
Und zuguterletzt nur noch eine Start Klasse (main), die... das Programm startet
Hallo,
ich arbeite momentan an einem Projekt, bei welchem ich einen char in unterschiedlichen Klassen verwende und sobald er sich in einer Klasse ändert, sollte er sich auch in allen anderen Klassen ändern, jedoch tut er das nicht, obwohl ich mit static arbeite.
Du meinst eine globale klassenübergreifende Variable? Im Allgemeinen sollte man so einen Programm Stil vermeiden (Kapselung Daten, Objekt orientiert .. ) . Wenn man das aber so haben möchte empfiehlt es sich ein Klasse für diese globalen Variablen zu benutzten. Die Klasse sollte mit ihrem Namen darauf hinweisen und die jeweilige globale Variable sollte mit einer Bemerkung zu Ihrem Zweck versehen sein und einen sprechenden Namen besitzen.
Java:
public class GLOBAL{
public static char namederZweckBeschreibt = ' '; // Bemerkung der den Grund der Varibale beschreibt
..
}
Ok, etwas allgeimeiner:
als ein schulisches Projekt arbeite ich an einem großen Tic Tac Toe (nicht das klassische, ich weiß nicht, ob ihr das kennt).
Anhand von Anleitungen habe ich das Grunggerüst für ein normales Tic Tac Toe Spiel programmiert und möchte dieses nun zu der großen Version ausbauen.
Dazu habe ich 9 klassische Tic Tac Toe Felder, die alle wunderbar funktionieren (die 9 Klassen), jedoch muss ich diese jetzt miteinander verlinken.
hilft das? Soll ich das System des Spieles beschreiben?
9 3x3 Felder, man beginnt in der Mitte.
Wenn sein Symbol in das Feld links oben gemacht worden ist, so setzt der andere Spieler sein Symbol in das 3x3 Feld links oben. Je nachdem, wo dieser sein Symbol setzt, wandert man zum nächsten 3x3 Feld und so weiter.
Ziel ist es, drei Feld, in denen man gewonnen hat, senkrecht, waagerecht oder diagonal zu haben.
Verständlich?
Warum müssen deshalb Spielfelder direkt miteinander interagieren?
Es geht doch im Prinzip nur darum, welches Spielfeld als nächstes aktiv ist und das erfährst du vom letzen aktiven Spielfeld, nachdem der Zug passiert ist. Mit der Info kannst du dann das nächste erlaubte Spielfeld aktivieren.
Den aktiven Spieler kennst du auch, dazu ist keine Aktion mit dem Spielfeld notwendig.
bisher wurde der aktive Spieler automatisch nach einem Spielzug gewechselt, das Problem ist, dass jedes Feld seinen eigenen aktiven Spieler hat.
Das heißt, wenn ich in ein Feld X setzte, wird in das nächste Feld beim nächsten Zug auch ein X gesetzt, da der aktive Spieler nicht bei allen Felder geändert wird, sondern nur im aktuellen 3x3 Feld
Das Problem ist, dass es genau so nicht ist, denn es gibt nur einen Spieler der gerade aktiv ist.
Das Spielfeld enthält normalerweise nur die 3x3 Matrix mit dem Inhalten: frei, X oder O. Genau diese Informationen braucht auch die GUI, um das Spielfeld zu zeichnen. Außerdem etwas Logik, damit auf ein Feld nur einmal gesetzt werden kann, usw.
Entweder sollte das Spielfeld den Spieler gar nicht kennen sondern nur Methoden haben wie setX(position), setO(position) oder set(position, X).
Oder du übergibst den aktiven Spieler für den Zug an das Spielfeld set(position, player).
Der Spielerwechsel erfolgt außerhalb des Spielfelds.
ja, danke. Hab langsam mehr Durchblick, bei dem, was ich mache. Bin, wie gesagt, mit allem noch recht neu.
Weiß aber jetzt, wie ich die Sachen angehen sollte. Danke für die Unterstützung. Probiere jetzt noch ein wenig weiter rum. Bei weiteren Fragen bin ich wieder hier.
Nochmals vielen Dank.
Ich habe 9 Klassen, die jeweils ein Feld dessen steuern, was ich programmieren möchte. Diese sind sehr identisch aufgebaut, und nun muss ich sie für die nächsten Schritte mehr miteinander interagieren lassen.
Also kurz dazu: Entweder es ist einfach nur eine falsche Verwendung vom Wort Klassen und du meinst, dass Du 9 Instanzen der Klasse "Feld" hast - oder da läuft vom Design her komplett etwas falsch!
Du beschreibst einmal, was etwas ausmacht. Also was macht einen Mitarbeiter aus? Name, Gehalt, Adresse, Steuerklasse, Abteilung, ....
==> Eine Klasse für alle Mitarbeiter. Man macht nicht für jeden Mitarbeiter eine eigene Klasse!
Da wäre also interessant zu wissen, was Du wie gemacht hast.
Was fällt da alles auf:
a) Egal ob Gewinner[X|O]() wahr ist - die Variable seSpieler wird so oder so gesetzt. Daher ist da kein if/else notwendig.
b) Code vereinfachen: Wenn man die äußere if/else Bedingung ansieht, dann erkennt man, dass gewisse Dinge dazu führen, dass nichts zu tun ist:
Wenn !felder[nr].isEmpty() dann wird nichts gemacht. Das ist also ein Fall für eine Validierung. Ebenso wenn !active gilt.
Somit kann man direkt am Anfang eine Validierung durchführen und der Code wird etwas übersichtlicher:
Java:
public void spielzug (int nr) {
if (!felder[nr].isEmpty()) return; // isEmpty wäre die richtige Schreibweise -> camel case!
if (!active) return;
if (seSpieler == 'x') {
felder[nr].setX();
if (GewinnerX() ) {
seSpieler = 'o';
} else {
seSpieler = 'o';
if (computer) {
computerzug();
}
}
} else { // Es gibt nur zwei Spieler, also entweder ist es 'x' oder 'o'! -> evtl. macht hier auch ein boolean Wert Sinn?
felder[nr].setO();
System.out.println(derSpieler.getaktiverspieler());
if (GewinnerO() ) {
seSpieler = 'x';
} else {
seSpieler = 'x';
}
}
}
c) Da sind zwei Blöcke, die fast identisch sind.... Es gibt jetzt keine Information, aber setX und setO dürften ebenfalls fast identisch sein. Daraus kann man dann bestimmt ein set(Spieler) machen. Dann wäre also nur ein felder[nr].set(seSpieler); in beiden Blöcken.
Ebenso dürfte GewinnerX / GewinnerO vermutlich fast identisch sein. Also macht wohl eine Methode hatGewonnen(Spieler) Sinn. (==> Name auch korregiert!)
Als vorletztes bleibt da noch ein Umsetzen des Spielers. Das wäre dann ein setzNaechstenSpieler() Aufruf -> dann kann man klar erkennen, was da geschieht.
Dann bleibt doch tatsächlich noch der computerzug: da kann die Validierung evtl. im computerzug liegen, aber von mir aus behält man das dann auch bei. Dann hätte man jetzt:
Nun bleibt nur noch die Logik: Es wird ja ein Zug durchgeführt. Was gehört denn da rein? Doch eigentlich nur eigentliche durchführen des Spielzuges. Schon das prüfen, ob der Zug zu einem Sieg geführt hat, ist eigentlich etwas anderes. Daher wäre der Code der Methode nach dem felder[nr].set Aufruf für mich eigentlich schon vorbei. Aber wir lassen es mal drin.
Java:
public void spielzugDurchfuehren (int nr) {
if (!felder[nr].isEmpty()) return; // isEmpty wäre die richtige Schreibweise -> camel case!
if (!active) return;
felder[nr].set(seSpieler);
if (hatGewonnen(seSpieler) ) {
// Hier ist das Spiel dann ja vorbei - es muss nichts weiter gemacht werden ... kein Computerzug und so!
// Also was auch immer getan werden soll muss dann hier hin.
return;
}
setzNaechstenSpieler();
if (seSpieler == 'x' && computer) {
computerzugDurchführen();
}
}
Da hat man schon eine deutlich kleinere, übersichtlichere Methode. Die Prüfung auf den Spieler und dass es ein Computer Spieler sein kann, zeugt aber aus meiner Sicht davon, dass es eine Klasse Spieler geben sollte. Dann wäre da eine einfache Prüfung auf seSpieler.istComputer() oder so am Ende durchzuführen.
Das ist alles nur eine kleine Übersicht, wie man etwas strukturieren kann. Die ersten wichtigen Punkte sind aus meiner Sicht:
a) Benenne alles Richtig! Methoden enthalten immer ein Verb und beschreiben, was sie machen!
b) Und dann machen Methoden auch nur genau das! Also wenn da steht: spielzugDurchführen, dann wird nur der Spielzug durchgeführt und danach nicht noch ein Gewinner geprüft. Und wenn ein Zug ausgeführt wird, dann findet da auf keinen Fall noch ein weiterer Zug statt! Das sind sonst Verhalten, die man beim Lesen des Codes nicht sieht. Code soll wirklich lesbar sein!
Ein aktiverSpieler.istComputer() ist deutlich einfacher zu verstehen, als irgendwelche Vergleiche...
c) Versuch doppelten Code zu vermeiden. Wenn Methoden sich nur durch eine Literal unterscheiden (setX & setO werden wohl dem Feld einfach ein 'x' oder 'o' zuweisen und ansonsten identisch sein, oder?), dann macht man daraus eine Methode und der Unterschied kommt als Parameter.
Das einfach nur einmal als Anregung und Hinweise. Ich weiss, dass ich damit schon recht weit vorgreife, aber das liegt mit daran, dass wohl die Aufgabe für Deinen aktuellen Wissensstand etwas komplex ist. Das kann durchaus in Ordnung sein, aber es bringt etwas mehr Komplexität mit rein, wie man hier erkennt. Aber es ist evtl. eine tolle Gelegenheit, dann auch gleich diese Aspekte mit zu lernen.