PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Integer "verliert" Wert



BlueJay
10-06-2007, 07:45
Hallo Leute,

ich beisse mich gerade durch mein erstes Java-Programm und an folgender Stelle fest:
Die global definierte Zugzahl weicht innerhalb der Methoden voneinander ab.

Bild:
http://www.gamecraft.de/_sonstiges/turnit_scr.png

rechts oben (blaues Feld) steht die korrekte Zahl, unten (rot) eine um 1 niedrigere Zahl (oder auch 0, als wäre sie nicht korrekt initialisiert)

Der Code: (Ausschnitte)



import javax.swing.*; // Buttons und so'n Kram
import java.awt.*; // grafischer Schnickschnack
import java.awt.event.*; // Mausklicks
import java.util.Random; // Random-Generator
import java.io.*; // Hiscore

public class turnit
{
private static JFrame frame;

// Spielvariable, alles, was man so braucht:
static int xmax=8;
static int ymax=8;
static int maxcolor=4;
static int modus=2;
static int zmax=xmax*ymax;
static int cnt;
static boolean spiel_laeuft;
....

public static void neu(int nr)
{ int i,k;
modus=nr;
Random r = new Random();
for (i=0; i<zmax; i++) { f[i]=0; show_chip(i); }
// Spiel generieren:
for (i=0; i<4*nr; i++) { k=Math.abs(r.nextInt())%zmax; turn(k); }
cnt=0; // Zugcounter initialisieren
lzug.setText("Zug:"+cnt);
anzeige.setBackground(Color.black);
messi.setText(modus+" Phasen");
loadit(); // Bestenliste laden
lhi.setText("Bestes Spiel: "+hi[modus-2]+" Z\u00fcge");
spiel_laeuft=true;
}

.....

// Reaktion auf Mausklick:
public static void klick(int mx,int my)
{ int ix,iy;
if (spiel_laeuft)
{ ix=mx*xmax/spiel.getWidth();
iy=my*ymax/spiel.getHeight();
ix=ix+xmax*iy;
turn(ix);
cnt++; // Zugcounter hochsetzen
lzug.setText(""+cnt); // hier ist die Welt in Ordnung
}
// System.out.println("hat Klick gemacht: ");
}

.....

// Abfrage, ob Eintrag:

public static void geschafft()
{ int i,j,k;
k=1; for (i=1; i<zmax; i++) if (k>0) if (f[i]!=f[0]) k=0;
if (k>0)
{ anzeige.setBackground(drot);
// hier hat cnt plötzlichPhantasiewerte, z.B. eins zu wenig
messi.setText("Geschafft in "+cnt+" Z\u00fcgen!");
spiel_laeuft=false;
loadit();
if (cnt<hi[modus-2])
{ messi.setText("neuer Rekord!");
hi[modus-2]=cnt;
lhi.setText("Bestes Spiel: "+hi[modus-2]+" Z\u00fcge");
saveit();
}
}
}


Die Methoden werdnin der obigen Reihenfolge abgearbeitet: neu() setzt cnt auf 0, klick() zählt cnt um 1 hoch und gibt auf blauem Feld aus, geschafft() soll cnt zum Speichern weiterleiten und im roten Feld anzeigen. Hier kommt cnt falsch an.

Wieso? Abhilfe?

so long,
BlueJay

bischi
10-06-2007, 08:56
Ich kann den Fehler gerade auch nicht sehen... Als kleiner Tipp: Gebe an verschiedenen Stellen den Wert von cnt über System.out.println() aus - dann merkst du recht schnell, wo der Haken ist! (System.out.println lässt sich in Java wunderbar zum debuggen verwenden :D )

MfG Bischi

PS: Du verwendest nicht per Zufall mehrere Threads?!
PS2: Btw - wieso verwendest du eigentlich alle Funktionen als "static"?

static

Variablen und Methoden mit dem Attribut static sind nicht an die Existenz eines konkreten Objekts gebunden, sondern existieren vom Laden der Klasse bis zum Beenden des Programms. Das static-Attribut beeinflußt bei Membervariablen ihre Lebensdauer und erlaubt bei Methoden den Aufruf, ohne daß der Aufrufer ein Objekt der Klasse besitzt, in der die Methode definiert wurde.

Wird das Attribut static nicht verwendet, so sind Variablen innerhalb einer Klasse immer an eine konkrete Instanz gebunden. Ihre Lebensdauer beginnt mit dem Anlegen des Objekts und dem Aufruf eines Konstruktors und endet mit der Freigabe des Objekts durch den Garbage Collector.

BlueJay
10-06-2007, 09:21
Als kleiner Tipp: Gebe an verschiedenen Stellen den Wert von cnt über System.out.println() aus.


Hab ich gemacht und einen bösen Bug entdeckt! Ich rufe bei klick die Auswertung auf und counte dann erst hoch. Da kriegt die Auswertung einen Zug weniger mit. (schäm)



PS: Du verwendest nicht per Zufall mehrere Threads?!
PS2: Btw - wieso verwendest du eigentlich alle Funktionen als "static"?

(Noch) nicht. neu- klick-[klick-] geschafft (die zitierten Methoden) ist der einzige "Durchlauf" für cnt.

Zu static:
Die Ausgabefunktion mit frame zusammen mit dem Size habe ich in groben Zügen vorgegeben bekommen, und ab da akzeptierte der Compiler (Black Hawk oder Sun) nur statische Variablen und Methoden.
(Sun beglückte mich ausserdem zusätzlich mit Warnungen vor Umlauten in Kommentarzeilen.)



Variablen und Methoden mit dem Attribut static sind nicht an die Existenz eines konkreten Objekts gebunden, sondern existieren vom Laden der Klasse bis zum Beenden des Programms.


Genauso sollte es sein, schöne, über die ganze Laufzeit global gültige Variablen (Spielparameter halt), die von irgendwelchen Methoden ausgelesen oder verändert werden.

BlueJay
10-06-2007, 11:24
Hast recht, das ganze Static-Gedöhns war Krampf. Werde dem Kumpel das umgeschriebene main vorschlagen. Derzeit ist static Vergangenheit.

Hoffentlich verkraftet das sein Java-Compiler (ist leider noch unbekannt). Ich weiss nur, dass es ein eklig kleines Display gibt, und dass ich speichermäßig nicht viel Platz habe.

Wie weit ist eigentlich das AWT verbreitet?

Liberty
15-06-2007, 02:22
Moin!

Das Thema ist zwar schon ein paar Tage alt, aber da sind ja noch ein paar Sachen unbearbeitet...

Verbreitung AWT:
Da gibt's ein eindeutiges "Jein", denn nein, das AWT spielt für die Fenster selbst keine Rolle mehr, aber ja, es ist noch sehr verbreitet, weil zumindest der "Nachfolger" Swing weiterhin das Event-Handling des AWT verwendet, dementsprechend über die Hintertür AWT immer noch beteiligt bleibt.

Mehrere Threads:
Ja, Du verwendest mehrere Threads. Allerdings im Hintergrund und ohne es zu wissen, ich weise nur deshalb darauf hin, weil das Event-Handling der GUIs in einem eigenen Thread läuft und das führt manchmal zu unerwartetem Verhalten, muss also immer im Hinterkopf mit einkalkuliert werden.

Static:
Static macht in dieser Situation durchaus Sinn, denn das ist der einfachere der sauberen Wege. Denn wenn Du die "static"-Qualifier nicht mehr haben möchtest, kommst Du nicht umhin, das gesamte Spiel sauber zu Kapseln und von der GUI komplett zu trennen. Alle Zwischenlösungen wären zumindest "unsauber".

So, noch was vergessen? Nö, sieht nicht so aus...

So long,
Liberty

P.S. @bischi:
Der Imperativ zu "geben" ist nach wie vor "gib"!!!

BlueJay
02-07-2007, 11:56
Mehrere Threads:
Ja, Du verwendest mehrere Threads. Allerdings im Hintergrund und ohne es zu wissen, ich weise nur deshalb darauf hin, weil das Event-Handling der GUIs in einem eigenen Thread läuft und das führt manchmal zu unerwartetem Verhalten, muss also immer im Hinterkopf mit einkalkuliert werden.


Mir ist klar, dass ich mit den Bibliotheken einige Threads einschleppe. Ich denke mal, da waren eigene gemeint. Und so weit bin ich erst jetzt (mit raeumen)



Static:
Static macht in dieser Situation durchaus Sinn, denn das ist der einfachere der sauberen Wege. Denn wenn Du die "static"-Qualifier nicht mehr haben möchtest, kommst Du nicht umhin, das gesamte Spiel sauber zu Kapseln und von der GUI komplett zu trennen.


Darauf sollte es hinauslaufen:
HSC- und Game sind static (Datenlieferanten), der Rest (UI) soll sehen, wie er damit zurechtkommt.