static non-static

anzahlSpieler = Hilfsprogramme.zahlEinlesen(2,6)
[...]
Die Methode zahlEinlesen ist ein sehr gutes Beispiel, da diese wirklich sehr überschaubar ist.

Immer verlangt der compiler, dass ich diese static machen soll, wo liegt da denn der Haken, das verstehe ich nicht.

Wenn mir das mal einer erklären könnte, dann kann ich auch meinen Frieden mit java machen.

Wie soll ich das denn verhindern?
Hier rufst du die Methode über die Klasse auf - sie muss also statisch sein, da du ja kein Objekt der Klasse Hilfsprogramme hast.
Wenn du eine nicht-statische Methode aufrufen willst, brauchst du immer erst ein Objekt, zu welche diese gehört, das hast du in diesem Fall ja nicht.


Wenn die Methode nicht statisch sein soll, musst du erste ein Objekt der Klasse Hilfsprogramme erzeugen new Hilfsprogramme(), und kannst dann auf diesem Objekt die Methode aufrufen.
 
Ahh. Danke,

ALLE meine Konstruktoren sind normale Methoden. JEtzt wird es klarer!!!!
Wie gesagt, haben wir Montag gemacht und da lag ich mit operiertem KReuzband im Bett, Danke!

VIELEN Dank!
Norman
 
Dann ist das mit dem static und non-static auch klar.
Ich habe die Objekte, von denen ich dachte, ich hätte sie erzeugt nie erzeugt!
OK!
Jetzt muss ich allerdings die Karten und Stapel anders erzeugen, in den jeweiligen Klassen, das mache ich Morgen.
Vielen Dank!
Jetzt schlafe ich besser!
Norman
 
Also, bei
anzahlSpieler = Hilfsprogramme.zahlEinlesen(2,6)
beschwert sich der compiler, "can'T make a static reference ..........."
Hast du dir denn das Beispiel aus #38 angesehen? Und verstanden? Oder nachgefragt, falls etwas daran nicht verstanden wurde?

Wenn du bei Hilfsprogramme.zahlEinlesen(2,6) die Java-Konventionen einhältst, dann scheint "Hilfsprogramme" eine Klasse zu sein. Da der Aufruf der Methode "zahlEinlesen()" direkt auf der Klasse erfolgt, müsste sie statisch sein. Ansonsten probier doch mal:

Java:
// erzeuge eine Instanz der Klasse Hilfsprogramme
Hilfsprogramme hp = new Hilfsprogramme();
// und rufe darauf die Methode auf.
anzahlSpiele = hp.zahlEinlesen(2,6);
Edit: Sorry, ich hab die Antwort von @mrBrown übersehen...
 
Vielen Dank!

Wie gesagt, meine Konstruktoren waren nur MEthoden. Dass ich zahlEinlesen non-static gemacht habe war nur ein Nebenfehler.
Aber jetzt fällt mir alles wie Schuppen von den Auugen!

Vielen Dank!

Gruß
Norman
 
Ok, weiter.

Ich habe jetzt eine Klasse Blatt (das mit dem Enum mache ich dann darein) mit dem Konstruktor Blatt.

Javascript:
public class Blatt extends Stapel  {
    private int anzahl;
    private  Karte [] karten = new Karte  [32];
    private final String [] farben = {"Kreuz", "Pik", "Herz","Karo"};
    private final String [] werte = {"7", "8", "9", "10", "Bube", "Dame", "König", "As"};
    
    public Blatt () {
        super(32);
        this.anzahl = 32;
        karten = new Karte [32];
        int k = 0;
        for (int i =0; i<4; i++) {
            for (int j=0; j < 8; j++) {
                karten[k] = new Karte(farben[i],werte[j]);
                //karten[k].zeigen();
            }
       
        }
    }

}
 }
Die Karten werden auch alle erzeugt. (Das habe ich überprüft und mir alle ausdrucken lassen, siehe auskommentiete Zeile)
In der Klasse Konfiguration gibt es den Konstruktor Konfiguration, der mir alles für das Spiel notwendige erzeugt.
Da wird aber Blatt nicht hinübergeben. Alle Einträge von Blatt sind hier leer.

Hmmm?

Wo liegt dass denn jetzt dran?
Grüße
Norman
 
