# Spiel Kniffel: Gesamtes Array untersuchen.



## Hjal (1. Aug 2016)

Hallo zusammen,
Ich habe vor kurzem angefangen Java zu lernen und habe mir als Übungsaufgabe gestellt, dass Spiel Kniffel in etwas vereinfachter Form in Java zu programmieren. Natürlich ersteinmal nur über die Konsole.
Ich habe eine Klasse Spieler erstellt, inder ich den Aktuellen Spielstand einspeichern kann und eine Klasse Wuerfeln, inder ich 5 zufällige Zahlen generiere (zwischen 1 und 6). Diese sollen ein wurf mit 5 Würfeln simulieren.

Nun zu meinem Problem. Nach den Würfen gibt der Nutzer ein in welches Feld sein Ergebnis gespeichert werden soll z.B. ein Full House. Das Programm soll anschließend überprüfen ob die 5 "Würfel" auch tatsächlich ein Full House(3 gleiche Zahlen und 2 andere gleiche Zahlen) ergeben.

Die 5 generierten Würfelaugen habe ich in einem Array gespeichert:

int[] wuerfel = new int[5];
wuerfel[0] = randomZahl();
wuerfel[1] = randomZahl();
wuerfel[2] = randomZahl();
wuerfel[3] = randomZahl();
wuerfel[4] = randomZahl();

Gibt es einen einfachen Weg wie ich die Zahlen in dem Array auf folgende Fälle untersuchen kann?

Dreier Pasch  -->  mind. drei gleiche Zahlen    z.B 1, 5, 5, 2, 5
Vierer Pasch  -->  mind. vier gleiche Zahlen    z.B 3, 3, 2, 3, 3
Full House   -->  drei gleiche Zahlen + zwei gleiche Zahlen   z.B. 4, 4, 3, 3, 3
kleine Straße --> mind. vier aufeinanderfolgende Zahlen   z.B   1, 3, 4, 2, 6
Große Straße --> fünf aufeinanderfolgende Zahlen   z.B  1, 3, 4, 2, 5

Ich hoffe ich konnte das Problem einigermaßen gut darstellen und hoffe das einer von euch eine Idee hat 

LG Hjal


----------



## dayaftereh (1. Aug 2016)

Ich würde das Array immer erstmal sortieren. Das hilft aber nicht gehen die ganzen Fall Unterscheidung. Ich denke du musst das Naive runter implementiern.


----------



## Hjal (1. Aug 2016)

Ok, Danke. Das Sortieren hilft auf jeden Fall schonmal


----------



## mrBrown (1. Aug 2016)

Sortiere und gleiche und aufeinanderfolgende Zählen.
Und dann nur noch ein switch/if wie viele es jeweils sind.


----------



## Hjal (1. Aug 2016)

Danke wird gemacht.


----------



## dayaftereh (1. Aug 2016)

Was du auch machen kannst ist für die sortieren Kombinationen einen eindeutigen HashCode berechnen. Den HashCode kannst du dann in einer Json, Xml oder Properties Datei abspeichern und auf FullHouse, Straße oder co abbilden.

Damit sparst du dir die häßlich if's bzw swiches. Ich würde behaupten dass es viel performanter ist, da du ein einfach lookup in na HashMap machen musst.


----------



## JCODA (1. Aug 2016)

Also... das geht auch einfacher!

```
int[] wuerfel = new int[5];
int[] anzahlWuerfe= new int[6];
for (int i = 0; i < wuerfel.length; i++){
     wuerfel[i] = getRandomNumber();//Liefert 0 bis einschließlich 5
     anzahlWuerfe[wuerfel[i]]++;
}
```
Nun steht bei anzahlWuerfe[index] drin, wie oft index gewürfelt wurde. 

Dreier Pasch ist dann, ob 3 in anzahlWuerfe liegt... 
Full House ist, ob 3 und 2 drin liegt...
Ich finde diese Art sehr viel eleganter, als HashMaps, externe Dateien usw...


----------



## mrBrown (1. Aug 2016)

JCODA hat gesagt.:


> Also... das geht auch einfacher!
> 
> ```
> int[] wuerfel = new int[5];
> ...


Stimmt, sortieren vorm zählen kann man sich sparen. Straße wäre dann 0 nur an Anfang/Ende



JCODA hat gesagt.:


> Ich finde diese Art sehr viel eleganter, als HashMaps, externe Dateien usw...



Dürfte auch schneller sein, und vor allem schneller umzusetzen, man spart sich das händische Eintragen von zig Würfen


----------



## Hjal (1. Aug 2016)

Vielen Dank, jetzt funktioniert alles


----------



## Xyz1 (1. Aug 2016)

Ich werfe einfach mal mit Code um sich:

```
private static boolean drei(int[] gewuerfelt) {
        int[] anzahl = new int[7];
        for (int i : gewuerfelt) {
            anzahl[i]++;
        }
        for (int i : anzahl) {
            if (i == 3) {
                return true;
            }
        }
        return false;
    }

    private static boolean vier(int[] gewuerfelt) {
        int[] anzahl = new int[7];
        for (int i : gewuerfelt) {
            anzahl[i]++;
        }
        for (int i : anzahl) {
            if (i == 4) {
                return true;
            }
        }
        return false;
    }

    private static boolean full(int[] gewuerfelt) {
        int[] anzahl = new int[7];
        for (int i : gewuerfelt) {
            anzahl[i]++;
        }
        boolean b2 = false, b3 = false;
        for (int i : anzahl) {
            if (i == 2) {
                b2 = true;
            }
            if (i == 3) {
                b3 = true;
            }
            if (b2 && b3) {
                return true;
            }
        }
        return false;
    }

    @NotImplementedYet
    private static boolean klein(int[] gewuerfelt) {
        throw new UnsupportedOperationException();
    }

    private static boolean gross(int[] gewuerfelt) {
        gewuerfelt = Arrays.copyOf(gewuerfelt, gewuerfelt.length);
        Arrays.sort(gewuerfelt);
        for (int i = 0; i < gewuerfelt.length - 1; i++) {
            if (gewuerfelt[i] != gewuerfelt[i + 1] - 1) {
                return false;
            }
        }
        return true;
    }
