static non-static

  • Themenstarter NormanPatrickBenner
  • Beginndatum
Diskutiere static non-static im Java Basics - Anfänger-Themen Bereich.
NormanPatrickBenner

NormanPatrickBenner

Hallo allerseits,

nach jahelangem "wildem Programmieren" habe ich jetzt die Gelegenheit, meine KEnntnisse in einer Fortbildung mal auf sicher Beine zu stellen.
Ich schaffe es aber nicht, das folgende Problem zu lösen:

ich habe echt lange gesucht, passendes gefunden, aber das hat mir nicht weitergeholfen (zu doof?)

Ich habe die Klasse Karten und die Klasse Stapel erstellt (Stapel extends Karte)

In Karte gibt es zum Beispiel die Methode:

12405
(Ich habe es zunächst anstatt mit this mit aktuelleKarte probiert und hatte gehofft, das sich das Problem mit this löst, hat es aber nicht.

Jetzt muss ich diese Methode aus Stapel aufrufen

12406
und dann kommt halt der berühmte Anfängerfehler "can-t make a static......

Ich habe versucht, alle MEthoden non-static zu machen, da sie das nach meinem Verständnis ja auch nicht sind (oder?!?!?!?!)
Aber irgendwie muss ich doch übergeben, welche Karte ich zeigen lassen will.

Wer kann mir weiterhelfen?

P.S.: Ich stelle mich jetzt auch in meinem Profil vor.
 
VfL_Freak

VfL_Freak

Moin,

kann man IMHO so schlecht beurteilen, da wior den relevanten Code nicht kennen!
Es kann sicher gute Gründe geben, etwas static zu machen!

Poste mal mehr Infos!

VG Klaus
 
K

kneitzel

Also in der Regel ist es so, dass Du mit Klassen beschreibst, wie Objekte aussehen und sich verhalten. Und dann sprichst Du diese Objekte gezielt an.

Also eine Klasse Karte hat dann von mir aus eine Methode zeige (Karte ist unnötig, denn Du rufst das zeige ja auch einer Karte auf), wobei hier ggf. die Methode toString überschrieben werden sollte....). Und die Karte selbst wird nicht übergeben - auf diese kannst Du dann ja per this zugreifen. Somit hätte man dann ggf. sowas:
Java:
public void zeige() {
    System.out.println("" + farbe + " " + wert);
}
Das "this." kann auch weggelassen werden - es ist klar, dass hier die Instanzvariablen angesprochen werden sollen....

Und wenn Du die Karten in einem Array speicherst in Deinem Kartenstapel, dann kann karten[0] die erste Karte sein. Die Methode kannst du da dann aufrufen per karten[0].zeige().
 
T

temi

Kurzes Beispiel zum Thema:
Java:
class Foo {
    public static void staticDoSomething() {
        // hier steht Code
    }

  
public void nonStaticDoSomething() {
        // hier steht Code
    }
}

// wird folgendermaßen verwendet:

Foo.staticDoSomething(); // die statische Methode wird direkt auf der Klasse aufgerufen

Foo foo = new Foo();
foo.nonStaticDoSomething(); // die nicht statische Methode wird auf eine Instanz der Klasse aufgerufen
Im Normalfall hat man nichtstatische Methoden, die haben dann auch Zugriff auf die Daten, die intern zu der Instanz gehören.
 
NormanPatrickBenner

NormanPatrickBenner

Ich muss also bei foo.nonStaticDoSomething foo nicht extra übergeben?
 
NormanPatrickBenner

NormanPatrickBenner

UND anscheinend wichtig, war mir aber nicht klar, non-static Code ist "auf dem gleichen "Niveau" wie die Klasse
also außerhalb der geschweiften Klammern der Klasse?
Sorry, falsch gelesen
Wo muss dann der Konstruktor hin? In die geschweiften Klammern und damit

Wenn ich aus der Klasse "Stapel" den Konstruktor in der Klasse Karte für eine Karte aufrufen will, dann muss der auch non-static?
Danke
Grüße
Norman
 
Zuletzt bearbeitet:
NormanPatrickBenner

NormanPatrickBenner

Okay, doSomething ist eine Eigenschaft, die ich foo automatisch mitgegeben habe, aha!
 
W

White_Fox

Ich habe die Klasse Karten und die Klasse Stapel erstellt (Stapel extends Karte)
Ich kenne dein Programm zwar nicht da du mit dem Code etwas sparsam bist, aber mir kommt dein Konstrukt etwas merkwürdig vor.

Vererben kannst/solltest du, wenn du eine IST-EIN-Beziehnung herstellen kannst. Beispiel: Du hast die (abstrakte) Klasse Fluggerät. Von dieser Klasse kansnt du die Klassen Hubschrauber, Düsenjäger, Segelflugzeug ableiten:
class Hubschrauber extends Fluggerät{}
class Düsenjäger extends Fluggerät{}
class Segelflugzeug extends Fluggerät{}
Denn Hubschrauber, Düsenjäger, Segelflugzeug, sind Fluggeräte.

Frage: Ist ein Kartenstapel eine Karte?
 
NormanPatrickBenner

NormanPatrickBenner

Nein, ein Kartenspiel besteht aus Karten.
Meine Zugriffsyntax war falsch, daher kamen die Fehlermeldungen.
Ich habe eine ausgewählteKarte vom Stapel genommen und diese dann der Methode in Klammer übergeben. Vorangestellt habe ich versucht dem Programm zu sagen, wo er die Methode getFarbe suchen soll, nämlich in der Klasse Karte, also Karte.getFarbe(ausgwählteKarte)
anstatt
ausgewählteKarte.getFarbe.

Jetzt funktioniert es.

Allerdings frage ich mich folgendes:

Wenn ich in der Klasse (Stapel) einen neuenStapel erstellen will, dann muss ich eventuell dafür neueKarten erzeugen.
Dafür habe ich in der Klasse Karte die Methode karteInitiieren.

Ist diese jetzt static oder nicht?



12410
Jetzt könnte man meinen, du brauchst die Karten eh nur einmal, OK, aber was ist, wenn ich eine variable Anzahl Stapel erstellen will.
Muss die Methode StapelInitiieren static oder nicht sein?

12411

Danke für die Antworten!

Norman
 

Anhänge

K

kneitzel

Also die Methode KarteInitiieren erzeugt eine neue Instanz von Karte. Sowas kann sinnvoll sein, so man da ggf. noch Aktivitäten hinein packt. Aber bei Dir ist das ja nur ein einfaches new Karte() -> das macht damit also nicht wirklich Sinn, denn der Konstruktor kann ja so direkt aufgerufen werden. Wenn man so eine Builder Methode haben will, dann ist diese tatsächlich statisch.

Und wenn Dein Stapel keine Karte ist, dann ist da auch ein extends falsch. In dem Stapel sind Karten, aber der Stapel ist keine Karte. Du solltest das extends Karte ersatzlos streichen können.

Code bitte immer in den Code Tags posten. Dann können wir den als ganzes sehen und beurteilen. Generell sind die Getter in der Form aufgebaut:
Java:
public String getFarbe() {
    return farbe;
}
Also keine Karte als Parameter, nicht statisch und dann ist der Aufruf kartenInstanz.getFarbe().

So statische Funktionen findet man in einer regulären Implementation normalerweise nicht. Wenn man eine fremde Klasse erweitern muss, dann bietet Java hier aber kein Mechanismus (Andere Sprachen wie C# oder Kotlin erlauben die Erweiterung von bestehenden Klassen, aber Java halt nicht) so dass hier dann oft eine Klasse wie <Klassenname>Util oder <Klassenname>Helper mit statischen Methoden bereit stellt Also z.B. eine StringUtils Klasse die Methoden für Strings bereit stellt. Aber das nur am Rande um zu erläutern, wo man sowas teilweise sieht.

Ansonsten in deinem Code:
- In den Schleifen fehlt die Initialisierung von i und j. Also int i = 0; bzw. int j = 0.
- Farbe und Wert sind Strings, Du versuchst da aber int Werte zu setzen. So Du nur eine Zahl haben willst, dann solltest Du evtl "" + i oder so setzen.

Tipp:
Schau Dir mal Enums an. Wenn Du eine Liste von Farben haben willst, dann kannst Du ein Enum für die Farben definieren und dann ist farbe vom Typ Farbe (So dein enum Farbe heisst).
Das Gleiche dann auch für Wert.

Oder Du machst diese Werte zumindest als public, damit Du auf die Farben / Werte zugreifen kannst. Diese Konstanten werden dann aber bitte auch gross geschrieben: FARBEN, WERTE.
 
NormanPatrickBenner

NormanPatrickBenner

Danke, die Farben sind Teile von Arrays. Die brauche ich nur zu Beginn des Spiels um den Anfangsstapel Blatt zu erzeugen.

farbe bei get ist also in dem Sinne kein String sondern nur ein Verweis auf den Platz im Array.
bei set ist die Farbe allerdings ein STring, da an der iten STelle ja ein String seht und der in farbe gespeichert wird.
ENUMs werde ich mal betrachten.
Ja, i und j haben kein 0, nicht aufgefallen
Auf Farben muss ich nur in der KLasse Karte zurückgreifen, daher habe ich Sie private gemacht.

Wenn ich das richtig verstanden habe gibt es sowas wie Interface die man implementieren kann um Klassen zu erweitern?

Wann benutzt man super, um Klassen zu implementieren?

Ich dachte, ich muss extends Karten schreiben, weil ich ja auf die MEthoden für die Karten IN dem Stapel zugreifen will, aber das kann ich das wohl weglassen.

Danke
Norman
 
K

kneitzel

Also der Stapel muss doch die Karten erstellen. Also braucht der Stapel das Wissen zu den Farben. Daher sollte der Stapel auch darauf zugreifen können.

Du kannst natürlich die Farbe als einen index für das Array speichern. Dann sollte es aber generell ein int sein und String.

Die Lösung mit den Enums würde ich Dir aber ans Herz legen. Das scheint mir hier erst einmal die beste Lösung zu sein.

Dann hättest Du zwei enums für Farbe und Wert.
Und der Stapel kann dann alle Karten anlegen mit for each schleifen also mit sowas wie:
Code:
for(Farbe farbe: Farbe.values()) {
  for (Wert wert: Wert,values()) {
    add(new Karte(farbe, wert));
  }
}
Damit dieser Code so funktioniert brauchst Du aber nicht nur die Enums Farbe und Wert sondern auch noch:
- im Stapel eine Methode add(Karte), um Karten hinzufügen zu können.
- Karte benötigt einen Konstruktor, der Farbe und Wert entgegen nehmen kann.

Zu dem existierenden Code noch paar Hinweise:
- Bei der Erstellung zählst du die variable k scheinbar nicht hoch. Somit wird immer die erste Karte gesetzt.
- Ich würde beim Stapel einen Konstruktor erwarten, der Anzahl und das Karten Array von Hand setzt. Die Anzahl ergibt sich doch über Anzahl der Farben und werte und das Array muss erst einmal leer erzeugt werden...
Oder man hat einen Parameter, der die Anzahl der verwendeten Kartensets entgegen nimmt. Also wenn man z.B. mit 2 Kartenspielen gleichzeitig spielen möchte oder so ...
 
W

White_Fox

Ein Interface erweitert eine Klasse um eine Funktionalität.

Beispiel: Ich hatte oben die Klassen Hubschrauber, Düsenjäger und Segelflugzeug erwähnt, die alle von der abstrakten Klasse Fluggerät abgeleitet werden. Jetzt implementieren wir ein Interface 'Schwimmfähig' in einer abgeleiteten Klasse:
Java:
public interface Schwimmfähig{
    public void schwimmen();
}
Damit könnte man jetzt z.B. ein Wasserflugzeug bauen:
Java:
public class Wasserflugzeug extends Fluggerät implements Schwimmfähig{
    public void schwimmen(){
        //Klassenabhängige Implementierung
    }
}

Wann benutzt man super, um Klassen zu implementieren?
Gar nicht. Mit 'super' wird auf eine Methode der Superklasse zugegriffen.
 
NormanPatrickBenner

NormanPatrickBenner

Ich habe immernoch das Problem mit static usw.

Ich habe die Initiierungsmethoden rausgeschmissen.
ABER, das hilft auch nicht weiter.
Wenn ich das Gesamtblatt erstelle, beschwert der Compiler sich immer, das setFArbe usw nicht statisch ist.

Ich finde keine Lösung!

Danke für Eure Hilfe!

Norman

Java:
import java.util.Random;

public class Stapel {
    
    private int anzahl;
    private  Karte [] karten;
    
    public void Stapel (int anzahl, Karte [] karten ) {
        this.anzahl = anzahl;
        this.karten= karten;
    }
    
        
    public static Stapel BlattErstellen( ) {
        Stapel Blatt = new Stapel();
        int k = 0;
        for (int i =0; i<4; i++) {
            for (int j=0; j < 8; j++) {
                karten[k] = new Karte;
                karten[k].setKontrollnummer (k);
                karten[k].setFarbe (i);
                karten[k].setWert(j);
            }
        }
        return Blatt;
    }
    
    public   Stapel StapelErstellen (int anzahl) {
        Stapel stapel = new Stapel();
        stapel.anzahl = anzahl;
        
        
        
        
        return stapel;
        
    }
            
    public void Mischen () {
        Karte zwischenSpeicher;
        Karte tauschPartner;
        int zufallsZahl;
        Random random = new Random();
        for (int i=0; i<anzahl-1;i++) {
            zufallsZahl= random.nextInt(anzahl);
            zwischenSpeicher = karten [i];
            karten [i]= karten [zufallsZahl];
            karten [zufallsZahl]=tauschPartner ;
        }
        
        
    }
    
    
    public int getAnzahl () {
        return anzahl;
    }
    
    public Karte holeErsteKarte () {
        return karten[anzahl-1];
    }
    
    public void zeigeErsteKarte () {
        karten[anzahl-1].zeigen();
    }
    
    
    public void zeigeKarten () {
        for (int i =0; i<= anzahl-1; i++) {
            System.out.print("Karte :  " +i);
            karten[i].zeigen();
        }
    }
    
    public Karte  getObersteKarte () {
        Karte obersteKarte= karten[(anzahl-1)];
        karten[anzahl-1] = null;
        anzahl = anzahl-1;
        return obersteKarte;
    }
    
    public Karte  KarteAnPositionNehmen (int p) {
        Karte gewählteKarte= karten[p];
        for (int i = p; i<(anzahl-1);i++) {
            karten [i]=karten[i+1];
        }
        karten[anzahl-1] = null;
        anzahl = anzahl-1;
        return gewählteKarte;
    }
    
    public void KarteHinzufügen (Karte karte) {
        karten[anzahl]=karte;
        anzahl= anzahl+1;
    }
    
    
    
}
 
NormanPatrickBenner

NormanPatrickBenner

Ihr habe natürlcih recht.

Einen normalen Stapel erzeuge ich auch anders. Indem ich vom gemischten Blatt die entsprechende Anzahl Karten ziehe.

Mit den Farben, das kann man sicher besser lösen.

Allerdings haben mir eure Antworten leider nicht zu static non-static weitergeholfen.

Wo stehe ich hier auf dem Schlauch?

Danke
Grüße
Norman
 
K

kneitzel

Also derzeit frage ich mich, wie Dein Code überhaupt ansatzweise compilieren soll....

Deine Klasse Stapel hat einen Konstruktor, der zwei Parameter verlangt. Aber Du rufst immer einen Konstruktor ohne Parameter auf.

Dann bei dem Erstellen der Karte hast du nur "new Karte" statt "new Karte()" - es fehlen also die Klammern.

Solche Fehler würde ich erst einmal beseitigen. Ansonsten sehen die Aufrufe des Setters korrekt aus, die da nach der Zeile mit dem new kommen.

Vorschlag:
Gib einmal alle Deine aktuellen Klassen komplett und dann nehmen wir diese Fehler einmal raus, damit es kompiliert. Denn im Augenblick fürchte ich, dass Dich andere Probleme daran hindern, womöglich Richtiges als richtig zu erkennen.
 
T

tommysenf

Eigentlich ganz einfach. Bei dem was du vorhast sollte nirgendwo ein static auftauchen, mal abgesehen von der public static void main Methode. Also raus mit allen statics, du wirst danach auf viele andere Fehler treffen, aber du bist dann schon mal ein Stück weiter.
 
NormanPatrickBenner

NormanPatrickBenner

OK!

Dann mache ich das. Aber ich habe das Problem bei laufenden Projekten auch gehabt, und da habe ich unwissend einfach alles auf static gesetzt, damit es funktioniert.

Also erstmal fertig machen.

Poste ich dann auch alle Klassen?

Grüße
Norman
 
K

kneitzel

Nicht alles fertig machen sondern erst einmal offensichtliche Fehler korrigieren, so dass es compiliert werden kann.

==> Code sollte meiner Meinung nach immer nur für möglichst kleine Zeitfenster nicht übersetzbar (und nicht testbar, aber mit Unit-Tests hast Du derzeit wohl noch nichts am Hut) sein.

Daher sollte man jetzt als erstes dafür sorgen, dass der Code übersetz werden kann. (Und das nicht durch unnötiges Einfügen von static!)

Daher wäre meine Bitte, den aktuellen Stand einmal zu teilen. Und das sind mind. die Klassen Karte und Stapel, aber evtl. auch noch etwas drumherum (falls Du z.B, eine Klasse mit main Methode hast oder Du schon eine enum angelegt hast oder so, dann sollten die auch mit kopiert werden).

Und die Hilfe, die ich angeboten habe, ist, dass ich (oder wir) dann zusehen, dass wir den aktuellen Stand etwas überarbeiten, so dass Du dann mit einem compilierbaren Stand etwas weiter machen kannst.
 
NormanPatrickBenner

NormanPatrickBenner

Hallo,

ich werde heute Nacht weitermachen, jetzt gehe ich erstmal zu den Kindern.
Static gilt für die ganze Klasse , beispiel Anzahl der Menschen in der Klasse Mensch, diese Anzahl ist ja für alle Menschen der Klasse gleich.
non static: gilt für Eigenschaft eines Menschen. Beispiel: Ein Mensch hat eine Haarfarbe, die ist bei jedem unterschiedlich.

Grüße
Norman
 
NormanPatrickBenner

NormanPatrickBenner

SO, nachdem ich jetzt mal einen Moment bei meiner Familie gesessen habe werde ich erstmal weiter programmieren.

static: Methode, die für die ganze Klasse gilt bzw. sich nicht ändert, wie zum Beispiel in der KLasse Menschen die Bevölkerungszahl aller Menschen, die ist für alle gleich.
Die Eigenschaft HAarfarbe ist jedoch nicht für alle gleich, also non-static

Wie ist es allerdings mit Essen (eine Handlung die alle Menschen machen aber halt jeder anders?

Grüße
Norman
 
T

tommysenf

Du schreibst die Antwort ja eigentlich schon selbst. Wie ein einzelner Mensch isst hängt von seinen individuellen Attributen ab...
 
T

temi

beispiel Anzahl der Menschen in der Klasse Mensch, diese Anzahl ist ja für alle Menschen der Klasse gleich.
Kann man machen, muss man aber nicht. Eine gute Empfehlung ist häufig vom wirklichen Leben auszugehen: Weiß ein einzelner Mensch, wieviele Menschen existieren und wann genau ein neuer dazu kommt? Oder, anderes Beispiel, weiß ein einzelnes Buch, wieviele davon in der Bücherei stehen? Eine Klasse sollte nur das tun, was sie unmittelbar betrifft, d.h. wenn du eine Klasse Mensch hast, dann hat sie z.B. Geschlecht, Größe, Gewicht, Haarfarbe, ...

Brauchst du mehrere Menschen, dann steck die einzelnen Menschen in die Klasse "Menschenmenge" oder "Erde".

Wie schon geschrieben wurde: Es ist eine gute Empfehlung, außer bei der Methode "main()" erst mal auf static zu verzichten. Es gibt Situationen, wo es gebraucht wird, die sind aber eher seltener.
 
NormanPatrickBenner

NormanPatrickBenner

Also,

beim ersten Compile Versuch war alles richtig außer:
12412

Das Hauptproblem ist nach wie vor erstmal, wo erstelle ich beim erstes Blatt, also alle KArten. Und wie mache ich das hier mit dem static-non-static
Anbei alle Klassen:
Javascript:
public class Karte {

    private String farbe;
    private String wert;
    private int kontrollnummer;
    private final String [] farben = {"Kreuz", "Pik", "Herz","Karo"};
    private final String [] werte = {"7", "8", "9", "10", "Bube", "Dame", "König", "As"};
    
    public void Karte (String farbe, String wert, int kontrollnummer) {
        this.farbe=farbe;
        this.wert=wert;
        this.kontrollnummer= kontrollnummer;
    }
    
        
    public void setFarbe ( int i) {
        farbe= farben[i];   
    }
    
    public String getFarbe () {
        return this.farbe;
    }

    public void setWert ( int i) {
        wert= werte[i];   
    }
    
    public String getWert () {
        return wert;
    }

    public void setKontrollnummer ( int kontrollnummer) {
        this.kontrollnummer= kontrollnummer;   
    }
    
    public int getKontrollnummer () {
        return this.kontrollnummer;
    }
    
    public void zeigen () {
        System.out.println("" + farbe + "  " + wert) ;
    }
}

import java.util.Random;

public class Stapel extends Karte{
    
    private int anzahl;
    private  Karte [] karten = new Karte  [31];
    
    public void Stapel (int anzahl, Karte [] karten ) {
        this.anzahl = anzahl;
        this.karten = karten;
    }
    
    public  Stapel BlattErstellen( ) {
        Stapel Blatt = new Stapel();
        int k = 0;
        for (int i =0; i<4; i++) {
            for (int j=0; j < 8; j++) {
                karten[k] = new Karte();
                karten[k].setKontrollnummer (k);
                karten[k].setFarbe (i);
                karten[k].setWert(j);
            }
        }
        return Blatt;   
    }
    
    public   void StapelFüllen (int anzahl) {
        this.anzahl = anzahl;
        for (int i = 0 ;i<anzahl;i++) {
            this.karten[i]=Blatt.getObersteKarte();
        }
    }
            
    public void Mischen () {
        Karte zwischenSpeicher;
        int zufallsZahl;
        Random random = new Random();
        for (int i=0; i<anzahl-1;i++) {
            zufallsZahl= random.nextInt(anzahl);
            zwischenSpeicher = karten [i];
            karten [i]= karten [zufallsZahl];
            karten [zufallsZahl] = zwischenSpeicher;
        }
    }
    
    
    public int getAnzahl () {
        return anzahl;
    }
    
    public String [] farbeUndWertOberste () {
        String[] farbeUndWert = new String [2];
        farbeUndWert[1]=karten[anzahl-1].getFarbe();
        farbeUndWert[2]=karten[anzahl-1].getWert();
        return farbeUndWert;
        
    }
    
        
    
    public void zeigeKarten () {
        for (int i =0; i<= anzahl-1; i++) {
            System.out.print("Karte :  " +i);
            karten[i].zeigen();
        }
    }
    
    public Karte  getObersteKarte () {
        Karte obersteKarte= karten[(anzahl-1)];
        karten[anzahl-1] = null;
        anzahl = anzahl-1;
        return obersteKarte;
    }
    
    public Karte  KarteAnPositionNehmen (int p) {
        Karte gewählteKarte= karten[p];
        for (int i = p; i<(anzahl-1);i++) {
            karten [i]=karten[i+1];
        }
        karten[anzahl-1] = null;
        anzahl = anzahl-1;
        return gewählteKarte;
    }
    
    public void KarteHinzufügen (Karte karte) {
        karten[anzahl]=karte;
        anzahl= anzahl+1;
    }

    public void zeigeObersteKarte() {
        karten[anzahl-1].zeigen();
    }
    
}
import java.util.Scanner;

public class Spieler extends Stapel {
    
    private String name;
    private Stapel handkarten;
    private int anzahlKarten;
    
    
    public Spieler(int anzahlStarthandKarten) {
        Scanner Eingabe = new Scanner (System.in);       
        this.handkarten = new Stapel();
        handkarten.StapelFüllen(anzahlStarthandKarten);
        this.anzahlKarten = anzahlStarthandKarten;
    }

    
    public void setName (int i) {
        System.out.println("Name des " +(i+1) + "ten Spielers?");
        Scanner Eingabe = new Scanner (System.in);
        String Name =  Eingabe.nextLine();
        name = Name;
    }
    
    public String getName () {
        return name;
    }
    
    public int anzahlHandkarten () {
        return handkarten.getAnzahl();
    }
    
    public Karte spieleKarte (int position) {
        return handkarten.KarteAnPositionNehmen(position);       
    }
    
    public void zieheKarte (Karte karte) {
        handkarten.KarteHinzufügen(karte);
    }
    
    public void zeigeHandKarten () {
        handkarten.zeigeKarten();
    }
    
    
}
import java.util.Scanner;

public class Konfiguration extends Spieler{
    public  Stapel Blatt;
    public static int anzahlSpieler;
    public static int anzahlStarthandKarten;
    private static Spieler [] spielerrunde = new Spieler [anzahlSpieler];
    public static int indexAktiverSpieler;
    public static int gewinner = -1;
    static Stapel  NachZiehStapel = new Stapel() ;
    static Stapel  AblageStapel = new Stapel ();
    static int [] konfig;
    
    
    static int ZahlEinlesen (int Minimum, int Maximum){
        Scanner Eingabe = new Scanner (System.in);
        int z =-1;
        boolean error=true;
        do{
            do{
                System.out.printf("Bitte geben Sie eine ganze Zahl ein zwischen %d und %d ein: /n", Minimum, Maximum);
                try{
                    z = Integer.parseInt(Eingabe.nextLine());
                    error=false;
                }
                catch (NumberFormatException e)    {
                    System.out.println("Nur Integer Zahlen eingeben!");
                    error=true;
                }
            }while ( error );
            if (z>Maximum || z < Minimum){
                System.out.println("Nur ganze Zahlen zwischen " + Minimum + " und " + Maximum + "  eingeben!");
            }
        }while (z>Maximum || z < Minimum);
            //System.out.println ( "Danke, Ihre Eingabe lautet : " + z );
            
            return z;
        }

    public void Konfiguration (){
        System.out.println("Bitte geben Sie an, mit wie vielen Spielern Sie spielen wollen:");
        anzahlSpieler = ZahlEinlesen (2,6);
        //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 = Math.min(6,z);
        for (int i = 0 ;i< anzahlSpieler ; i++) {
            spielerrunde [i]  = new Spieler (anzahlStarthandKarten);
        }
        int []konfig_a = {anzahlSpieler, anzahlStarthandKarten};
        NachZiehStapel = Blatt;
        AblageStapel.KarteHinzufügen(NachZiehStapel.getObersteKarte ());
        
    }
    
    public int  KartenAuswählen (int indexAktiverSpieler ) {
        System.out.println("Spieler " + spielerrunde[indexAktiverSpieler].getName() + " , Sie sind dran. /n Ihre Karten:");
        spielerrunde[indexAktiverSpieler].zeigeHandKarten();
        System.out.println("Biite wählen Sie die Karte aus, die Sie ausspielen wollen:/ Mit -1 ziehen Sie eine Karte vom NAchziehstapel.");
        int auswahl = ZahlEinlesen (-1,(spielerrunde [indexAktiverSpieler].anzahlHandkarten()-1));
        return auswahl;
    }
    
    public void KartevomNachziehstapelGeben(int indexAktiveSpieler) {
        spielerrunde[indexAktiverSpieler].KarteHinzufügen(NachZiehStapel.getObersteKarte());
        System.out.println("In dieser Variante ist dann jetzt der Nächste dran, Sorry");
    }
    
    public boolean kartePrüfen (int auswahl) {
        boolean kartePasst;
        String [ ]prüfKarte = {spielerrunde [indexAktiverSpieler].spieleKarte(auswahl).getFarbe(), spielerrunde [indexAktiverSpieler].spieleKarte(auswahl).getWert()};
        String [] oberAblage = AblageStapel.farbeUndWertOberste();
        if (prüfKarte[0].equals(oberAblage[0]) || prüfKarte[1].equals(oberAblage[1])) {kartePasst = true;}
        else {kartePasst = false;
            System.out.println("Ihre Karte hat nicht gepasst. Sie wird Ihnen zurückgegeben und der nächste Spieler ist dran.");
        }
        return kartePasst;
    }
    
        
    public int Spielzug (Spieler [] spielerrunde,  int anzahlSpieler) {   
        indexAktiverSpieler = 0;
        while(spielerrunde[indexAktiverSpieler].anzahlHandkarten() !=0) {       
            boolean kannAblegen;
            System.out.println("Die oberste Karte auf dem Stapel ist");
            NachZiehStapel.zeigeObersteKarte();
            int auswahl = KartenAuswählen(indexAktiverSpieler);
            if (auswahl == -1) {
                KartevomNachziehstapelGeben(indexAktiverSpieler);
                kannAblegen = false;}
            else {kannAblegen=kartePrüfen (auswahl);}
            
            if (kannAblegen == true) {
                AblageStapel.KarteHinzufügen(spielerrunde [indexAktiverSpieler].spieleKarte(auswahl));
            }
            if (NachZiehStapel.getAnzahl()==0) {
                Karte Zwischenspeicher =AblageStapel.getObersteKarte();
                NachZiehStapel = AblageStapel;
                NachZiehStapel.Mischen();
            }
            if (indexAktiverSpieler < anzahlSpieler) {indexAktiverSpieler ++;}
            else {indexAktiverSpieler =0;}
        } ;
        
        gewinner = indexAktiverSpieler;
        return gewinner;
        
    }
    
    
    
    
    public static void main(String[] args) {
            Blatt = BlattErstellen ();
            Konfiguration Konfiguration = new Konfiguration();
            gewinner =Spielzug (spielerrunde, anzahlSpieler);   
            System.out.println("Gewonnen hat: " + spielerrunde[gewinner].getName());
    }
            

}
 
Thallius

Thallius

Der Fehler liegt ja schon darin, dass der Stapel nicht die Karte erweitert. Der Stapel ist eine gewisse Anzahl an Karten aber nicht eine Erweiterung einer Karte. Also das extens ist vom Konzept her einfach falsch.
 
T

temi

Das Hauptproblem ist nach wie vor erstmal, wo erstelle ich beim erstes Blatt, also alle KArten.
Wenn man sich das so anschaut, dann fehlen dir offenbar sehr wichtige Grundlagen, die du dir dringend z.B. anhand eines guten Buches zuerst aneignen solltest.

Du solltest darauf achten, dass du Java Konventionen einhältst, z.B. Klassennamen werden im CamelCase (Großbuchstabe am Anfang) geschrieben und Methoden- und Variablennamen werden im sogenannten lowerCamelCase (Kleinbuchstabe am Anfang) geschrieben.

Dann sollten Klassen nur eine Funktionalität haben und nichts vermischen. In deinem Fall z.B. eine Hauptklasse "Kartenspiel" mit der main() Methode und die Klassen "Karte" und "Blatt" für den Anfang.

Deine "extends" Anweisungen sind auch völlig fehl am Platz, wie schon @Thallius geschrieben hat. "Extends" bedeutet immer eine Ist-ein-Beziehung und ein Stapel ist keine Karte, sondern enthält Karten.

In der main() könnten dann ungefähr stehen:

Java:
    public static void main(String[] args) {
        // die Klasse Blatt enthält eine Kollektion von Karten, die zusammen ein Blatt ergeben
        // die Initialisierung (zufällige Erzeugung) kannst du bereits im Konstruktor machen. 
        Blatt blatt = new Blatt();

        // mit diesem Blatt kannst du jetzt spielen
        Karte ersteKarte = blatt.getErsteKarte();
    }
Edit:

Sinnvoll wäre hier allerdings, dass "Blatt" von "Stapel" erbt und den einfachen Stapel um die Funkionalität erweitert einen gemischten Kartenstapel zu erzeugen.
 
Zuletzt bearbeitet:
T

temi

Mal ein konkreter Vorschlag, wie die Klasse Karte aussehen könnte. Ich habe zusätzlich noch Enumerationen für Farbe und Wert vorgesehen, die das Ganze klarer machen und Fehler vermeiden (Strings sind für diese Funktionalität sehr fehleranfällig).

Die Karte ist immutabel, d.h. das sich Farbe und Wert nicht ändern können, wenn die Karte erstellt wurde. Das ist aber auch in einem echten Spiel so der Fall, also durchaus logisch. Darum gibt es auch keine Setter-Methoden.

Java:
public enum Farbe {
    KREUZ("Kreuz"), PIK("Pik"), HERZ("Herz"), KARO("Karo");

    private String info;

    Farbe(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return info;
    }
}

public enum Wert {

    SIEBEN("7"), ACHT("8"), NEUN("9"), ZEHN("10"), BUBE("Bube"), DAME("Dame"), KOENIG("König"), AS("As");

    private String info;

    Wert(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return info;
    }
}

public class Karte {

    private final Farbe farbe;
    private final Wert wert;

    public Karte(Farbe farbe, Wert wert) {
        this.farbe = farbe;
        this.wert = wert;
    }

    public Farbe getFarbe() {
        return farbe;
    }

    public Wert getWert() {
        return wert;
    }

    // normalerweise trennt man Funktion und Ausgabe, aber dennoch
    public void zeigen() {
        System.out.println(this);
    }

    @Override
    public String toString() {
        return farbe + " " + wert;
    }
}
Und in der main() exemplarisch, damit du siehst, wie das verwendet wird. Deine tatsächliche main() wird wohl später etwas anders aussehen.

Java:
public class Main {

    public static void main(String[] args) {
        Karte karte = new Karte(Farbe.HERZ, Wert.AS);

        karte.zeigen();

        // oder

        System.out.println(karte);
    }
}
Nimm das mal als Start für deine weiteren Klassen.
 
Zuletzt bearbeitet:
K

kneitzel

Ich möchte einen Punkt noch einmal kurz vertiefen:

Der Startpunkt ist immer die public static void main Methode, d.h. eine statische Methode. Hier hast Du also eine Startposition, bei der noch keine Objekte existieren. Daher ist es jetzt wichtig, dass Du Dir an dieser Stelle die Welt, die Du brauchst, erstellst.

Also was ist das zentrale Element in Deinem Spiel? Das kann das Spiel selbst sein. Also eine Klasse Spiel oder Game, falls Du die Namen auf Englisch bevorzugst.

Somit wird da immer in der main Methode sowas sein wie: Erstelle das zentrale Objekt und dann starte da drin den eigentlichen Ablauf (also z.B. eine start oder run Methode in Spiel/Game).

Und ehe Du anfängst auch nur irgend einen Code zu schreiben, ist nun wichtig, dass Du Dir im klaren darüber bist, was es denn alles so für Elemente gibt.

In dem Spiel gibt es Spieler. Wie viele? Was macht ein Spieler aus? (Was für Daten sind hier wichtig? Was muss der Spieler können?)
Was ist in dem Spiel sonst noch wichtig? Es gibt von mir aus einen Kartenstapel, von dem Karten gezogen werden können. Es können Karten abgelegt werden, ....

Du musst Dir das im Detail genau überlegen. Und dann kennst Du die einzelnen Elemente, die Du brauchst incl. dem, was diese Elemente aus machen und was diese machen können.

So hat ein Spieler z.B. eine Menge Karten, hat einen Namen, ...
Ein Spieler kann eine Karte ziehen (unter bestimmten Bedingungen, z.B. wenn er am Zug ist), kann eine Karte ablegen (am Zug ist, und ggf. gibt es Regeln, wann er welche Karte wie ablegen darf.)

Und dann ist klar, was es alles so gibt oder nicht gibt. Hier ist dann auch wichtig, dass man dann alles, was man schreibt, direkt testen kann. Hier ist meine klare Empfehlung: Schau die Unit Tests an. JUnit ist nicht so kompliziert! Oder mach es einfach in der Form von "Unit Tests für Dumme": Schreib einfach Klassen wie "XyzTest" mit Xyz dem Namen einer Klasse und in der Klasse hast Du in erster Linie eine public static void main Methode, in der Du dann mit Spieler irgendwas machst, um den Spieler zu testen.
Der Spieler soll einen Namen haben, also kannst Du da ganz einfach testen: Wenn Du einen Spieler erstellst und den Namen setzt: Ist dann der Name wirklich gesetzt? Trivialer Test, scheint erst einmal unnötig, aber testen halt setter und getter vom Namen. Wird aber auch komplexer: Du generierst von mir aus eine Spiel Instanz mit einem Kartenstapel und dann testest Du, dass ein Spieler eine Karte ziehen kann, incl:
- Wenn der Spieler nicht dran ist, dann bekommst Du eine Exception.
- Die oberste Karte ist danach nicht mehr auf dem Stapel und der Spieler hat diese Karte danach.
- Wenn der Stapel leer ist, dann kommt auch eine Exception wie gewünscht
- ....
Einfach alle Testfälle. Diese Testfälle sind etwas blöd, da Du die immer nur manuell selbst aufrufen kannst, aber das ist ein Anfang. Später kannst Du die Funktion etwas umschreiben, JUnit einbinden für das @test und paar Asserts und so, aber das wäre ein erster Anfang.
 
NormanPatrickBenner

NormanPatrickBenner

Jo, alles ist immer ganz einfach

Nimm doch den Windowbuilder um frames , contents, panels , LAyouts zu erzeugen GANZ Einfach
nimm doch dieses oder jenes oder ENUMS (habe ich schon tausendmal gehört und esse ich jeden Tag zum Frühstück
Nimm doch ArrayList, dann hast du alle Methoden gleichzeitg
Nimm doch einen stack-Array, dann hast du automatisch einen Kellerspeicher

Erzeuge doch dieses und jenes und importiere dieses Package,

speicher hier und da

Super

Die Bücher fangen immer mit Hello World an und dann kommen auf der zweiten Seite schon eintausendvierhundertachtundfünfzig Wörter, für die man je weiter eintausendvierhunderachtunfünfzig Bücher lesen muss.

Wenn man alles kann, lesen sich die Bücher sehr einfach und man denkt, ja, genau, super beschrieben.

Ansonsten hangelt man sich von einem Eintrag und Index zum anderen und nach zwei Wochen schafft man gerade anstatt HAllo Word vielleicht Hallo ihr alle zu schreiben.

Ich habe vor 30 Jahren in Basic programmiert, dann in PAscal, im Studium musste ich irgendwie mit VisualBAsic rumfuddeln, dann 20 Jahre nichts.
Ich habe drei Kinder, bin Feuerwehrmann, Musiker, Lehrer und laufe und fahre gerne Fahrrad, gerade bin ich froh, dass ich mit einem kaputten Kreuzband im Bett liege und eine Woche Zeit habe mal was zu programmieren außer "Hello World"

Also die Namen, klar, krieg ich hin.
Das mit dem Extends habe ich auch kapiert und das regt euch anscheinend sehr auf, also mache ich es weg, dass ist gegen die Konventionen.

Das mit den Klassen , static usw hat mir als promovierter Physiker in den letzten zwei Wochen der Professor selber, sein Assistent, mehrere Leute die schon JAhre programmieren usw versucht zu erklären, aber JUNGS, ihr denkt halt schon anders. Es kommen bei euch sofort zweihundertachtundreißig Worte in jedem Satz, die ein nicht-Programmierer erst mal nachschauen muss. Da für mich das wichtigste war, das mit den Unterklassen und so zu kapieren, bin ich froh, dass ich das so hinbekommen habe, wie ich es hinbekommen habe.

Die Konventionen werde ich ab sofort einhalten und glaubt mir , ich bin in meiner Lerngruppe nicht der , der am weitesten hinten ist.



Danke für eure kosntruktive Hilfe, ich mach mich an die Abreit.
 
NormanPatrickBenner

NormanPatrickBenner

Zum konkreten Problem Blatt:

Blatt ist doch nur ein Spezialfall von Stapel, kriegt Blatt dann einen eigenen Konstruktor?
Ist das sinnvoll? Ich benötige das doch nur einmal am Anfang. Dann wäre aber extends wenigstens mal im richtigen Sinne verwendet.
Blatt rufe ich im main Programm auf, so weit war ich ja schon, aber ich lasse es auch dort initiieren, und nicht in der Methode blattErstellen?, Ok, ist schon implementiert.

Mein Main Programm war ja sehr kurz, daher dachte ich, dass Konfiguration, was im Prinzip der Konstruktor für ein Spiel ist, da er die Anzahl der Spieler erzeugt , den Namen abfragt, "Blatt" erzeugt, die Stapel vereilt, und den Nachziestapel vorbereitet.
Ansonsten war da ja nur das Spiel selber und ein paar kleine Methoden, soll aber trotzdem nicht ins main-Fenster???
Also, so wie ich es verstanden habe. soll der Konfigurator, der alles erzeugt, was man für das Spiel braucht in eine extra Klasse in Konfigurator ( spielerrunde, anzahlSpieler, anzahlStartHandKarten, nachZiehStapel und AblageStapel).

Wo sollen die Methoden hin, die für das Spiel selber benötigt werden? In Konstruktor oder in die Klasse mit dem main Programm. Wenn ich es richtig verstanden habe. sollen die helfenden Methoden nicht in die gleiche Klasse wie das main-Programm. (spielzug, kartePrüfen, ZahlEinlesen, kartePrüfe, kartevomNachziehstapelGeben, kartenAuswählen)



Dann muss ich die spielerrunde, die alle Spieler mit allem enthält und im Konfigurator erzeugt wird doch immer komplett mit übergeben, macht das Sinn?

Also, ich erzeuge Blatt jetzt erstmal im Konstruktor meiner Main Klasse, die ich erstmal in der Klasse Konfigurator lasse (ja, ist UNMÖGLICH!)


Vielen Dank!

Norman


P.S.: Wie genau es mein Blatt geschafft hat, static zu werden habe ich immernoch nicht verstanden. Vielleicht stand das bei eurer Version vor Blatt, aber die war auch ohne es davor zu schreiben plötzlich static.



Danke nochmals
 
W

White_Fox

Blatt ist doch nur ein Spezialfall von Stapel, kriegt Blatt dann einen eigenen Konstruktor?
Ist das sinnvoll? Ich benötige das doch nur einmal am Anfang. Dann wäre aber extends wenigstens mal im richtigen Sinne verwendet.
Blatt rufe ich im main Programm auf, so weit war ich ja schon, aber ich lasse es auch dort initiieren, und nicht in der Methode blattErstellen?, Ok, ist schon implementiert.
Erstmal: Kompliment für dein Durchhaltevermögen. Es gibt Leute, die haben über diesen Kram Klausuren mit einer guten Note bestanden und weniger verstanden als du bis jetzt. Kopf hoch, und weiter so. :)

Zu deiner Frage: Schaue dir einfach mal die Realität an. 'Stapel' ist eine Ansammlung von Karten, 'Blatt' auch. Aber: wenn du zwei oder mehr Blätter erzeugen willst, mußt du dafür Sorgen, daß nicht in zwei Blättern ein Pik As vorkommt. Jede Karte muß einzigartig sein, die Reihenfolge jedoch trotzdem zufällig.

Es würde, meiner Meinung nach, Sinn ergeben, für 'Blatt' gar keinen (öffentlichen!) Konstruktor vorzusehen. Besser wäre, wenn die Klasse 'Stapel' einfach Blätter austeilt. Was du also machen könntest:
-für alle Klassen, die direkt mit deinen Karten zu tun haben, ein eigenes Package Karten anlegen (deine main-Methode kommt in ein eigenes Packages main).
-den Konstruktor von 'Blatt' auf package private setzen (also einfach keinen Sichtbarkeitsmodifizierer mitgeben), dann können nur Klassen desselben Packages den Konstruktor aufrufen. Also z.B. die Klasse Stapel. In der main-Methode könntest du den Konstruktor jedoch nicht erreichen.


Übrigens: Ich hab etwa ein Jahr daran gesessen, eine vernünftige MVC-Struktur in meinem Programm zu implementieren. Es ist nicht so daß wir das Problem, so absolut gar nichts zu verstehen, nicht kennen würden. Jeder hat irgendwann mal angefangen. :)
 
NormanPatrickBenner

NormanPatrickBenner

Jetzt stehe ich schon wieder vor dem gleichen Problem.

Für alle Methoden in der Klasse Konfiguration soll z.B.anzahlSpieler gleich sein, (also static??),

ich muss dann aber im main-Programm auf diesen Wert zurückgreifen, da aber genau verweigert sich java?

anzahlSpieler wird ja im Konfigurator erzeugt. Daher erstelle ich in der Klasse eine Methode, um diesen Wert für meine main-Klasse abrufen zu können. Die main Klasse benötigt anzahlSpieler um dann in der Klasse Konfigurator (oder einer anderen, noch zu erstellenden) den Gewinner des Spiels zu ermitteln. Das klingt strange, aber ihr habt mehr Ahnung als ich und ich verstehe es halt noch nicht.
Wenn ich die Variablen im Konstruktor erzeuge bzw. verwende (und sie dann Teil von diesem sind?) muss ich diese dann immer hin- und herschicken und da kommt dann zum Beispiel wenn ich das hier machen will:

Code:
public int getAnzahlSpieler() {
         return  this.anzahlSpieler;
     }

should be accesed in a static way
 
NormanPatrickBenner

NormanPatrickBenner

Das war eine schöne Antwort, Danke!


Erstmal: Kompliment für dein Durchhaltevermögen. Es gibt Leute, die haben über diesen Kram Klausuren mit einer guten Note bestanden und weniger verstanden als du bis jetzt. Kopf hoch, und weiter so. :)

