Java: Methode wird sehr wahrscheinlich nicht aufgerufen?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Du gehst in karteout in eine Endlosschleife. Die Elemente des Array cards werden alle mit dem Wert 0 initialisiert und nicht noch einmal neu gesetzt (das sollte wohl eigentlich die kartendeck-Methode regeln). Folglich ist die Bedingung

if (cards[karte] != 0) {

immer unwahr und die Schleife wird nie enden.

In diesem Zug möchte ich gleich noch auf ein paar andere Punkte eingehen, die definitiv verbesserungswürdig wären.

1) Die Namen deiner Symbole sind ein wilder Mix aus Deutsch und Englisch. Lege dich besser auf nur eine Sprache fest.

Gib deinen Variablen zudem immer passende und aussagekräftige Namen. Exemplare wie counter1, pturn oder zs1 sind in der Hinsicht Negativbeispiele.

Bei zusammgensetzten Wörtern (wie cardid) hilft die Kamelhöckerschreibweise, den Namen einfacher lesbar zu machen: cardId. Zwischen Termen und Operatoren wiederum sollte ein Leerzeichen gesetzt werden, sodass sie leichter auseinandergehalten werden können (Beispiel: zs1 % 100).

Auch die Namen deiner Methoden solltest du überdenken. Methoden stellen ein Verhalten dar bzw. führen eine Aktion aus, weshalb sich Verben (oder Imperativsätze) für ihre Benennung besser eignen. Für die Methode player könnte man bspw. draw oder play als Namen vergeben.

2) Ich kann nicht nachvollziehen, wieso du Labels verwendest. In karteout erfüllt das Label beispielsweise keinerlei Funktion. Belasse es bei dem break und der Code wird genauso ausgeführt.

In player hast du dir die nächste Endlosschleife gebaut. Wenn die Nutzereingabe weder Hit noch Stay war, wird eine Fehlermeldung ausgegeben und die innere Schleife startet erneut. Der Nutzer hat zwischendurch keine Gelegenheit, eine neue Eingabe zu tätigen. Stattdessen wird stets die alte Eingabe geprüft.

Belasse es stattdessen bei einer Schleife. Da sie stets mindestens einmal laufen soll, passt do-while ganz gut:

do {
  System.out.println("Was möchtest du machen?");
  System.out.println("--> Hit");
  System.out.println("--> Stay");

  userinput = scan.nextLine();

  if (userinput.equals("Hit")) {
    karten.karteout();
  }
  else if (userinput.equals("Stay")) {
    break;
  }
  else {
    System.out.println("Diese Funktion ist nicht verfügbar!");
  }
}
while (userinput.equals("Hit"));

Labels sind an sich dazu gedacht, einfacher aus geschachtelten Schleifen (oder einer Schachtelung von Schleife und switch) auszubrechen, wobei man in so einem Fall auch überlegen sollte, ob es nicht auch durch eine Aufteilung lösbar ist (die innere Struktur wird in eine Hilfsfunktion mit Rückgabewert ausgelagert), die zudem Lesbarkeit des Codes verbessert.

An anderer Stelle sollten Labels nie notwendig sein.

3) Dein if-else if-Konstrukt für den ersten Ausgabenteil kann leicht verkürzt werden. Die Berechnung des Prüfwerts sollte auf jeden Fall nur an einer Codestelle erfolgen (weniger Redundanz = weniger potentielle Fehlerquellen).

int cardId = zs1 % 100;

if (cardId == 1) {
  System.out.print("Ace ");
}
else if (cardId > 1 && cardId < 11) {
  System.out.print(cardId + " ");
}
/* further cases 11, 12, 13 ... */
else {
  return;
}

Wenn dieser erste Ausgabeteil bereits auf keinen der vorrangigen Fälle zutrifft, kannst du die Methode an der Stelle auch direkt verlassen. Einen zweiten Ausgabeteil wird es dann ja nicht geben (bzw. er wäre auch nicht erwünscht).

4) Überlege dir bezüglich deiner Felder nochmals, ob sie wirklich notwendig sind (also ihr Zustand immer wieder innerhalb der Methoden der Klasse verwendet wird) oder ob sie nicht durch lokale Variablen ersetzt werden können.

So wie ich das sehe, hat nur cards eine Daseinsberechtigung als Feld. Die Werte aller anderen Felder werden in den jeweiligen Methoden direkt wieder überschrieben und nicht übergreifend in Methoden gelesen.

5) Die kartendeck-Methode dient offensichtlich der Initialisierung des cards-Feldes. Insofern wäre es besser, sie z.B. setup zu benennen (bzgl. der Bezeichner würde ich mich also durchgehend auf Englisch festlegen) und im Konstruktor aufzurufen.

public class CardDeck {
  public CardDeck() {
    setup();
  }

  /* ... */

  private void setup() {
    /* ... */
  }
}

6) Innerhalb der Schleife (kartendeck-Methode) sind die De-/Inkrement-Operationen überflüssig. Entweder du addierst die 1 einfach innerhalb der Formel auf die Variable auf:

100 * (i + 1) + (j + 1)

oder (besser) du änderst einfach den Zählerbereich der Schleifen:

int index = -1;

for (int i = 1; i <= 4; ++i) {
  for (int j = 1; j <= 13; ++j) {
    int cardId = 100 * i + j;
    cards[++index] = cardid;
  }
}
SRWa0676 
Fragesteller
 12.04.2024, 18:28

Danke für die Tipps. Ich werde versuchen sie in das Programm zu implementieren, aber da ich erst seit Februar dieses Jahres code, werde ich auch die "unschönen" Code-Stellen dabei belassen und mich erst mal auf die Funktionalität des Codes konzentrieren.

0

Ich vermute, der Fehler liegt darin, dass du in der Klasse Player ein zusätzliches Kartendeck initialisierst (zusätzlich zu dem in der Main-Klasse), aber die Funktion Kartendeck.kartendeck() nicht aufrufst. Der Player verwendet deshalb ein leeres Kartendeck zum Spielen, d.h. er kann auch nichts ziehen.

Ausserdem würde ich dir anraten, dich einmal mit Konstruktoren zu beschäftigen :-). Konstruktoren machen ziemlich genau das, was du mit Kartendeck.kartendeck() machen willst, nur automatisch, d.h. du musst den Konstruktor nicht explizit aufrufen.

Das program ist schon zu kompliziert für hier, verwende einen debugger.

und bitte switch …case aber nicht so eine if else if else if ….struktur

Int foo = zs1%100 == 1

Switch (foo) {

case 1: return “Ace”

case 2: return String.format(“%i”, foo)

case 11: …

}

Erzesel  12.04.2024, 09:14

Warum die ganze Rödelei mit if oder switch? Jeder Vergleich kostet Zeit. Zudem wird der Code mit sinnlosen Text aufgeblasen. Einmal alle Namen in einem Array ablegen , und diesen abrufen.

Pseudocode:

Int foo = zs1%100
String[] cardnames = {"Nope","Ace","2","3","4",....usw...,"King"}; //  array mit allen Namen

//statt 13 alternierender Ifs oder Cases ,ein Zugriff auf das Array :

.println(cardnames[foo])

...soviel zur prozeduralen Verfahrensweise.

Optimal wäre es gleich eine Stuctur/Klasse anzulegen, welche Kartenenfabe/-Name und Wert in einer Variable verinigt....


1