```

Wegen `klein` schaue mal hier: http://stackoverflow.com/questions/15671620/small-straight-method

Das Problem ist, dass vier auch drei sein kann, full auch drei sein kann und gross auch klein sein kann . . . . Deswegen in umgekehrter Reihenfolge:

```
if (gross(ia)) {
                System.out.println("gross");
            }
//            if (klein(ia)) {
//                System.out.println("klein");
//            }
            if (full(ia)) {
                System.out.println("full");
            }
            if (vier(ia)) {
                System.out.println("vier");
            }
            if (drei(ia)) {
                System.out.println("drei");
            }
```

Mit if und Else ! ! ! !


----------



## Xyz1 (1. Aug 2016)

Sorry, drei kann auch vier sein, drei kann auch full sein und klein kann auch groß sein. :S

Insgesamt ist das wohl ziemlich Frikadelle, also besser das mit dem Hash. (vorher aber bitte Sortieren)


----------



## Hjal (2. Aug 2016)

Habe beim Würfel jetzt den Counter für die Anzahl genommen wie JCODA vorgeschlagen.

Für das Auswerten habe ich folgendes gemacht:

```
boolean isDreierTrue = false;
isDreierTrue = IntStream.of(var.anzahlWuerfe).anyMatch(x -> x >= 3);

boolean isViererTrue = false;
isViererTrue = IntStream.of(var.anzahlWuerfe).anyMatch(x -> x == 4);

boolean isFullHouseTrue = false;
isFullHouseTrue = IntStream.of(var.anzahlWuerfe).anyMatch(x -> x == 3) && IntStream.of(var.anzahlWuerfe).anyMatch(x -> x == 2);

boolean isHitTrue = false;
isFullHouseTrue = IntStream.of(var.anzahlWuerfe).anyMatch(x -> x == 5);
```


Vielleicht gibt es elegantere Lösungen aber es funktioniert auf jeden Fall 

Noch eine kleiner andere Frage, wie kann ich den Code wie bei euch in ein eigenes Feld schreiben?


----------



## InfectedBytes (2. Aug 2016)

Hjal hat gesagt.:


> Noch eine kleiner andere Frage, wie kann ich den Code wie bei euch in ein eigenes Feld schreiben?


siehe Signatur von @DerWissende


----------



## Hjal (2. Aug 2016)

thx


----------



## Xyz1 (2. Aug 2016)

Hast du dir den Link von SO angeguckt?
http://stackoverflow.com/questions/15671620/small-straight-method

4er Straße stellt wirklich ein Problem dar...
(Es beschreibt exakt deine Fragestellung...)


----------



## Blender3D (3. Aug 2016)

```
import java.util.Random;

public class Dices {
    private int[] result = new int[6];
    private final int NUM_DICES = 5;

    public void clear() {
        for (int i = 0; i < result.length; i++)
            result[i] = 0;
    }

    private boolean isConnectedCount(int num) {
        int cnt = 0;
        for (int i = 0; i < result.length; i++) {
            cnt = (result[i] == 0) ? 0 : cnt + 1;
            if (cnt == num)
                return true;
        }
        return false;
    }

    public int[] getResult() {
        return result;
    }

    public boolean isBigStreet() {
        return isConnectedCount(5);
    }

    public boolean isFourOfAKind() {
        for (int i = 0; i < result.length; i++) {
            if (result[i] == 4)
                return true;
        }
        return false;
    }

    public boolean isFullHouse() {
        if (!isThreeOfAKind())
            return false;
        for (int i = 0; i < result.length; i++) {
            if (result[i] == 2)
                return true;
        }
        return false;
    }

    public boolean isSmallStreet() {
        return isConnectedCount(4);
    }

    public boolean isThreeOfAKind() {
        for (int i = 0; i < result.length; i++) {
            if (result[i] == 3)
                return true;
        }
        return false;
    }

    public void rollDice() {
        Random rnd = new Random(System.currentTimeMillis());
        clear();
        for (int i = 0; i < NUM_DICES; i++)
            result[Math.abs(rnd.nextInt() % 6)]++;
    }

    @Override
    public String toString() {
        StringBuffer tmp = new StringBuffer();
        for (int i = 0; i < result.length; i++) {
            int cnt = result[i];
            while (cnt > 0) {
                tmp.append("[" + (i + 1) + "] ");
                cnt--;
            }
        }
        return tmp.toString();
    }
}
```
So könnte man es auch machen!


----------

