# Minesweeper Java



## btl1903 (12. Okt 2017)

Hallo! Ich muss das Spiel Minesweeper in Java programmieren. Da ich nicht so gut beim Programmieren bin, habe ich keine Idee, wie ich überhaupt anfangen soll.

Die Angabe lautet so: 

Stick to the following format:

Sample input    Sample output
(from file)     (to System.out)

4 4             Field: 1
*...            *100
....            2210
.*..            1*10
....             1110
3 5             Field: 2
**...           **100
.....           33200
.*...           1*100
0 0             22


Additionally, your programm shall implement the following interface, where the return value of the method minesweep shall be the sum of all integers in the output fields (for the example above, this is 22):

import java.io.File;

public interface Assignment1 {
   public long minesweep(File inputfile);
}

Note: do not use the Java 'package' statement.

Wie sollte ich anfangen oder was sollte ich grundsätzlich machen?


----------



## krgewb (12. Okt 2017)

Deine Werte in Monospace-Schrift:

```
4 4 Field:

*...  *100
....  2210
.*..  1*10
....  1110


3 5 Field:

**...  **100
.....  33200
.*...  1*100
```

So wie ich das verstehe musst du kein spielbares Spiel programmieren sondern nur das Feld mit den Ziffern ausgeben.
In der Datei, die gegeben ist sind nur Punkte und Sterne. Punkte stehen für sichere Felder. Sterne stehen für Minen.
Hier gibt es solch eine Aufgabenstellung auf deutsch, sogar mit denselben Zahlen: http://www.programmierkurs-java.de/materialien/Aufgaben/UE17-Aufgaben.pdf (Aufgabe 43).


----------



## thet1983 (12. Okt 2017)

btl1903 hat gesagt.:


> Sample input Sample output
> (from file) (to System.out)





krgewb hat gesagt.:


> So wie ich das verstehe musst du kein spielbares Spiel programmieren sondern nur das Feld mit den Ziffern ausgeben.


Denke ich auch...

@krgewb 
Danke für den Link. Bin seit zwei Tagen Projektlos, jetzt kann ich mir das mal anschauen..


----------



## btl1903 (14. Okt 2017)

ich hab derzeit folgenden Code:


```
import java.io.File;
import java.io.*;
import java.util.Scanner;

public interface Assignment1 {
    public long minesweep(File inputfile);
  

    public static void main(String[] args) throws FileNotFoundException  {

        Scanner in = null;
       
        try{
            in  = new Scanner(new BufferedReader(new FileReader("input.txt")));
  
            int zaehler=1;
            char [][] feld;
            int width;
            int height;

            while(in.hasNextLine()){
                if(in.hasNextInt()){
                    int i = in.nextInt();
                    int j = in.nextInt();
                    feld = new char [i][j];
                    width=i;
                    height=j;
                    System.out.println("Field:" + zaehler);   
                    zaehler++;
                }
              
                else{
                    in.nextLine();
                    if (in.hasNext()){
                        String a=in.next();
                        System.out.println(a);
                    }
                }
            }    
        }
        finally{
            in.close(); 
        }          
    }
}
```

Hab ein Zähler für die Angabe der Felder. Danach liest das Programm die input file und gibt eigentlich nur die gleiche Eingabe wieder aus. Ich komme nicht weiter, wie ich jetzt zu den Zahlen kommen soll. Da muss ich ja die 8 Nachbarfelder überprüfen und die Zahl der Mienen angeben. Aber wie soll ich das machen? Derzeit wo steht "Field: 3" muss am Ende die Summe aller ganzen Zahlen in der Ausgabe stehen.


----------



## krgewb (14. Okt 2017)

btl1903 hat gesagt.:


> Danach liest das Programm die input file und gibt eigentlich nur die gleiche Eingabe wieder aus.


Dein Programm müsste demnach

```
*...
....
.*..
....
```
ausgeben aber derzeit gibt es folgendes aus:

```
....
.*..
....
```
Es fehlt also die erste Zeile. Ich helfe dir per PN.