Zu deiner Frage: Schaue dir einfach mal die Realität an. 'Stapel' ist eine Ansammlung von Karten, 'Blatt' auch. Aber: wenn du zwei oder mehr Blätter erzeugen willst, mußt du dafür Sorgen, daß nicht in zwei Blättern ein Pik As vorkommt. Jede Karte muß einzigartig sein, die Reihenfolge jedoch trotzdem zufällig.

Es würde, meiner Meinung nach, Sinn ergeben, für 'Blatt' gar keinen (öffentlichen!) Konstruktor vorzusehen. Besser wäre, wenn die Klasse 'Stapel' einfach Blätter austeilt. Was du also machen könntest:
-für alle Klassen, die direkt mit deinen Karten zu tun haben, ein eigenes Package Karten anlegen (deine main-Methode kommt in ein eigenes Packages main).
-den Konstruktor von 'Blatt' auf package private setzen (also einfach keinen Sichtbarkeitsmodifizierer mitgeben), dann können nur Klassen desselben Packages den Konstruktor aufrufen. Also z.B. die Klasse Stapel. In der main-Methode könntest du den Konstruktor jedoch nicht erreichen.


Übrigens: Ich hab etwa ein Jahr daran gesessen, eine vernünftige MVC-Struktur in meinem Programm zu implementieren. Es ist nicht so daß wir das Problem, so absolut gar nichts zu verstehen, nicht kennen würden. Jeder hat irgendwann mal angefangen. :)
 
W

White_Fox

Für alle Methoden in der Klasse Konfiguration soll z.B.anzahlSpieler gleich sein, (also static??),
Wie wäre es denn mit folgendem Ansatz: Erstelle eine Klasse Kartenspiel. Wenn du ein neues Spiel eröffnest (den Konstruktor von 'Kartenspiel' aufrufst) gibst du alle nötigen Informationen mit. Der gesamte Spielablauf würde innerhalb dieser Klasse stattfinden. Von außen greifst du nur noch mit Methoden wie 'nächsterSpieler' oder so zu. Und diese Klasse weiß natürlich, wieviele Spieler teilnehmen.

Denn, angenommen du hättest zwei Spiele parallel zu laufen: Was interessiert es die eine Spielrunde, wieviele Teilnehmer die jeweils andere hat?
Es ist allgemein gut, möglichst restriktiv zu programmieren. D.h. jede Klasse bekommt nur die Informationen, die sie wirklich braucht. Informationen, die die Klasse nicht braucht, werden nicht freigegeben, deswegen gibt es die ganzen Sichtbarkeitsmodifizierer. Später etwas nachträglich freizugeben ist in der Regel nie ein Problem. Später aber den Zugriff zu entfernen ist oft ein Problem.
 
NormanPatrickBenner

NormanPatrickBenner

Danke!

OK, ich habe das mit dem static immer weiter nach oben geschoben. In der Klasse Konfiguration gibt es den Konstruktor Konfiguration, der alles erstellt was man für ein Spiel braucht (Blatt, verschiedene Stapel, Spieler usw.
Außerdem liegen da alle Methoden, die man für das Spiel braucht. (prüfeKarte, wähleSpieler usw
Meine MAin-Klasse sieht jetzt nur noch so aus.

Code:
public class MauMau {
    static int anzahlSpieler;
    Konfiguration Konfiguration;
    

    public static void main(String[] args) {
        System.out.println("Bitte geben Sie an, mit wie vielen Spielern Sie spielen wollen:");
        anzahlSpieler = Hilfsprogramm.zahlEinlesen (2,6);
        Konfiguration Konfiguration = new Konfiguration(anzahlSpieler);
        Konfiguration.spiel();
        Konfiguration.gewinnerAusgeben();
        
    }

}
Komischerweise sagt der Compiler, dass Konfiguration keinen integer übergeben haben will, obwohl ich ihn dahingehend geändert habe.
Jetzt kommt aber wieder das Problem mit
stati-nonstatic


Exception in thread "main" java.lang.Error: Unresolved compilation problems:
Cannot make a static reference to the non-static method zahlEinlesen(int, int) from the type Hilfsprogramme
The constructor Konfiguration(int) is undefined

Das erste Problem verstehe ich nicht, weil ich es einfach immernoch nicht kapiere.
Das zweite Problem verschwindet vielleicht, wenn ich das Programm schließe und wieder öffne, da ich den Konstruktor Konfigurator ganz sicher so geändert habe, dass er ein Integer übernimmt.

Danke für die ganzen Hinweise, aber stati-nonstatic ist immer noch nicht ganz durch bei mir.

Grüße
Norman
 
T

temi

Ich bemühe noch einmal die Klasse Foo ;)

Java:
class Foo {

    // Diese Methode wird direkt auf der Klasse aufgerufen: Foo.staticDoSomething();
    public static void staticDoSomething() {
        // hier steht Code
    }

    // für diese Methode musst du vorher eine Instanz der Klasse erzeugen: Foo instance = new Foo();
    // auf diese Instanz kann die Methode aufgerufen werden: instance.nonStaticDoSomething();
    public void nonStaticDoSomething() {
        // hier steht Code
    }
}
Der Unterschied zwischen den beiden Methoden ist, dass die statische Methode direkt auf der Klasse Foo aufgerufen wird, während nicht statische Methoden nur und ausschließlich auf Instanzen dieser Klasse aufgerufen werden können. Bei Variablen ist es im Prinzip genauso. Eine statische Variable gehört zur Klasse, d.h. es gibt sie nur einmal, egal wieviele Instanzen du von der Klasse erzeugst, der Inhalt der statischen Variablen ist für alle identisch.

Nicht statische Variablen hingegen gehören zur Instanz der Klasse. Jede Instanz hat eine "eigene" Variable.

Und noch einmal: Statische Methoden oder Variablen sind eher selten. Die Regel ist nicht statisch.
 
M

mrBrown

In der Klasse Konfiguration gibt es den Konstruktor Konfiguration, der alles erstellt was man für ein Spiel braucht (Blatt, verschiedene Stapel, Spieler usw.
BTW, die meisten deiner Klassen enthalten keine Konstruktoren, sondern nur Methoden, die genauso heißen wie die Klasse und void als Rückgabetyp haben - durch den Rückgabetyp ist es aber einfach nur noch eine normale Methode, da solltest du noch mal drüber gucken :)

Das dürfte dann auch der Grund hierfür sein:
The constructor Konfiguration(int) is undefined
 
NormanPatrickBenner

NormanPatrickBenner

Also, bei
anzahlSpieler = Hilfsprogramme.zahlEinlesen(2,6)
beschwert sich der compiler, "can'T make a static reference ..........."
Die MEthode zahlEinlesen ist in ihrer Klasse auf jeden Fall non-static.
Die VAriable anzahlSpieler im main Programm da habe ich auch das static gelöscht.
Mir erscheint es so, dass wenn ich mit einer VAriable anfange zu arbeiten, diese also aufrufe, diese dann static wird.
JEtzt muss diese Variable aus irgendeinem Aufruf herkommen, und dann verlangt der compiler in meinen Augen, dass diese Methode auch static sein muss, weil die VAriable ja da "festgelegt" wird. Wenn ich das aber nach unten verlängere, dann ist doch irgendwie alles static, und das kann ja nicht im Sinne des Erfinders sein.

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?

Vielen Dank wenn ihr da das Brett vor meinem Kopf entfernen könntet

Grüße
Norman
 
M

mrBrown

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

NormanPatrickBenner

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
 
NormanPatrickBenner

NormanPatrickBenner

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
 
T

temi

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

NormanPatrickBenner

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
 
NormanPatrickBenner

NormanPatrickBenner

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
 
NormanPatrickBenner

NormanPatrickBenner

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 ());
    }
 