Hier der Konfigurator:
Javascript:
public  Konfiguration (int anzahlSpieler){
        this.anzahlSpieler= anzahlSpieler;
        this.gewinner = -1;
        Blatt blatt = new Blatt();
        blatt.zeigeKarten();
        //Damit genug Karten zum Spielen da sind, wird jetzt berechnet, wie viele Karten jeder bekommen soll.
        int z =(int) Math.floor(32/(anzahlSpieler+2));
        anzahlStarthandKarten = 6;//Math.min(6,z);
        spielerrunde = new Spieler [ anzahlSpieler];
        for (int i = 0 ;i< anzahlSpieler ; i++) {
            this.spielerrunde [i]  = new Spieler (anzahlStarthandKarten, blatt);
        }
        this.nachZiehStapel = blatt;
        Stapel ablageStapel = new Stapel (32);
        ablageStapel.karteHinzufügen(nachZiehStapel.getObersteKarte ());
    }
 
Aber Blatt ist doch ein Stapel?
Wie sieht denn Stapel aus?

Edit:

Ich bin jetzt nicht 100% auf dem Laufenden, was Begriffe aus dem Kartenspiel angeht, aber ich würde mal raten:

Ein Stapel ist eine Art Kartensammlung, die erst mal leer ist und auf die man Karten legen und wieder entnehmen kann?

Das Blatt wäre insofern ein Stapel, der bereits mit allen Karten gefüllt (gemischt) ist, die man dann entnehmen kann?

Ich kenne aber Blatt ("Was hast du für ein Blatt?") auch als Begriff für die Karten, die man auf der Hand hat (was aber dann auch "Hand" sein könnte).

Es ist schon sehr wichtig, dass man vorher die Begriffe klärt, damit wir sie nicht unterschiedlich verwenden.
 
Die Karten werden auch alle erzeugt. (Das habe ich überprüft und mir alle ausdrucken lassen, siehe auskommentiete Zeile)
In der Klasse Konfiguration gibt es den Konstruktor Konfiguration, der mir alles für das Spiel notwendige erzeugt.
Da wird aber Blatt nicht hinübergeben. Alle Einträge von Blatt sind hier leer.

Hmmm?

Wo liegt dass denn jetzt dran?
Das liegt daran, dass Du Batt von Stapel ableitest, in Blatt aber erneut ein Array karten[] deklarierst. Das Array karten[] in Klasse Blatt ist somit ein anderes als das Array karten in Klasse Stapel. Du könntest das Array in Blatt genauso gut xyz nennen, das hätte den gleichen Effekt, wäre nur deutlicher :)

Mal in kurz:
Java:
public class Basis {
    private int x;

    public void zeige() {
        System.out.println(x); // zeigt den Wert des in Basis deklarierten x
    }   
}

public class Erweitert extends Basis {
    private int x;

    public Erweitert() {
        this.x = 5;
    }
}
Wenn Du jetzt
Java:
Erweitert e = new Erweitert();
e.zeige();
aufrufst, dann wird dir 0 ausgegeben; der Grund ist oben im Kommentar angegeben.

So etwas löst man dadurch, dass man entsprechende Konstruktoren oder Methoden verwenden:
Java:
public class Basis {
    private int x;

    public Basis() {}
    public Basis(int x) { this.x = x; }
    protected final void setX(int x) { this.x = x; }

    public void zeige() {
        System.out.println(x); // zeigt den Wert des in Basis deklarierten x
    }   
}

public class Erweitert extends Basis {
    public Erweitert() {} // ruft implizit super() auf
    public Erweitert(int x) { super(x); } // setzt x über den Konstruktor der Basisklasse

    public void reset() { setX(4); } // setzt x über die Methode setX
}
Jetzt kannst Du z. B. folgendes machen
Java:
Erweitert e1 = new Erweitert();
Erweitert e2 = new Erweitert(100);
e1.zeige(); // liefert 0
e1.reset();
e1.zeige(); // liefert 4
e2.zeige(); // liefert 100
Nachtrag: das war jetzt nur die technische Erklärung. Die Sinnhaftigkeit, Blatt von Stapel abzuleiten, ist ein ganz anderes Thema.
 
Die Begriffe sind nicht ganz eindeutig.

Deck = Kartendeck = alle Karten
Stack = Kartenstapel (= Kartendeck) = alle Karten, eine Teilmenge oder eine Hand...
Hand = alle Einzelkarten die ein Spieler aktuell oder anfangs auf der Hand hält
Karte = eine Einzelkarte

andere Begriffe hängen vom Kartenspiel ab

Und ein Blatt bezeichnet meist eine anfängliche Hand
 