----------



## krgewb (14. Okt 2017)

input.txt:

```
**...
.....
.*...
```

Assignment1:

```
package de.hrw;

import java.io.*;

public interface Assignment1 {
    public long minesweep(File inputfile);

    public static void main(String[] args) throws FileNotFoundException {

        int height = 0;
        int width = 0;
        BufferedReader br;

        // Die Datei wird eingelesen damit die height und width herausgefunden
        // werden koennen.
        // Dies ist notwendig, weil Hoehe und Breite von Arrays nachtraeglich
        // nicht
        // vergroessert werden koennen.

        try {
            br = new BufferedReader(new FileReader("input.txt"));
            try {
                String x;

                // Die Schleife wird fuer alle Zeilen in der Datei
                // durchlaufen.
                while ((x = br.readLine()) != null) {
                    if (x.equals("") == false) {
                        // Anzahl der Zeilen um 1 erhoehen.
                        height++;
                        // Anzahl der Spalten setzen.
                        width = x.length();
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }

        if (height == 0) {
            System.out.println("FEHLER. Die Anzahl der Spalten ist 0.");
            return;
        }

        if (width == 0) {
            System.out.println("FEHLER. Die Anzahl der Spalten ist 0.");
            return;
        }

        char[][] feld = new char[height][width];

        // Die Datei wird noch einmal eingelesen und die Zeichen werden
        // in dem feld-Array gespeichert.

        try {
            br = new BufferedReader(new FileReader("input.txt"));
            try {
                String x;

                // i ist die Nummer der Spalte
                int i = 0;

                // Die Schleife wird fuer alle Zeilen in der Datei
                // durchlaufen.
                while ((x = br.readLine()) != null) {
                    if (x.equals("") == false) {
                        // j ist der index des Zeichens (ganz links = 0)
                        for (int j = 0; j < x.length(); j++) {
                            // Zeichen in das Array speichern.
                            feld[i][j] = x.charAt(j);
                        }

                        i++;
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }

        // Fuer das neue Array wird int als Datentyp verwendet.
        // Alternativ kann mit einem char-Array und ASCII-Tabelle
        // ( http://www.chip.de/ii/1/2/5/4/9/5/8/0/ascii-93c823e7009f26b0.png )
        // gearbeitet werden.
        int[][] feldNEU = new int[height][width];

        // Nun wird fuer jedes Kaestchen geschaut, wieviele Nachbar-Kaestchen
        // Minen haben.
        for (int i = 0; i < height; i++) {

            for (int j = 0; j < width; j++) {

                // Falls das Kaestchen eine Mine enthaelt wird -1 gespeichert.
                if (feld[i][j] == '*') {
                    feldNEU[i][j] = -1;
                }

                else {

                    int anzahlMinen = 0;

                    // Es muessen die acht Nachbarfelder betrachtet werden.
                    // Davor muss jedoch geschaut werden, ob es solch ein
                    // Nachbarfeld ueberhaupt gibt. Das Feld oben links hat z.B.
                    // keinen Nachbarn oben, keinen Nachbarn links und keinen
                    // Nachbarn oben links.

                    // Oben links
                    if (i > 0 && j > 0) {
                        if (feld[i - 1][j - 1] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Oben
                    if (i > 0) {
                        if (feld[i - 1][j] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Oben rechts
                    if (i > 0 && j < width - 1) {
                        if (feld[i - 1][j + 1] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Links
                    if (j > 0) {
                        if (feld[i][j - 1] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Rechts
                    if (j < width - 1) {
                        if (feld[i][j + 1] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Unten links
                    if (i < height - 1 && j > 0) {
                        if (feld[i + 1][j - 1] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Unten
                    if (i < height - 1) {
                        if (feld[i + 1][j] == '*') {
                            anzahlMinen++;
                        }
                    }

                    // Unten rechts
                    if (i < height - 1 && j < width - 1) {
                        if (feld[i + 1][j + 1] == '*') {
                            anzahlMinen++;
                        }
                    }

                    feldNEU[i][j] = anzahlMinen;
                }

            }

        }

        int summeAllerZahlen = 0;

        // Die Summe der Zahlen berechnen.
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < height; j++) {
                if (feldNEU[i][j] > 0) {
                    summeAllerZahlen += feldNEU[i][j];
                }
            }
        }

        System.out.println(height + " " + width + " Field: " + summeAllerZahlen);

        for (int i = 0; i < height; i++) {

            // In der Ausgabe sollen beide Tabellen nebeneinander sein.
            // Dazu werden zwei for-Schleifen benoetigt.

            for (int j = 0; j < width; j++) {
                System.out.print(feld[i][j]);
            }

            // Zwei Leerzeichen
            System.out.print("  ");

            for (int j = 0; j < width; j++) {
                // Falls der Wert -1 ist soll ein Sternchen ausgegeben werden.
                // Anderenfalls soll der Wert ausgegeben werden.
                if (feldNEU[i][j] == -1) {
                    System.out.print("*");
                } else {
                    System.out.print(feldNEU[i][j]);
                }
            }

            // Zeilenumbruch
            System.out.print("\n");
        }

    }
}
```

Ausgabe:

```
3 5 Field: 11
**...  **100
.....  33200
.*...  1*100
```


----------



## btl1903 (15. Okt 2017)

krgewb hat gesagt.:


> Dein Programm müsste demnach
> 
> ```
> *...
> ...




meine Ausgabe lautet so:

```
Field:1
*...
....
.*..
....
Field:2
**...
.....
.*...
Field:3
```

die erste zeile fehlt nicht..


----------



## krgewb (15. Okt 2017)

@thet1983 Hast du eine Idee, wie man es programmieren kann?


----------



## thet1983 (16. Okt 2017)

deine lösung ist doch e korrekt...


----------



## krgewb (16. Okt 2017)

Wenn sie meinen Code ausführt kommt folgende Meldung:

```
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at de.hrw.Assignment1.main(Assignment1.java:72)
```


----------



## VfL_Freak (16. Okt 2017)

Moin,


krgewb hat gesagt.:


> at de.hrw.Assignment1.main(Assignment1.java:72)


aha, und welches ist Zeile 72 ??
Auf jeden Fall tritt dort die Exception auf !!

VG Klaus


----------



## btl1903 (16. Okt 2017)

der code funktioniert eigentlich, aber sobald ich einen längeren input benutze, bekomme ich eine ArrayIndexOutOfBoundsException. Der input muss doch beliebig sein also, darf ich zum beispiel auch so ein input haben, oder: 

```
*.*...*
.*...*.
.*.*..*
..*..*.
*.*.*..
*.*...*
*.*.*..
*.*...*
```


----------



## VfL_Freak (16. Okt 2017)

nun, Dein Input ist halt länger als Dein Array ....


VfL_Freak hat gesagt.:


> welches ist Zeile 72 ??
> Auf jeden Fall tritt dort die Exception auf !!



VG Klaus


----------



## thet1983 (16. Okt 2017)

krgewb hat gesagt.:


> feld[i][j] = x.charAt(j);


kommt hier die exception?


----------



## btl1903 (16. Okt 2017)

eigentlich müssen input und output so aussehen:

```
input:        output:

