Frage dazu Variablen klassenübergreifend zu verändern

Diskutiere Frage dazu Variablen klassenübergreifend zu verändern im Java Basics - Anfänger-Themen Bereich.
J

Josaria

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

JustNobody

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

JustNobody

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.
 
Thema: 

Frage dazu Variablen klassenübergreifend zu verändern

Passende Stellenanzeigen aus deiner Region:
Anzeige

Anzeige

Anzeige
Oben