Frage dazu Variablen klassenübergreifend zu verändern

Josaria

Mitglied
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.

Könnte mir da vielleicht jemand mit helfen?
 
Meinst du unterschiedliche Klassen oder unterschiedliche Instanzen einer Klasse?

Ein wenig Code (minimaler Auszug der relevanten Teile) wäre nicht schlecht.
 
Ein wenig Code (minimaler Auszug der relevanten Teile) wäre nicht schlecht.
[/QUOTE]

public static char aktiverspieler = 'x';

public void spielzug4 (int nr) {
if (aktiverspieler == 'x' && felder4[nr].isempty() && active) {
felder4[nr].setX();
System.out.println(aktiverspieler);
if (GewinnerX4()) {
aktiverspieler = 'o';
}
else {
aktiverspieler = 'o';
}

}
else if (aktiverspieler == 'o' && felder4[nr].isempty() && active) {
felder4[nr].setO();
System.out.println(aktiverspieler);
if (GewinnerO4() ) {
aktiverspieler = 'x';
}
else {
aktiverspieler = 'x';
}
}
}

andere Klasse:

static char seSpieler = Spiel4.aktiverspieler;

public void spielzug (int nr) {
if (seSpieler == 'x' && felder[nr].isempty() && active) {
felder[nr].setX();

if (GewinnerX() ) {
seSpieler = 'o';
}
else {
seSpieler = 'o';
if (computer) {
computerzug();
}
}
}
else if (seSpieler == 'o' && felder[nr].isempty() && active) {
felder[nr].setO();
System.out.println(derSpieler.getaktiverspieler());
if (GewinnerO() ) {
seSpieler = 'x';
}
else {
seSpieler = 'x';
}
}
}

(sorry, bin neu hier und weiß nicht, wie ich den Code richtig anzeigen lasse)
 
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.
 
public static char aktiverspieler = 'x';
andere Klasse:
static char seSpieler = Spiel4.aktiverspieler;
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.
 
danke, erst mal

der aktive Spieler soll nach jedem Spielzug von X auf O oder von O auf X wecheln, auch, wenn der Spielzug in einer anderen Klasse erfolgt ist
 
wiue würde ich ebendiesen genau programmieren?

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
 
habe kein allzu großes Wissen über das, was ich hier mache
Das ist nicht gut...
Ich gebe mein Bestes.
Das ist gut!
Ich habe 9 Klassen, die jeweils ein Feld dessen steuern, was ich programmieren möchte.
Das solltest du etwas näher beschreiben. Ich tappe immer noch im Dunkeln darüber, was du eigentlich vor hast. Geraten: TicTacToe?
eine, die Methoden für die 9 bereits erwähnten Klassen beinhaltet.
Das klingt seltsam, weil die Klassen ja die Methoden haben sollten. Dafür sind es ja Klassen.
Dazu habe ich eine Klasse, die das Grafische Interface steuert
Das wiederum klingt gut.
 
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.

Könnte mir da vielleicht jemand mit helfen?
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
    ..
}
 
Das solltest du etwas näher beschreiben. Ich tappe immer noch im Dunkeln darüber, was du eigentlich vor hast.

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?
 
Das sagt mir leider nichts.
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?

Ein Feld ist ein einzelnes Feld des "3x3 Felds" oder handelt es sich um neun komplette 3x3 Felder?

ja, ein einzelnen 3x3 Feld
 
Je nachdem, wo dieser sein Symbol setzt, wandert man zum nächsten 3x3 Feld und so weiter.
D.h. der Zug des zweiten Spielers bestimmt durch diese Zug in welchem Spielfeld der erste Spieler als nächstes setzen darf?

Setzt er in das Feld rechts unten (des ersten Spielfeldes), dann ist der nächste Zug im Spielfeld ganz rechts unten. Richtig?
 
D.h. der Zug des zweiten Spielers bestimmt durch diese Zug in welchem Spielfeld der erste Spieler als nächstes setzen darf?

Setzt er in das Feld rechts unten (des ersten Spielfeldes), dann ist der nächste Zug im Spielfeld ganz rechts unten. Richtig?


genau, so springt man die ganze Zeit in den Feldern hin und her.
Das Spiel benötigt viel denken/ Planung, macht aber viel Spaß
 
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.
 
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
 
Noch einmal langsam:
  1. Spiel beginnt im mittleren Spielfeld
  2. Spieler 1 setzt dort in das rechte untere Feld.
  3. Spieler 2 ist am Zug, aktives Spielfeld ist rechts unten.
  4. Spieler 2 setzt dort in das untere mittlere Feld.
  5. Spieler 1 ist am Zug, aktives Spielfeld ist mittig unten.
  6. usw.
Die Spieler wechseln also unabhängig vom Feld immer ab, es wird nur immer ein anderes Spielfeld aktiv.

das Problem ist, dass jedes Feld seinen eigenen aktiven Spieler hat.

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.
 
Das Problem ist, dass es genau so nicht ist, denn es gibt nur einen Spieler der gerade aktiv ist.

ja, nein. Das war unglücklich von mir formuliert. So war es. Ich bin mir bewusst, dass ich ändern muss.

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.
 
Und dann evtl. auch ein Hinweis, wie man doppelten Code verhindern kann.

Du hast den folgenden Code gezeigt (Etwas eingerückt und so):
Java:
public void spielzug (int nr) {
  if (seSpieler == 'x' && felder[nr].isempty() && active) {
    felder[nr].setX();

    if (GewinnerX() ) {
      seSpieler = 'o';
    } else {
      seSpieler = 'o';
      if (computer) {
        computerzug();
      }
    }
  } else if (seSpieler == 'o' && felder[nr].isempty() && active) {
    felder[nr].setO();
    System.out.println(derSpieler.getaktiverspieler());
    if (GewinnerO() ) {
      seSpieler = 'x';
    } else {
      seSpieler = 'x';
    }
  }
}

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.
 

Zurück
Oben