NormanPatrickBenner

NormanPatrickBenner

Offensichtlich habe ich blatt gar nicht als konkretes Objekt erzeugt. mmhh
 
NormanPatrickBenner

NormanPatrickBenner

Ne, war doch nur ein Laufvariablenfeher, falsche Laufvariable genommen.
 
Thallius

Thallius

Es ist Teil des Stapels aber es erweitert den Stapel doch nicht durch irgendwelche Funktionen
 
T

temi

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

mihe7

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

Tobias-nrw

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:
W

White_Fox

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

NormanPatrickBenner

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
 
M

mrBrown

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.
Was muss der Konstruktor denn da wissen?

Ich würde Blatt und Stapel einfach trennen (wobei ja erstmal noch zu klären wäre, was Blatt sein soll), und zwischen den beiden keine Ist-Ein-Beziehubg aufbauen. Die führt nur zu Problemen (eins davon hast du ja schon gemerkt und mit protected „behoben“).
 
NormanPatrickBenner

NormanPatrickBenner

Ok,

ich hätte zum Speicher eine stack Liste nehmen sollen, aber gefordert war das Array,

Vorab: Ich vermute stark, dass das Problem bei "anzahl" liegt. Das ist die Variable, die anzeigt, welches die oberste Karte eines Stapels ist.

JEtzt habe ich ein anderes Problem.
Im Konfigurator werden die Spieler Konfigurationen aufgerufen, die wiederum die Stapelkonfiguratoren aufrufen die wiederum die Kartenkonfigurationen aufrufen.
Spieler [0] wir erstellt und bekommt die Variable "anzahlStartHandkarten". Mit der kann er selber nichts anfangen und reicht die weiter an den Stapel Konfigurator.

Code:
public Spieler(int anzahlStarthandKarten, Stapel blatt) {   
        // die Variable anzahlStarthandKarten wird direkt an den Stapelkonfigurator weitergeegeben.
        this.handkarten = new Stapel(anzahlStarthandKarten);
        System.out.println("Name des  Spielers?");
        Scanner Eingabe = new Scanner (System.in);
        name =  Eingabe.nextLine();
        //Jetzt werden die Handstapel gefüllt, dass kann der Stapelkonfigurator nicht machen, da nicht jeder Stapel gefüllt sein muss.
        handkarten.stapelFüllen(blatt);
    }
JEtzt werden die also gefüllt.
Jetzt hat der Stapel in der Variable die richtige Zahl ABER mit einer sysout-Anweisung , in der ich mir die Anzahl ausdrucken lasse , was auch funktioniert, gibt es hier den ersten Fehler
12413

Javascript:
    public void stapelFüllen(Stapel blatt) {
        //Hier kommt es zum ersten Fehler "java.lang.NullPointerException
        // Ich habe nachgeprüft, anzahl ist hier auf jeden Fall immer richtig!
        for (int i = 0; i < anzahl; i++) {
            System.out.println("Index i in stapelfüllen " +i );
            //Hier kann er Karte [0] nicht finden, (habe ich mir auch schonmal ausgeben lassen)
            //obwohl er SICHER 0 als index verwendet hat, das habe ich MEHRMALS überprüft!!! siehe oben!!
            karten[i].zeigen();
        }
    }
komischerweise macht er manchmal weiter, bis er hier landet:

Javascript:
public Karte getObersteKarte() {
        //Hier fängt er IMMER mit dem richtigen Index an.
        Karte obersteKarte = karten[(anzahl - 1)];
        System.out.println("hinter oberste KArte");
        System.out.println(obersteKarte.getFarbe());
        //Die nächse Zeile ist eigentlich überflüssig, da ich nur auf den Index verweise, wenn
        // oberste KArte haben will, aber ich will sie löschen. Das war zunächst meine Vermutung für Abstürze,
        // aber auch mit rauskommentieren ändert sicht nichts, scheint also kein großes Problem zu sein.
        karten[anzahl - 1] = null;
        System.out.println();
        //In der nächsten Zeile bleibt er häufig hängen?!?!?!
        anzahl = (anzahl - 1);
        return obersteKarte;
    }