Zuletzt bearbeitet:
Ich schlage einfach mal folgende Struktur vor:
Java:
public class Player{
    private final String name;
    private ArrayList<Card> cards;
    
    Player(String name){
        this.name = name;
    }
    public String getName(){return name;}
    
    void setHand(ArrayList<Card> hand){
        cards = hand;
    }
}

public enum Number{ SIEBEN, ACHT, NEUN, ZEHN, BUBE, ...}
public enum Color{HERZ, KARO, PIK, KREUZ}

public class Card{
    public final Number number; //Achtung, Ausnahme, Instanzvariablen sollten normalerweise privat sein.
    public final Color color;
    Card(Number number, Color color){
        this.number = number;
        this.color = color;
    }
}

public class Game{
    ArrayList<Player> players;
    ArrayList<Card> cardsdeck;
    private Player activePlayer;
    
    public Game(int hand, String... playernames){
        //Kartendeck generieren
        cardsdeck = new ArrayList<>();
        for(Color color : Color.values()){
            for(Number number : Number.values()){
                cardsdeck.add(new Card(number, color));
            }
        }
        
        //Spieler generieren
        players = new ArrayList<>();
        for(String playername : playernames){
            players.add(new Player(playername));
        }
        
        //Allen Spielern ein Blatt in die Hand geben
        for(Player player : players){
            ArrayList<Card> newhand = new ArrayList<>();
            for(int i = 0; i < hand; i++){
                int cardindex;
                //cardindex einen zufälligen Wert zuweisen, der zwischen einschl. 0 und  ausschl. cardsdeck.size() liegt
                newhand.add(cardsdeck.remove(cardindex));
            }
            player.setHand(newhand);
        }
    }
    
    //Einige Beispielmethoden, die für das Spiel benötigt werden,
    //evt. müssen dazu noch ein paar Instanzvariablen implementiert werden
    
    //Liefert den Spieler, der gerade am Zug ist
    public Player getActivePlayer(){
        return activePlayer;
    }
    
    //Beendet die Runde des jeweiligen Spielers und markiert den nächsten als activePlayer
    public void endTurn(){
        //...
    }
    
    //...
}

Das ist zwar nicht ganz so kompliziert mit statischen Methoden, und es sind auch weniger Klassen. Dafür bietet dieser Ansatz ein paar andere Vorteile:
  • Einfachheit ist immer erstmal gut, kompliziert wird es im weiteren Verlauf von ganz alleine. Versprochen. ;)
  • Du kannst dich gleich noch mit abstrakten Klassen beschäftigen: Mache aus Game eine abstrakte Klasse, und implementiere dort nur Methoden, die du für alle Spiele brauchst. Leite verschieden Klassen ab, und implementiere in jeder dieser abgeleiteten Klassen andere Spielregeln.
  • Du kannst beliebig viele Spiele parallel spielen: einfach ein neues Game instanziieren.
Wie gesagt, ist nur ein Vorschlag, aber vielleicht gibt dir das eine Inspiration.
 
Meine main Klasse hat nur 4 Zeilen oder so, ist also schon sehr kurz.

Für Basis einen eigenen Konstruktor zu schreiben war ein Vorschlag von hier und finde ich mittlerweile auch ganz gut. Weil dann beim Aufruf vom Stapel blatt das gesamte Blatt direkt erzeugt wird. Das finde ich eleganter als die Lösung über ein Spezialfall von Stapel.
Im Konfigurator von Stapel holt sich dieser dann die Karten von Blatt "immer von oben" wie im echten Spiel.
OK, wenn Blatt keine ERWEITERUNG von Stapel ist und ich somit kein extends benötige , woher weiß der Konstruktor überhaupt, dass Blatt ein besonderer Stapel ist.
karten[] habe ich in Stapel jetzt auf protected geändert und und kann diese jetzt übernehmen. Wobei dass auch anders geklappt hatte.

Aber Danke!
Vielleicht hängt hier ja doch irgendwie mein Indexproblem, aber ich bin schon ziemlich weit.

Ich will dass das Programm läuft und auch den allgemeinen Ansprüchen genügt, aber 99% reichen, das schaut sich außer euch und dem Übungsleiter eh nie mehr jemand an.
Ob jetzt Deck Deck ist usw. ist mir irgendwann auch egal. Aber der Hinweis stimmt natürlich.

Danke nochmals, ich finde das eine sehr angenehme Diskussion und gute Hilfen.

Grüß
Norman
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben