Ne, war doch nur ein Laufvariablenfeher, falsche Laufvariable genommen.
Aber Blatt ist doch ein Stapel?
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 deutlicherDie 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?
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;
}
}
Erweitert e = new Erweitert();
e.zeige();
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
}
Erweitert e1 = new Erweitert();
Erweitert e2 = new Erweitert(100);
e1.zeige(); // liefert 0
e1.reset();
e1.zeige(); // liefert 4
e2.zeige(); // liefert 100
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(){
//...
}
//...
}
Gib dem Teil eine schicke Oberfläche (dann kannst du dich gleich in GUI-Programmierung üben) und verkauf das im Appstore oder so...das schaut sich außer euch und dem Übungsleiter eh nie mehr jemand an
Was muss der Konstruktor denn da wissen?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.
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);
}
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();
}
}
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;
}
Doch, das finde ich gut.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“).
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).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?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.
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 ());
}
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();
}
}
Herzlichen Glükwunsch.FERTIG!!
Schau dir mal an, wie man mit einem Debugger arbeitet. Dann findest du solche Fehler leichter.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!
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.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?)
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.Jo, wo stelle ich ein, dass ich nur MEINEN Code debugge.
Langsam wird es Zeit die Koffer zu packen. Diesem Land ist nicht mehr zu helfen...Meine jüngste Tochter erhält ihren Matheunterricht in der 5. KLasse gerade von einer Zahnarzthelferin, so viel dazu.
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...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).
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, daß, was ich darunter verstehe - kannst du doch. Anscheinend meinst du aber was anderes. Also: was meinst du denn?Ich will halt nur den CODE anschauen, den ich selber geschrieben habe, nicht den, den ich benutze.