4 4            Field: 1
*...            *100
....             2210
.*..            1*10
....             1110
3 5            Field: 2 
**...          **100
.....            33200
.*...           1*100
0 0            22           // wenn 0x0, dann soll die Summe aller Zahlen ausgegeben werden
```

also soll im input schon stehen wie groß mein array sein soll.


----------



## thet1983 (16. Okt 2017)

```
// input.txt
*.*...*
.*...*.
.*.*..*
..*..*.
*.*.*..
*.*...*
*.*.*..
*.*...*
```


```
// output
8 7 Field: 103
*.*...*   *3*112*
.*...*.    3*422*3
.*.*..*   2*4*33*
..*..*.    24*43*2
*.*.*..   *5*4*32
*.*...*   *6*523*
*.*.*..   *6*4*32
*.*...*   *4*312*
```

was ist daran falsch?


----------



## btl1903 (16. Okt 2017)

Beispiel input.txt:

```
4 4
*.*.
.*..
.*.*
..*.
3 5
**...          
.....          
.*...         
0 0
```

output:

```
Field: 1
*100
2210
1*10
1110
Field: 2
**100
33200
1*100
22   //Summe aller Zahlen
```

der input muss eigentlich anders sein!


----------



## btl1903 (16. Okt 2017)

also ich habe folgenden input:

```
4 4
*.*.
.*..
.*.*
*.*.
3 5
**...        
.....        
.*...       
0 0
```

Das programm soll wissen, dass ich ein 4x4 und ein 3x5 feld habe, danach die zeichen lesen und die Zahlen ausgeben. Wenn ich ein 0x0 feld habe, soll die summe aller zahlen ausgegeben werden.

mein output sollte dann so aussehen: 


```
Field: 1
*100
2210
1*10
1110
Field: 2
**100
33200
1*100
22   //Summe aller Zahlen
```

also ich sollte ein zähler für die felder haben, und am ende die summe aller zahlen.

ich habe jetzt dein Code bisschen umgeformt, so dass ich den Feldzähler habe. Aber es funktioniert trotzdem irgendwas nicht. Das programm kann ab der zweiten Zeile die Zeichen * und . nicht lesen denk ich.


----------



## thet1983 (16. Okt 2017)

was sagt der debugger?


----------



## btl1903 (16. Okt 2017)

ich bekomme diese Ausgabe:

```
Field:1
Field:2
Field:3
FEHLER. Die Anzahl der Zeilen ist 0.
```

Statt Field: 3 muss eigentlich die summe der zahlen stehen, aber das muss ich noch ändern.

Wenn ich ein paar sachen ändere, bekomme ich eine ArrayIndexOutOfBoundsException


----------



## krgewb (16. Okt 2017)

btl1903 hat gesagt.:


> also soll im input schon stehen wie groß mein array sein soll.


Achso, dann habe ich es falsch verstanden!


----------



## krgewb (16. Okt 2017)

Ich verbessere es gerade.


----------



## krgewb (17. Okt 2017)

So. Jetzt sollte alles funktionieren.

input.txt:

```
4 4
*...
....
.*..
....
3 5
**...
.....
.*...
0 0
```

Assignment1:

```
import java.io.*;
import java.util.ArrayList;

public interface Assignment1 {
    public long minesweep(File inputfile);

