# "Prime Game" - Übung



## ienAri (20. Nov 2015)

Hallo zusammen,

da das hier mein erster erstellter Thread in diesem Forum ist, bitte ich vorab um Gnade, falls trotz "Vor dem ersten Posten lesen!" lesen etwas schief gegangen ist.

Zu meinem Problem, im folgenden versuchte ich mich an der Erstellung eines Prime Games, die Regeln des Spiels sind simpel: Zufällig generierte Zahlen werden abwechselnd von Spieler 1 und 2 ausgewählt. Die ausgewählte Zahl bekommt der entsprechende Spieler auf seinem Konto gutgeschrieben, allerdings bekommt der gegnerische Spieler alle generierten Divisoren der gewählten Zahl auf sein Konto addiert.

Ich denke das habe ich relativ präzise umgesetzt. Allerdings hat mein Programm die Eigenart, bei doppelt generierten Zahlen entweder keinen Endkontostand der Spieler, oder den Integer Min Value auszugeben, was ich mir leider nicht erklären kann.

Hier die drei Klassen:

PrimeGame.java

```
public class PrimeGame {

    public static void main(String[] args) {

        int[] spielfeld = new int[20];
        int[] spielerPunkte = new int[2];
        int gesamtWert = 0;

        for (int i = 0; i < spielfeld.length; i++) {
            do {
                spielfeld[i] = (int) (Math.random() * 100);
            } while (spielfeld[i] == 0);
        }

        System.out.println("Die generierten Zahlen lauten wie folgt: ");

        for (int m = 0; m < spielfeld.length; m++) {
            System.out.print(spielfeld[m] + " ");
            gesamtWert = spielfeld[m] + gesamtWert;
        }

        System.out.println("\n\nGesamtwert:\t\t" + gesamtWert + " Punkte");
        System.out.println("==================================");

        for (int n = 0; n < spielfeld.length; n++) {

            Spieler1.zahlWählenSpieler1(spielfeld, spielerPunkte);

            Spieler2.zahlWählenSpieler2(spielfeld, spielerPunkte);

        }
        System.out.println("Spieler 1 hat:\t\t" + spielerPunkte[0] + " Punkte");
        System.out.println("Spieler 2 hat:\t\t" + spielerPunkte[1] + " Punkte");

    }

}
```

Spieler1.java

```
public class Spieler1 {

    public static void zahlWählenSpieler1(int[] spielfeld, int[] spielerpunkte) {

        int groessteZahl = 0;
        int divisorenGesamt = 0;
        int posGewählteZahl = 0;

        do {
            for (int x = 0; x < spielfeld.length; x++) {
                if (groessteZahl <= spielfeld[x]) {
                    groessteZahl = spielfeld[x];
                    posGewählteZahl = x; // Damit wir wissen, welchen Arrayplatz
                                            // wir
                                            // nicht mehr benutzen können.
                }

            }
          
            spielfeld[posGewählteZahl] = 0; // Funktioniert weil sich Methoden &
                                            // richtiges Array Heap-Speicherplatz
                                            // teilen (oder wie das heißt)


            for (int y = 0; y < spielfeld.length; y++) {
                if (spielfeld[y] != 0) {
                    if (groessteZahl % spielfeld[y] == 0) {
                        divisorenGesamt += spielfeld[y];
                    }
                }

            }
        } while (groessteZahl < divisorenGesamt);

        for (int z = 0; z < spielfeld.length; z++) {
            if (spielfeld[z] != 0) {
                if (groessteZahl % spielfeld[z] == 0) {
                    spielfeld[z] = 0;
                }
            }
        }


        spielerpunkte[0] += groessteZahl;
        spielerpunkte[1] += divisorenGesamt;

    }

}
```

Spieler2.java

```
public class Spieler2 {

    public static void zahlWählenSpieler2(int[] spielfeld, int[] spielerpunkte) {

        int groessteZahl = 0;
        int divisorenGesamt = 0;
        int posGewählteZahl = 0;

        do {
            for (int x = 0; x < spielfeld.length; x++) {
                if (groessteZahl <= spielfeld[x]) {
                    groessteZahl = spielfeld[x];
                    posGewählteZahl = x; // Damit wir wissen, welchen Arrayplatz
                                            // wir
                                            // nicht mehr benutzen können.
                }

            }
          
            spielfeld[posGewählteZahl] = 0; // Funktioniert weil sich Methoden &
            // richtiges Array Heap-Speicherplatz
            // teilen (oder wie das heißt)

            for (int y = 0; y < spielfeld.length; y++) {
                if (spielfeld[y] != 0) {
                    if (groessteZahl % spielfeld[y] == 0) {
                        divisorenGesamt += spielfeld[y];
                    }
                }

            }
        } while (groessteZahl < divisorenGesamt);

        for (int z = 0; z < spielfeld.length; z++) {
            if (spielfeld[z] != 0) {
                if (groessteZahl % spielfeld[z] == 0) {
                    spielfeld[z] = 0;
                }
            }
        }



        spielerpunkte[1] += groessteZahl;
        spielerpunkte[0] += divisorenGesamt;

    }

}
```

Vorab, vielen Dank für eure Mühen!


----------



## Khal Drogo (20. Nov 2015)

Hallo.
Du solltest die Klassen Spieler1 und Spieler2 zusammenfassen, da das obere alles andere als objektorientiert ist. Falls das nicht relevant für dich ist, bleibt Punkt 3:
Vereinfachtes Beispiel. Dein Array besteht aus den Einträgen (4, 2, 2), was passiert dann in deiner Spielerklasse? Sofern ich nichts übersehen habe, sollten dir Fehler auffallen.
Mit freundlichen Grüßen
Xelsarion


----------



## ienAri (20. Nov 2015)

Danke für die schnelle Antwort, Spieler 1 und Spieler 2 hätten in der Realität eigenständig angefertigte Methoden die "gegeneinander spielen". Daher die Trennung. Deinen Hinweis schau ich mir jetzt genauer an, danke nochmals!


----------



## Khal Drogo (20. Nov 2015)

Du meinst damit, dass Spieler1 und Spieler2 verschiedene Taktiken implementiert bekommen, oder wie ist das zu verstehen?
Wenn ich das richtig verstehe, würde man dennoch anders an die Sache herangehen, aber so wie es jetzt ist, reicht es ja auch erst mal, wenn die Fehler ausgemerzt wurden.
Kleiner Tipp: Aktuell ist es wirklich vom Zufall abhängig, ob dein Spiel funktioniert, oder nicht. Auch wenn es ein Zufallsspiel (Glücksspiel) sein soll, ist das aber vermutlich nicht, was du erreichen wolltest 

Mit freundlichen Grüßen
Xelsarion


----------



## ienAri (20. Nov 2015)

Ja, das hast du korrekt verstanden! (Übrigens bin ich für bessere Wege auch durchaus offen) Ich bin auch der Meinung, dass meine Methode ggf. mehr Arbeit macht, als sie in der Praxis sollte. (Die Praxis ist eine Art Vorklausur für mein Studium, allerdings hüten sich die Verantwortlichen davor, mehr von der Aufgabenstellung preiszugeben... was auch immer noch mehr sein könnte.)

Ein zufällig funktionierendes Java Programm ist doch auch ein Teilerfolg! Oder so. Im übrigen tut habe ich tatsächlich die Objektorientierung gemieden, da ich erst seit Beginn meines Studiums - im Oktober - mit dem Programmieren angefangen habe. Da versucht man automatisch die Dinge so zu regeln, wie man sie am sichersten bewältigen kann. Verzeihung dafür, ich gelobe zukünftige Besserung!


----------



## Khal Drogo (20. Nov 2015)

Um dir das Leben etwas zu erleichtern, mach ich dich schon mal auf zwei grobe Schnitzer aufmerksam. Wenn der Spieler seine Zahl wählt, wird zunächst als potenzielle Wahl die größte Zahl im Array festgelegt, danach setzt du sie auf 0, prüfst anschließend, ob der Gegner nicht doch am Ende mehr von deiner Wahl hat, als du selbst, und falls das der Fall ist, wählst du eine andere Zahl, bis du zufrieden bist. Dabei setzt du jedes Mal die größte Zahl auf 0, und da bleibt sie dann auch, sodass du im schlimmsten Fall das ganze Spielfeld auf 0 setzt, ohne eine Wahl getroffen zu haben => Endlosschleife. Dieses Verfahren bricht dir dann das Genick. Zudem addierst du immer munter auf die Divisoren drauf, ohne sie zwischendurch zurückzusetzen, weshalb du nach dem ersten Durchlauf keine Wahl mehr treffen kannst. Das sollte dir mein kleines Beispiel (4, 4, 2) verdeutlichen.