Manchmal geht es aber sogar dann weiter, (das Programm hat sogar schon für zwei bis sechs Spieler alle Karten ausgeteilt, den Ablage und Nachziehstapel erstellt. Aber spätestens, wenn die oberste Karte vom Ablagestapel gezeigt werden soll, gibt es ein Problem mit anzahl.
anzahl ist der Verweis auf die oberste KArte.
Hier erscheint mir ein prinzipielles Problem.
Ich hoffe, ich habe es gut beschrieben.

Danke im Voraus.
 
NormanPatrickBenner

NormanPatrickBenner

Was muss der Konstruktor denn da wissen?

Ich würde Blatt und Stapel einfach trennen (wobei ja erstmal noch zu klären wäre, was Blatt sein soll), und zwischen den beiden keine Ist-Ein-Beziehubg aufbauen. Die führt nur zu Problemen (eins davon hast du ja schon gemerkt und mit protected „behoben“).
Doch, das finde ich gut.

Ich muss auch von Blatt Karten abheben und den Spielern geben, dafür könnte ich natürlich eine MEthode neu schreiben, da das nur zu BEginn vorkommt, werde ich auch machen, aber jetzt lese ich erstmal meiner Tochter vor. OK, ich brauche nur die Mehtode gibKArte, ja scheint Sinn zu machen.

Blatt wird aber anders "hergestellt" als Stapel, daher erscheint ein eigener Konstruktor auf jeden Fall sinnvoll.
 
M

mrBrown

Der Code und der Fehler passen nicht wirklich zusammen?

Laut Fehler wird in stapelFüllen getObersteKarte aufgerufen, in dem gezeigten Code passiert das nicht.


stapelFüllen versucht eine Karte auszugeben - existiert denn da überhaupt schon eine Karte in dem Array? (Falls du nicht im Konstruktor von Stapel welche anlegst nein).
 
M

mrBrown

Doch, das finde ich gut.

Ich muss auch von Blatt Karten abheben und den Spielern geben, dafür könnte ich natürlich eine MEthode neu schreiben, da das nur zu BEginn vorkommt, werde ich auch machen, aber jetzt lese ich erstmal meiner Tochter vor. OK, ich brauche nur die Mehtode gibKArte, ja scheint Sinn zu machen.

Blatt wird aber anders "hergestellt" als Stapel, daher erscheint ein eigener Konstruktor auf jeden Fall sinnvoll.
Auf welchen Teil meines Beitrags beziehst du dich damit, und willst du damit verteidigen, dass Blatt ein Stapel ist oder stimmst du mir zu, dass es Unsinn ist?



Jetzt irgendwo extends zu nutzen, wird nur zu Problemen führen (wird leider meist viel zu früh gelehrt...).

Selbst wenn du jetzt sagst, dass ein Blatt (von dem immer noch nicht geklärt ist, was es ist) ein Stapel ist - willst du in deinem Programm irgendwo ein Blatt nutzen, wo ein Stapel benötigt wird? Wenn Nein: Vererbung weg. (Und wenn Ja: könnte jeder Spieler statt Stapel also einfach ein Blatt bekommen?)

Ein eigener Konstruktor macht grundsätzlich in jeder Klasse sein, und sei es nur, um den default-Konstruktor zu verhindern - das ist aber völlig unabhängig davon, ob es irgendeine Vererbungsbeziehung gibt.
 
NormanPatrickBenner

NormanPatrickBenner

Ui, in Blatt füllen habe ich vor lauter kommentieren den Code gelöscht, SCHADE!
 
W

White_Fox

Hat Eclipse sowas wie eine History? Dann könntest du das einfach wiederherstellen lassen.
 
NormanPatrickBenner

NormanPatrickBenner

Mmhh, hatt schon zu viele ander Sachen auch geändert. Blatt hat jetzt nicht mehr mit Stapel zu tun. Jetzt habe ich allerdings die Methoden mischen und getObereKarte zweimal, einmal in Stapel und einmal in Blatt.
Obwohl ich nicht weiß, wo da der Fehler lag, funktioniert Konfiguration jetzt wunderbar. Jetzt muss ich allerdings den Rest des Blattes an den Nachziehstapel übergeben.
 
NormanPatrickBenner

NormanPatrickBenner

Also, doch nicht wunderbar

Javascript:
    public  Konfiguration (int anzahlSpieler){
        this.anzahlSpieler= anzahlSpieler;
        this.gewinner = -1;
        Blatt blatt = new Blatt();
        blatt.blattMischen();
        //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 =Math.min(6,z);
        spielerrunde = new Spieler [anzahlSpieler];
        for (int i = 0 ;i< anzahlSpieler ; i++) {
            this.spielerrunde [i]  = new Spieler (anzahlStarthandKarten, blatt);
            System.out.println("Hier kommt der erste Fehler, aber es geht trotzdem weiter");
            spielerrunde [i].zeigeHandKarten();
        }
        nachZiehStapel.stapelFüllen(blatt);
        Stapel ablageStapel = new Stapel (32);
        ablageStapel.karteHinzufügen(nachZiehStapel.getObersteKarte ());
    }
12414

Javascript:
public void zeigeKarten() {
        System.out.println("Zahl der Handkarten:" +anzahl);
        for (int i = 0; i < anzahl-1; i++) {
            System.out.println("Karte :  " + i+ " jetzt kommt der Fehler");
            karten[i].zeigen();
        }
    }
Irgendwie füllt er karten[0] nicht
 
NormanPatrickBenner

NormanPatrickBenner

Ich bin weiter!!!!

Ich hatte die ZEILE 100% , sogar 1000%, eingefügt (k=k+1), aber die Heinzalmännchen haben sie wieder gelöscht.
Hat mich 4 Stunden gekostet!
In der Zeit hätte ich das ganze Programm neu schreiben können!
 
NormanPatrickBenner

NormanPatrickBenner

FERTIG!!

Wenn ich mal Lust habe baue ich ENUMS ein,
und baue ein GUI drum rum(mit den ActionListenern habe ich mich schon ganz schön rumgeärgert, insbseonder wie ich die Werte aus Ihnen rausbekomme, aber vielleicht klappt das ja mit dem jetzigen Wissen besser.)
Außerdem könnte man es mit stacks ausrüsten.
Andere Spiele implentieren.

JEtzt ist erstmal ruhe!
Es stehen auch noch andere Sachen an.
Vielen Dank für eure Geduld!
Danke
Norman
 
K

kneitzel

Mein Ratschläge wären:
a) (Wie schon einmal geschrieben) Tests. Wenn man Tests einmal geschrieben hat für einzelne Teile, dann kann man diese Teile ganz einfach testen. Und das Testen von kleinen Teilen ist deutlich effektiver und einfach als nur das große Ganze zu sehen.
(Und ehe wieder diese Auslassungen kommen von wegen "ganz einfach": Das bezieht sich auf das Testen. Das ist dann, wenn man die Tests hat, ganz einfach. Bei dem vorgeschlagenen Tests für Dumme ist das ein einfaches Anstarten einer main Methode und das kannst Du doch schon und das ist auch in Deinen Augen ganz einfach, oder etwa nicht?)
b) Eine Source Code Verwaltung macht auch Sinn. Dann kann man auf alte Stände zurückgreifen, so man z.B. etwas löscht, was man später dann doch wieder haben möchte ...
 
W

White_Fox

a) (Wie schon einmal geschrieben) Tests. Wenn man Tests einmal geschrieben hat für einzelne Teile, dann kann man diese Teile ganz einfach testen. Und das Testen von kleinen Teilen ist deutlich effektiver und einfach als nur das große Ganze zu sehen.
(Und ehe wieder diese Auslassungen kommen von wegen "ganz einfach": Das bezieht sich auf das Testen. Das ist dann, wenn man die Tests hat, ganz einfach. Bei dem vorgeschlagenen Tests für Dumme ist das ein einfaches Anstarten einer main Methode und das kannst Du doch schon und das ist auch in Deinen Augen ganz einfach, oder etwa nicht?)
Netbeans kann das und ich nehme an, Eclipse kann das auch: Tests automatisch erstellen. Die automatisierten Tests mußt du dann zwar noch mit Leben füllen, aber grundsätzlich bekommst du eine Idee davon, wie der Test aussehen soll. Das, was dein Testframework noch alles bietet, kann man wunderbar mit der Autocodevervollständigung erforschen.
Es gibt auf youtube bestimmt genug Videos, wo gezeigt wird wie das geht.
 
NormanPatrickBenner

NormanPatrickBenner

Ja DAnke,

normalerweise fange ich ja auch bei main an, da ich aber so einen tollen Plan hatte, wer was können soll muss ich ja erstmal Karte erstellen um mit Stapel zu arbeiten.
NA ja.
Die Methode hatte ja auch schon funktioniert, ich habe die Zeile nur durchs kommentieren wieder gelöscht.
Ja. immer zwischenspeichern ;-))