    public static void main(String[] args) throws FileNotFoundException {

        BufferedReader br;

        int summeAllerZahlen = 0;

        ArrayList<String> dateiInhalt = new ArrayList<String>();

        ArrayList<char[][]> arrays = new ArrayList<char[][]>();

        // Fuer die Arrays mit den neuen Feldern (fuer Output) wird int als
        // Datentyp verwendet. Alternativ kann mit einem char-Array und
        // ASCII-Tabelle (
        // http://www.chip.de/ii/1/2/5/4/9/5/8/0/ascii-93c823e7009f26b0.png )
        // gearbeitet werden.
        ArrayList<int[][]> arraysNEU = new ArrayList<int[][]>();

        // Die Datei wird eingelesen und der komplette Inhalt wird in einer
        // ArrayList gespeichert.

        try {
            br = new BufferedReader(new FileReader("input.txt"));
            try {
                String x;

                // Die Schleife wird fuer alle Zeilen in der Datei
                // durchlaufen.
                while ((x = br.readLine()) != null) {
                    // trim entfernt fuehrende und nachfolgende Leerzeichen
                    x = x.trim();
                    if (x.equals("") == false) {
                        dateiInhalt.add(x);
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }

        // Nun wird die ArrayList mit dem Dateiinhalt durchgeguckt und geschaut,
        // ob die einzelnen Zeilen Ziffern enthalten. Aufgrund der Informationen
        // werden arrays erstellt (aber noch nicht befuellt) und zu
        // einer ArrayList namens arrays hinzugefuegt.

        for (int i = 0; i < dateiInhalt.size(); i++) {

            String einzelneZeile = dateiInhalt.get(i);

            if (StringEnthaeltMindestensEineZiffer(einzelneZeile) == true) {

                // In solch einer Zeile sind ja zwei Werte hinterlegt. Diese
                // sind durch ein Leerzeichen getrennt. Mithilfe der
                // split-Methode koennen die Werte herausgepickt werden.
                String[] hoeheUndBreite = einzelneZeile.split(" ");

                int height = Integer.parseInt(hoeheUndBreite[0]);
                int width = Integer.parseInt(hoeheUndBreite[1]);

                if (height > 0 && width > 0) {
                    char[][] feld = new char[height][width];
                    arrays.add(feld);

                    int[][] feldNEU = new int[height][width];
                    arraysNEU.add(feldNEU);
                }

            }
        }

        int wievielteZeileMitAngabenZuHoeheUndBreite = 0;

        // Nun wird die ArrayList nochmals durchgeguckt und es werden die arrays
        // befuellt.
        for (int i = 0; i < dateiInhalt.size(); i++) {

            String einzelneZeile = dateiInhalt.get(i);

            if (StringEnthaeltMindestensEineZiffer(einzelneZeile) == true) {

                wievielteZeileMitAngabenZuHoeheUndBreite++;

                if (wievielteZeileMitAngabenZuHoeheUndBreite > arrays.size()) {
                    continue;
                }

                char[][] array = arrays.get(wievielteZeileMitAngabenZuHoeheUndBreite - 1);

                int height = array.length;
                int width = array[0].length;

                if (height > 0 && width > 0) {

                    for (int k = 1; k < height + 1; k++) {

                        String ganzeZeileMitPunktenUndSternen = dateiInhalt.get(i + k);

                        for (int m = 0; m < width; m++) {
                            array[k - 1][m] = ganzeZeileMitPunktenUndSternen.charAt(m);
                        }
                    }
                }

            }

        }

        for (int p = 0; p < arrays.size(); p++) {

            char[][] aktuellesArray = arrays.get(p);

            int height = aktuellesArray.length;
            int width = aktuellesArray[0].length;

            int[][] aktuellesArrayNEU = arraysNEU.get(p);

            // Nun wird fuer jedes Kaestchen geschaut, wieviele
            // Nachbar-Kaestchen Minen haben.
            for (int i = 0; i < height; i++) {

                for (int j = 0; j < width; j++) {

                    // Falls das Kaestchen eine Mine enthaelt wird -1
                    // gespeichert.
                    if (aktuellesArray[i][j] == '*') {
                        aktuellesArrayNEU[i][j] = -1;
                    }

                    else {

                        int anzahlMinen = 0;

                        // Es muessen die acht Nachbarfelder betrachtet werden.
                        // Davor muss jedoch geschaut werden, ob es solch ein
                        // Nachbarfeld ueberhaupt gibt. Das Feld oben links hat
                        // z.B. keinen Nachbarn oben, keinen Nachbarn links und
                        // keinen Nachbarn oben links.

                        // Oben links
                        if (i > 0 && j > 0) {
                            if (aktuellesArray[i - 1][j - 1] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Oben
                        if (i > 0) {
                            if (aktuellesArray[i - 1][j] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Oben rechts
                        if (i > 0 && j < width - 1) {
                            if (aktuellesArray[i - 1][j + 1] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Links
                        if (j > 0) {
                            if (aktuellesArray[i][j - 1] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Rechts
                        if (j < width - 1) {
                            if (aktuellesArray[i][j + 1] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Unten links
                        if (i < height - 1 && j > 0) {
                            if (aktuellesArray[i + 1][j - 1] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Unten
                        if (i < height - 1) {
                            if (aktuellesArray[i + 1][j] == '*') {
                                anzahlMinen++;
                            }
                        }

                        // Unten rechts
                        if (i < height - 1 && j < width - 1) {
                            if (aktuellesArray[i + 1][j + 1] == '*') {
                                anzahlMinen++;
                            }
                        }

                        aktuellesArrayNEU[i][j] = anzahlMinen;
                    }

                }

            }

            int summeAllerZahlenEinesArrays = 0;

            // Die Summe der Zahlen berechnen.
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (aktuellesArrayNEU[i][j] > 0) {
                        summeAllerZahlenEinesArrays += aktuellesArrayNEU[i][j];
                    }
                }
            }

            summeAllerZahlen += summeAllerZahlenEinesArrays;

            System.out.print(HoleDieSoundsovielteZeileMitAngabenZuHoeheUndBreite(dateiInhalt, p + 1));
            System.out.print("  Field: " + summeAllerZahlenEinesArrays + "\n");

            for (int i = 0; i < height; i++) {

                // In der Ausgabe sollen beide Tabellen nebeneinander sein. Dazu
                // werden zwei for-Schleifen benoetigt.

                for (int j = 0; j < width; j++) {
                    System.out.print(aktuellesArray[i][j]);
                }

                // Zwei Leerzeichen
                System.out.print("  ");

                for (int j = 0; j < width; j++) {
                    // Falls der Wert -1 ist soll ein Sternchen ausgegeben
                    // werden. Anderenfalls soll der Wert ausgegeben werden.
                    if (aktuellesArrayNEU[i][j] == -1) {
                        System.out.print("*");
                    } else {
                        System.out.print(aktuellesArrayNEU[i][j]);
                    }
                }

                // Zeilenumbruch
                System.out.print("\n");
            }

        }

        for (int i = 0; i < dateiInhalt.size(); i++) {
            if (dateiInhalt.get(i).equals("0 0")) {
                System.out.print(dateiInhalt.get(i) + "  " + summeAllerZahlen);
            }
        }

    }

    public static boolean StringEnthaeltMindestensEineZiffer(String einzelneZeile) {

        for (int i = 0; i < einzelneZeile.length(); i++) {

            Character c = einzelneZeile.charAt(i);

            // Sobald eine Ziffer gefunden worden ist wird true zurueckgegeben.
            if (Character.isDigit(c)) {
                return true;
            }
        }

        return false;
    }

    public static String HoleDieSoundsovielteZeileMitAngabenZuHoeheUndBreite(ArrayList<String> dieArrayList, int n) {

        int wievielteZeileMitAngabenZuHoeheUndBreite = 0;

        for (int i = 0; i < dieArrayList.size(); i++) {

            if (StringEnthaeltMindestensEineZiffer(dieArrayList.get(i))) {
                wievielteZeileMitAngabenZuHoeheUndBreite++;
            }

            if (n == wievielteZeileMitAngabenZuHoeheUndBreite) {
                return dieArrayList.get(i);
            }
        }

        return null;
    }
}
```

Ausgabe:

```
4 4  Field: 11
*...  *100
....  2210
.*..  1*10
....  1110
3 5  Field: 11
**...  **100
.....  33200
.*...  1*100
0 0  22
```


----------



## krgewb (17. Okt 2017)

-


----------



## btl1903 (17. Okt 2017)

krgewb hat gesagt.:


> System.out.print("  Field: " + summeAllerZahlenEinesArrays + "*\n*");



bei Field: ... sollte man eigentlich immer ausgeben, im wie vielten feld wir sind. Also wenn man hier die Variable wievielteZeileMitAngabenZuHoeheUndBreite statt summeAllerZahlenEinesArrays schreibt, kommt in beiden Fällen Field: 3 raus.


----------



## krgewb (17. Okt 2017)

Achso! Entschuldige vielmals. Ich schaue es mir heute an.

Edit: Ich habe es mir angeschaut. Die Zeile muss wie folgt lauten:

```
System.out.print("  Field: " + (p + 1) + "\n");
```


----------



## btl1903 (17. Okt 2017)

Super!! Ich danke dir vielmals!


----------