Mit freundlichen Grüßen
Xelsarion


----------



## ienAri (20. Nov 2015)

Danke für die Ausführung! Bin ich auch grade drauf gestoßen, benötigt nun ein wenig Umbau des ganzen, wie es scheint! Wenn das das Problem war, weiß ich immerhin, was zu tun ist! Danke, hat mir sehr geholfen!


----------



## ienAri (20. Nov 2015)

Hier übrigens eine billige Lösung der Problematik:


```
public class Spieler1 {

    public static void zahlWählenSpieler1(int[] spielfeld, int[] spielerpunkte) {

        int groessteZahl = 0;
        int posGewählteZahl = 0;
        int wertGewählteZahl = 0;
        int divisorenGesamt = 1;
        int[] schlechteZahlen = new int[100];
        int schleifenZähler = 0;

        while (groessteZahl < divisorenGesamt && schleifenZähler < 100) {

            divisorenGesamt = 0;

            if (groessteZahl != 0) {
                spielfeld[posGewählteZahl] = wertGewählteZahl;
                schlechteZahlen[posGewählteZahl] = 1;
            }

            for (int x = 0; x < spielfeld.length; x++) {
                if (groessteZahl < spielfeld[x] && schlechteZahlen[x] == 0) {
                    groessteZahl = spielfeld[x];
                    posGewählteZahl = x;
                    wertGewählteZahl = spielfeld[x];
                }

            }

            spielfeld[posGewählteZahl] = 0;

            for (int y = 0; y < spielfeld.length; y++) {
                if (spielfeld[y] != 0) {
                    if (groessteZahl % spielfeld[y] == 0) {
                        divisorenGesamt += spielfeld[y];
                    }
                }

            }
            schleifenZähler++;

        }

        for (int z = 0; z < spielfeld.length; z++) {
            if (spielfeld[z] != 0) {
                if (groessteZahl % spielfeld[z] == 0) {
                    spielfeld[z] = 0;
                }
            }
        }

        spielerpunkte[0] += groessteZahl;
        spielerpunkte[1] += divisorenGesamt;

    }

}
```

Billig weil ich nun eigentlich ermitteln müsste, warum ich nicht aus der Schleife komme. Besser gesagt, was ich tun müsste, wenn komme was wolle die divisoren größer sind als die größte Zahl. Juhu, mehr Arbeit fürs Wochenende


----------



## Khal Drogo (20. Nov 2015)

Naja, da hast du einiges verschlimmbessert, viel Spaß jedenfalls (vielleicht einfach mal den Abend entspannen und morgen neu anfangen, wenn der Kopf frei ist, so Sachen lösen sich oft spontan über Nacht).
Wenn du wieder nicht weiter kommst, meld dich einfach wieder 

Mit freundlichen Grüßen
Xelsarion


----------



## ienAri (22. Nov 2015)

Ich hab noch eine ergänzende Frage zu meinem ersten fehlerhaften Code, was ruft hervor, dass die Console den int min value ausspuckt? kommt mir ehrlich gesagt vor wie hexerei


----------



## Khal Drogo (22. Nov 2015)

Ich weiß nicht genau, ob ich jetzt genau weiß, was du meinst. Aber ich denke, dass die Antwort auf deine Frage ist, dass du durch ungünstige Kombinationen von Werten in diese Endlosschleife kamst, sodass am Ende der kleinste ausgewählt wurde.
Falls das nicht der Antwort entspricht, die du dir erhofft hast, gib bitte genauer an, was du meinst (vielleicht mit Zeilenangabe im Code o. ä.).

Mit freundlichen Grüßen
Xelsarion


----------



## ienAri (22. Nov 2015)

Wenn man das ursprüngliche Programm laufen lässt und man durch doppelt generierte werte in die endlosschleife kommt, spuckt das programm entweder nichts, oder den int min value -2147483648 aus, wobei ich keine variable entsprechend definiert habe. im prinzip könnte mir das egal sein, aber ich scheine ja irgendeinen effekt ausgelöst zu haben, das entsprechendes passiert


----------