Auch mit den Test war ich sehr zufriedenAber zum Debugger:
An die ganzen Möglichkeiten in eclipse habe ich mich noch nicht gewöhnt (arbeite erste zwei Wochen mit java) .
Mir ist klar, dass man Debuggen kann und ich habe das auch schon gemacht. Man kann aber eclipse tausendfach individualisieren und eine Million Sachen einstellen, da ist es nicht einfach den Überblick zu behalten wenn man gleichzeitig, static, main, Enums und auch noch packages, utilities, ....... alles machen soll.
Ich habe den Debugger schon mehrmals verwendet und mir auch das Variablenfenster dabei angeschaut (manchmal verschwindet das bei Window-> ShowView, dann erscheint es einfach nicht.
Jetzt das PROBLEM: Benutzt man den Debugger in der Variablenansicht, dann werden auch immer die von Java implizierten Methoden alle mitangezeigt, und das sind im Falle eines NULL-Pointer Fehlers SEEEEEHR viele. Da verliert man die Lust, den Debugger zu benutzen. (Eintausenmal F5 drücken). Ich weiß aber nicht, wie das heißt, was ich ausschalten will, daher habe ich in jeder Zeile, die ich überprüfenswert fand ein Sysout eingesetzt. Ich weiß ja selber, dass das unprofessionell ist. ALSO: Was muss ich ausschalten, um wirklich nur MEIN Code zu debuggen, ansonsten kann ich den Debugger nicht benutzen.

An sich war ich mit meinem Programm ansonsten sehr zufrieden. Im NAchhinein war es am schwersten das mit den Methoden zu verstehen, weil ich halt nicht gemerkt habe, dass ich keine Konfiguratoren hatte, das hat die Logik unheimlich erschwert, weil es ja nicht so funktionierte, wie es hätte sollen.


Fraglich ist allerdings, ob ich mich so sehr reinfuchse, da ich nicht weiß, ob ich überhaupt nach den zwei Wochen weiter Java programmiere.
Zur Erläuterung: Ich gehöre zu einer Gruppe von Lehrer, die in 2 Jahen in Kursen mit einer Gesamtlänge von ca 6 bis 8 Wochen Vollzeit zum Informatiklehrer ausgebildet werden. Die Ausbildung finde ich zwar sehr schmalspur, aber sie ist gleichwertig zu jemandem , der 8 Semester Informatik studiert hat. Da muss halt alles ein wenig schneller gehen. Zum Glück ist der mathematische Teil nicht so schwer (habe ich schon Vorlesungen gehalten) und in Physik habe ich schon Halbaddierer und Volladdierer mit Transistoren mit den Schülern gebaut, gewisse Grundkentnisse sind also da.
ToDoListe:
1. Wie debugge ich ohne die implizierten Fenster
2. GUIs erstellen
3. Was sind packages und was weiß ich alles
3. ENUMS
4. Diese Sache mit den Test der einzelnen Methoden

Grüße
Norman
 
W

White_Fox

Da ich Eclipse nicht benutze gehe ich jetzt mal von Netbeans aus und setze vorraus, daß Eclipse sich hier äquivalent verhält:

Das mit den 10^x Methodenaufrufen, damit meinst du wahrscheinlich den Stacktrace. Den mußt du in der Regel nicht völlig durchgehen, es reicht, wenn du nach deinen eigenen Klassen suchst. Der Stacktrace zeigt dir an, wo der Fehler herkommt. Wenn du eine Nullpointer-Exception in einem ArrayList hast, dann wird die Exception irgendwo tief in den Eingeweiden der Java Standardbibliothek geworfen, diese Stelle versteckt sich irgendwo hinter mindestens zwei oder drei Klassen und einem Interface und zig internen privaten Methodenaufrufen. Daher ist der Trace so lang.

Aber eigentlich geht der Fehler von ganz weit oben aus, wo in deiner Klasse der problematische Aufruf herkam. Und an dieser Stelle hilft dir der Debugger: Ein Haltepunkt am Methodenanfang, und dann schrittweise, Zeile für Zeile, das Programm weiter durchgehen. Dabei kannst du dir die Werte aller Variablen anschauen und prüfen, ob da die Werte drinstehen, die du erwartest.
 
K

kneitzel

Also ich finde erst einmal gut, dass Du da eine solche Weiterbildung machst, aber die Ansprüche der AUsbildung bezüglich den "8 Semestern Informatik" kann ich nicht nachvollziehen.... Irgendwie haben wir in den 8 Semestern mehr Stoff gehabt, als man mal eben so in 6-8 Wochen durchziehen könnte :)

Generell ist es egal, was für eine Sprache du nimmst. Aber ich fürchte, dass Du eine Sprache doch so gut können musst, dass Du diese auch vermitteln kannst. Und wenn etwas bei einem Schüler nicht läuft, dann sollte man das doch überblicken und einordnen können... Ob dies nun Java ist oder irgend eine andere Sprache ist dabei erst einmal egal. Aber eine Beherrschung sollte da sein, so dass man selbst das machen kann, was ja von den Schülern dann auch verlangt wird....

IDEs gibt es viele. Eclipse ist nicht bekannt für eine einfache, intuitive Bedienung. Daher wäre meine Empfehlung, sich einmal andere IDEs anzusehen. Hier ist z.B. auch zu beachten, was für Anforderungen es speziell aus Schulsicht gibt. IntelliJ finde ich sehr gut und das setze ich ein. Die Community Edition ist frei und für Schul-Belange mehr wie ausreichend. (JEE wird da wohl kaum Thema werden.) Zum Lernen gedacht ist z.B. auch BlueJ. Es gibt sehr viele Möglichkeiten und man sollte sich eine suchen, mit der man gut klar kommt, also da dann ruhig einmal andere IDEs ausprobieren.

Im Debugger reicht es in der Regel, den eigenen Code zu debuggen. Also nicht erst bei einer Exception reagieren, sondern vorher schon Schritt für Schritt durch den eigenen Code zu gehen. Aber bezüglich Debugger ist auch anzumerken, dass dieser überbewertet ist. Die Zeit, die ich im Debugger bin, ist extrem klein. Durch die Aufteilung in kleine Teile und die direkten Tests dieser Teile ist der Einsatz eines Debuggers oft unnötig. Der Griff zum Debugger ist da dann meist ein Zeichen, dass man da noch zu komplexe Teile hat mit zu wenig oder zu schlechten Tests.

Und generell ist die Frage, was den Schülern vermittelt werden soll. Was steckt da in den Lehrplänen alles drin?
==> Das sollte man sich im Detail gut aneignen. Wie will man etwas vernünftig vermitteln, wenn einem selbst das Verständnis fehlt?
 
NormanPatrickBenner

NormanPatrickBenner

Jo, wo stelle ich ein, dass ich nur MEINEN Code debugge.
Ich sehe das mit der Fortbidlung ähnlich, aber das Kultusministerium meint, dass das ausreichend ist.
Meine jüngste Tochter erhält ihren Matheunterricht in der 5. KLasse gerade von einer Zahnarzthelferin, so viel dazu.

Grüße
Norman
 
W

White_Fox

Jo, wo stelle ich ein, dass ich nur MEINEN Code debugge.
Gar nicht. Denn der von dir verwedete Code gehört ja genauso zu deinem Programm. Du mußt ja aber nicht die Bibliotheken mitdebuggen, es reicht doch wenn du durch deine eigenen Codezeilen tippelst.


Meine jüngste Tochter erhält ihren Matheunterricht in der 5. KLasse gerade von einer Zahnarzthelferin, so viel dazu.
Langsam wird es Zeit die Koffer zu packen. Diesem Land ist nicht mehr zu helfen... :mad:
 
Zuletzt bearbeitet:
T

tommysenf

Benutzt man den Debugger in der Variablenansicht, dann werden auch immer die von Java implizierten Methoden alle mitangezeigt, und das sind im Falle eines NULL-Pointer Fehlers SEEEEEHR viele. Da verliert man die Lust, den Debugger zu benutzen. (Eintausenmal F5 drücken).
Neben Step Into (F5) gibt es auch Step Over womit du zu nächsten Zeile springst und nicht in die aufgerufene Funktion. Das wird wahrscheinlich genau das sein was du suchst. Kann es gerade nicht ausprobieren aber ich tippe mal auf F6. Weiterhin gibt es auch noch Step Return womit du in der Aufrufhirarchie wieder eine Stufe nach oben kommst. Im Zweifelsfall schau dir einfach mal die Buttons oben im Debugger an...
 
K

kneitzel

Jo, wo stelle ich ein, dass ich nur MEINEN Code debugge.
Ich sehe das mit der Fortbidlung ähnlich, aber das Kultusministerium meint, dass das ausreichend ist.
Meine jüngste Tochter erhält ihren Matheunterricht in der 5. KLasse gerade von einer Zahnarzthelferin, so viel dazu.
Also beim Debuggen führst Du den Debugger. Da Du in der Regel ja einen Breakpoint setzt, landest Du an genau der gewünschten Stelle.
Dann geht es entweder in Einzelschritten weiter (also "Step over" um den Befehl der aktuellen Zeile auszuführen oder eben "Step into" um in den Code weiter hinein zu gehen.) oder man lässt es direkt weiter laufen (resume) so dass er bis zum nächsten Breakpoint läuft.

Daher wäre mein Ratschlag, Breakpoints etwas großzügiger zu setzen, denn wenn er beim step over auch auf einen Breakpoint läuft, dann hält er auch wieder an.

In welchem Bundesland bist Du denn, wenn man fragen darf? Das mit der Zahnarzthelferin ist schon recht heftig finde ich.
 
NormanPatrickBenner

NormanPatrickBenner

Ja, die macht das nur Vertretungsweise, aber schon häufiger, die gibt auch Deutsche, Kunst, was immer gebraucht wird.

Zum Debugger: Ich setze verschiedene Debugger Toggles, klar, dann kann ich mir die Variablen anschauen. Da diese aber static sind, sehe ich die nicht mehr, wenn ich implizierte Funktionen aufrufe (also "javainterne"), will ich aber gar nicht. Ich will halt nur den CODE anschauen, den ich selber geschrieben habe, nicht den, den ich benutze.
 
Thema: 

static non-static

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben