Hallo zusammen,
ich habe mich die letzten Tage mal daran gesetzt ein Schiffe versenken Spiel zu programmieren.
Das Spiel ansich läuft so weit prima.
Jetzt habe ich das Ganze auch noch so programmiert, dass der aktuelle Score immer zwischengespeichert wird und dann am Ende ausgegeben wird. Der Score wird auch korrekt gespeichert.
Bei der Ausgabe klappt allerdings etwas noch nicht.
Ich wollte das folgendermaßen machen:
Nachdem das letzte Schiffsfeld aufgedeckt wurde, wird der Benutzer aufgefordert seinen Name einzugeben.
Dieser Name wird dann mit dem Score im aktuellen Fenster ausgegeben (also dort wo vorher noch das Spielfeld war (hat gestern auch schon mal funktioniert; das Spielfeld wird dann einfach nur "überzeichnet") und in der Datei highscore.txt gespeichert.
Dabei soll nach jedem Spiel der Name und Score in einer neuen Zeile in der Datei gespeichert werden.
Beim nächsten Klick soll dann diese Datei wieder ausgelesen werden und deren Inhalt (also alle gespeicherten Highscores) wieder im aktuellen Fenster (wieder mittels "Überzeichnen") ausgegeben werden.
Von der Funktionalität her sollte das ja kein Problem sein. Nur leider habe ich noch einen Fehler im Code und der Inhalt der Datei bleibt leer. Ganz egal, was ich eingebe.
Die IF-Anweisungen in der Paint-Methode müssten so ja eigentlich laufen.
Dass der Score im Fenster angezeigt wurde hat heute Abend schon auf diese Weise geklappt.
Es würde mich sehr freuen, wenn ihr euch mal den Code ansehen würdet.
Ich finde den/die Fehler einfach nicht.
Viele Grüße,
Masipulami
ich habe mich die letzten Tage mal daran gesetzt ein Schiffe versenken Spiel zu programmieren.
Das Spiel ansich läuft so weit prima.
Jetzt habe ich das Ganze auch noch so programmiert, dass der aktuelle Score immer zwischengespeichert wird und dann am Ende ausgegeben wird. Der Score wird auch korrekt gespeichert.
Bei der Ausgabe klappt allerdings etwas noch nicht.
Ich wollte das folgendermaßen machen:
Nachdem das letzte Schiffsfeld aufgedeckt wurde, wird der Benutzer aufgefordert seinen Name einzugeben.
Dieser Name wird dann mit dem Score im aktuellen Fenster ausgegeben (also dort wo vorher noch das Spielfeld war (hat gestern auch schon mal funktioniert; das Spielfeld wird dann einfach nur "überzeichnet") und in der Datei highscore.txt gespeichert.
Dabei soll nach jedem Spiel der Name und Score in einer neuen Zeile in der Datei gespeichert werden.
Beim nächsten Klick soll dann diese Datei wieder ausgelesen werden und deren Inhalt (also alle gespeicherten Highscores) wieder im aktuellen Fenster (wieder mittels "Überzeichnen") ausgegeben werden.
Von der Funktionalität her sollte das ja kein Problem sein. Nur leider habe ich noch einen Fehler im Code und der Inhalt der Datei bleibt leer. Ganz egal, was ich eingebe.
Die IF-Anweisungen in der Paint-Methode müssten so ja eigentlich laufen.
Dass der Score im Fenster angezeigt wurde hat heute Abend schon auf diese Weise geklappt.
Es würde mich sehr freuen, wenn ihr euch mal den Code ansehen würdet.
Ich finde den/die Fehler einfach nicht.
Viele Grüße,
Masipulami
Code:
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
class SchiffeVersenken extends Frame
{
public int zaehler = 0;
final int MAXSPALTE = 16, MAXZEILE = 16; // Geometrie des Spielfelds
Image bild0, bild1, bild2, bild3, bild4, bild5, bildT; // Referenzen auf die zu ladenden Bildchens
int maxX = 0; // maximaler x-Wert, dient zur Errechnung der notweindigen Fenstergröße
Point aktMausPunkt = new Point(0,0); // Koordinaten des letzten Mausklicks
// Sichtbarkeitsmatrix - zeigt an ob an dieser Stelle das Spielbrett sichtbar ist (true) oder nicht (fals)
boolean sm[][] = new boolean[MAXSPALTE][MAXZEILE];
// Wertematrix des Spielfelds. Wird mit Hilfe von Zufallszahlen im Kostruktor erzeugt.
int spielFeld[][] = null;
int feld1 = 0; int feld2 = 0;
int scoreZähler = 0; // Variable, die den aktuellen Score speichert
final int ABSTAND=4; // Abstand des Bildes von oben, unten, links rechts
int schiffsfeldzaehler = 0; // zählt alle Felder aller Schiffe zusammen
int wert; // Wert, der an jeweiligen Stelle des mit Random() erzeugten Arrays steht
Font f; // für Highsoreausgabe
public int x=50; // Position der Textausgabe
public int y=50; // Position der Textausgabe
String ausgabe; // Hier wird Aufgabestring von Punktestand des Scorzählers gespeichert
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String name; // für eingegebenen Name (für Highscore)
String highsc; // wird später so verwendet: highsc = name + " " + ausgabe;
int c;
public static void main (String[] args)
{
SchiffeVersenken re = new SchiffeVersenken();
}
public SchiffeVersenken()
{
super("Bild Anzeigen");
f = new Font("Verdana", Font.PLAIN, 24);
addWindowListener(new WindowClosingAdapter(false));
// Schliesst den MouseListerner mit eigener Klasse (in der gleichen Datei unten!) an
addMouseListener(new myMausListener());
setBackground(new Color(0,22,0)); // Hintergrundfarbe setzen
setSize(200,200); // die Größe ist nur vorläufig, wird in paint() auf den endgültigen Wert geändert
Random zufallsGenerator = new Random();
int[][] spielFeld = new int[16][16];
int zufallsZahl = 0; // Variable speichert die Zufallszahl
int hilfsVariable = 0; // Hilfsvariablen sollen einen reibungslosen Ablauf der
int hilfsVariable2 = 0; // Arrayaufnahme der unterschiedlichen Schiffe sichern.
int zähler = 0; // Zähler, der die Anzahl der Schiffe zählt.
// Hier werden im Array mittels Zufallsgenerator die Schiffe platziert.
// Somit sind die Schiffe bei jedem Start an einer anderen Position.
for(int i = 0; i <16; i++)
{
for(int j = 0; j < 16; j++)
{
// Hier werden die 2er, 3er, 4er und 5er Felder im Array aufgenommen.
if(hilfsVariable == 2 | hilfsVariable == 3 | hilfsVariable == 4 | hilfsVariable == 5)
{
spielFeld[i][j] = zufallsZahl;
hilfsVariable2--;
if(hilfsVariable2 == 1)
{
hilfsVariable = 0;
zähler++; // Zähler der die Anzahl der Schiffe hochzählt,
} // wenn ein 2er, 3er, 4er oder 5er Schiff platziert wird.
}
else
{
// Eine Zufallszahl wird generiert. Die Zufallszahö ist deshalb so hoch damit nicht
// zu viele Schiffe auf dem Spielfelsd sind.
zufallsZahl = zufallsGenerator.nextInt(30);
// Wenn die Zufallszahl größer 5 ist dann wird sie genullt, also leeres Feld.
if(zufallsZahl > 5)
zufallsZahl = 0;
// Sorgt dafür, dass kein zu großes Schiff vor Ende der Spalte gezeichnet wird.
if(zufallsZahl + j > 15)
zufallsZahl = 0;
if(zufallsZahl == 1)
// Zähler der die Anzahl der Schiffe hochzählt, wenn ein 1er Schiff platziert wird.
zähler++;
spielFeld[i][j] = zufallsZahl; // Hier werden die leeren Felder und die 1er Felder ins Array aufgenommen.
hilfsVariable = zufallsZahl; //Hilfsvariablen die einen reibungslosen Ablauf,
hilfsVariable2 = zufallsZahl;// der 2er, 3er, 4er und 5er Felder bei der Arrayaufnahme sicherstellen.
}
}
}
// Nachdem der Spielfeldarray nun mit Zufallswerten gefüllt wurde, werden die
// Schiffsfelder ausgezählt, also alle Felder, auf denen ein Teil eines Schiffes ist.
for(int k = 0; k <16; k++)
{
for(int l = 0; l <16; l++)
{
int wert = spielFeld[k][l];
if(wert == 1 | wert == 2 | wert == 3 | wert == 4 | wert == 5)
{
schiffsfeldzaehler++;
}
}
}
System.out.println("============================");
System.out.println("== Schiffeversenken ==");
System.out.println("============================");
// Bei der Erstellung des Frames wird die Anzahl der erzeugten Schiffe ausgegeben
System.out.println("Anzahl der Schiffe: " +zähler);
// GIbt die Anzahl der Schiffsfelder aus
System.out.println("Anzahl der Schiffsfelder: " + schiffsfeldzaehler);
System.out.println("============================\n");
//System.out.println();
// Weist das Konstruktorarray dem Klassenarray zu
this.spielFeld = (int[][]) spielFeld.clone();
// Bilder werden geladen
bild0=getToolkit().getImage("feld0.gif");
bild1=getToolkit().getImage("feld1.gif");
bild2=getToolkit().getImage("feld2.gif");
bild3=getToolkit().getImage("feld3.gif");
bild4=getToolkit().getImage("feld4.gif");
bild5=getToolkit().getImage("feld5.gif");
bildT=getToolkit().getImage("feldT.gif");
setVisible(true);
}
// wird von myMausListener aufgerufen, und setzt die Referenz der Variablen aktMausPunkt
// auf das Point-Objekt mit den aktuellen Daten des letzten Mausklicks
public void addPunkt(Point p)
{
this.aktMausPunkt = p;
}
private void feldBerechnen()
{
int insOben = getInsets().top;
int insLinks = getInsets().left;
int bildBreite = bild0.getWidth(this);
int bildHoehe = bild0.getHeight(this);
int x=-1,y=-1;
/*
Nachdem die Insets des Fensters und Höhe und Breite der Button-Bilder ermittelt wurden, werden nun aus den Mauskoordinaten
die Koordinaten des angeklickten Feldes errechnet.
Algorithmus:
der x-Wert (d.h. die linke Kante) des beispielsweise 5. Bildes errechnet sich aus
insetLinks + (5*Abstand-zwischen-Bildern) + 4*Bildbreite (5 Abstände und 4 Bilder liegen rechts des 5. Bildes)
Dieser Wert ist die Linke Kante und muss kleiner sein als der x-Wert des Mausklicks, damit das 5. Bild angeklickt sein kann
Die rechte Kante des beispielsweise 5. Bildes errechnet sich aus
insetLinks + (5*Abstand-zwischen-Bildern) + 5*Bildbreite ( d.h. Linke Kante + Bildbreite)
Dieser Wert muss größer sein als der x-Wert des Mausklicks, damit dieses Bild angeklickt sein kann
.. analoges gilt für die y-Werte
Wurde zwischen die Felder geklickt wird für beide Koordinaten -1 ausgegeben
*/
for ( int i =0; i < MAXSPALTE; i++)
for ( int j =0; j < MAXZEILE+1; j++)
if ( aktMausPunkt.x > insLinks + (i+1)* ABSTAND + i*bildBreite && aktMausPunkt.x < insLinks + (i+1)*ABSTAND + (i+1)* bildBreite &&
aktMausPunkt.y > insOben + (j+1)* ABSTAND + j*bildHoehe && aktMausPunkt.y < insOben + (j+1)*ABSTAND + (j+1)*bildHoehe )
{
x = i;
y = j;
this.feld1 = x; // Speichert den angklickten Punkt in der Klassenvariablen
this.feld2 = y; // Speichert den angklickten Punkt in der Klassenvariablen
}
// wenn kein Feld getroffen wurde (d.h. es wurde ins Wasser neben den Schiffen geklickt) wird auch nix eingetragen
// anderfalls wird das jeweilige Feld in der Sichtbarkeitsmatrix auf true gesetzt, d.h. an dieser Stelle kann der
// Eintrag im Spielfeld (sp-Matrix) ausgegeben werden
if ( x != -1) // Feld getroffen
// der angelickte Punkt wird als true in der Sichtbarkeitsmatrix wird auf true gesetzt
sm[x][y] = true;
System.out.println("getroffen: "+ (x+1) + " - " + (y+1));
}
// Gibt die Klassenvariable zurück. Hab das müssen so programmieren da der Compiler es bei
// mir anders nicht gemacht hat
private int xKoordinate()
{
return this.feld1;
}
// Gibt die Klassenvariable zurück.
private int yKoordinate()
{
return this.feld2;
}
private void scoreBerechnen()
{
// Gibt den Wert des Arrays zurück auf den geklickt wurde
int bildKoordinate = spielFeld[xKoordinate()][yKoordinate()];
// Jetzt wird noch je nach Klick der Score ausgerechnet und der Schiffsfeldzähler
// um 1 herabgesetzt, damit später (wenn der Schiffsfeldzähler bei 0 angekommen ist
// die Eingabeaufforderung, das Ausgaben des Scores und das Speichern des Scores
// in einer Datei ausgeführt werden kann -> siehe Paint()
if(bildKoordinate == 0)
{
scoreZähler = scoreZähler -2;
}
if(bildKoordinate == 1)
{
scoreZähler = scoreZähler +1;
schiffsfeldzaehler--;
}
if(bildKoordinate == 2)
{
scoreZähler = scoreZähler +2;
schiffsfeldzaehler--;
}
if(bildKoordinate == 3)
{
scoreZähler = scoreZähler +3;
schiffsfeldzaehler--;
}
if(bildKoordinate == 4)
{
scoreZähler = scoreZähler +4;
schiffsfeldzaehler--;
}
if(bildKoordinate == 5)
{
scoreZähler = scoreZähler +5;
schiffsfeldzaehler--;
}
System.out.println("Aktueller Score: " + scoreZähler);
System.out.println("Verbleibende Schiffsfelder: " + schiffsfeldzaehler);
System.out.println();
ausgabe = "Punktestand: " + scoreZähler;
}
public void paint(Graphics gra)
{
if(schiffsfeldzaehler > 0)
{
// die x-Koordinate des lo-Ecks des Bildes wird errechnet: Inset-Wert plus (selbstdefinierter) ABSTAND
int aktX=ABSTAND + getInsets().left;
// die y-Koordinate des lo-Ecks des Bildes wird errechnet: Inset-Wert plus (selbstdefinierter) ABSTAND
int aktY = ABSTAND + getInsets().top;
// nun werden für alle möglichekn Koordinatenwertepaare das jeweilige bild angezeigt
// für alle Zeilen und für alle Spalten einer Zeile wird mit bildSuchen das für
// den Koordinateneintrag passende Bild gesucht und an der errechneten Stelle ausgegeben
for ( int j = 0; j < MAXZEILE; j++)
{
for (int i = 0; i < MAXSPALTE; i++)
{
// bildSuchen gibt das passende Bild für die Koordinaten zurück
// aktX und aktY sind die errechneten Pixel-Koordinaten des Bildecks links oben
gra.drawImage( bildSuchen(i,j),aktX, aktY,this);
aktX += bild0.getWidth(this) + ABSTAND; // x weiterschalten
maxX = aktX;
}
aktY += bild0.getHeight(this) + ABSTAND;// y weiterschalten
aktX=ABSTAND + getInsets().left;
}
aktX = maxX + getInsets().right;
aktY = aktY + getInsets().bottom;
this.setSize(aktX, aktY); // und das Fester wird auf die neue Größe eingestellt
}
if(schiffsfeldzaehler == 0)
{
gra.setColor(new Color(188,0,0));
gra.setFont(f);
//ausgabe = "Punktestand: " + scoreZähler;
gra.drawString(ausgabe, x, y);
this.setSize(200, 200);
try
{
PrintWriter f = new PrintWriter(new BufferedWriter(new FileWriter("highscore.txt")));
System.out.print("Bitte geben Sie Ihren Name ein: ");
name = stdin.readLine();
highsc = name + " " + ausgabe;
f.println(highsc);
f.close();
}
catch (IOException ex) {};
}
if(schiffsfeldzaehler < 0)
{
gra.setColor(new Color(188,0,0));
gra.setFont(f);
this.setSize(200, 200);
try
{
FileReader f = new FileReader("highscore.txt");
while ((c = f.read()) != -1)
{
int z = 0;
char highscArr[];
highscArr[z]=(char)c;
z++;
}
f.close();
gra.drawString("HIGHSCORELISTE", x, y);
gra.drawString(ausgabe, x, y);
}
catch (IOException ex) {};
}
}
/*
aus paint() ausgegliederte Methode - um paint() nicht riesig werden zu lassen
errechnet aus den x, und y Koordinaten in der Spiele-Matrix - nicht den Mauskoordinaten(!!)
*/
Image bildSuchen(int x, int y)
{
int matrixWert = spielFeld[x][y];
if( sm[x][y]) // Eintrag in Sichtbar-Matrix ist true - Feld soll sichtbar sein
switch(matrixWert)
{
case 0: return bildT;
case 1: return bild1;
case 2: return bild2;
case 3: return bild3;
case 4: return bild4;
case 5: return bild5;
}
else
return bild0;
return bild0;
}
class myMausListener extends MouseAdapter
{
public void mousePressed(MouseEvent event)
{
SchiffeVersenken fenster = (SchiffeVersenken) event.getSource();
Point aktPoint = new Point(event.getX(), event.getY());
fenster.addPunkt(aktPoint);
fenster.feldBerechnen();
fenster.scoreBerechnen();
fenster.repaint();
zaehler++;
}
}
}