# Böse 6 (Würfelspiel) programmieren.



## Chloe (2. Jan 2013)

Abend.
Ich darf in meinem Kurs das Spiel Böse 6 programmieren. Kurz gefasst würfelt jeder Spieler so lange er möchte, oder bis eine 6 kommt. Wenn er eine 6 würfelt, dann sind die Punkte dieser Runde verzockt, wenn er vorher aufhört, dann schreibt er die gewürfelten Punkte seinem Punktekonto gut. Gespielt wird bis 50 Punkte oder mehr erreicht werden.
Ich habe mir schon einiges selber erarbeiten können, komme aber gerade nicht weiter. Besonders hapert es bei der Klasse Spiel unter der Methode spielen(). Ich habe dort irgendwie einen Denkfehler eingebaut, sehe aber nicht dessen Lösung. Der Compiler sagt mir, dass ich += nicht nutzen kann, da es nicht für das Objekt spieler definiert ist.
Die Objekte und Methoden sind mir vom Namen und Typ vorgeschrieben, daher kann ich das auch nicht ändern.


```
import java.util.*;

public class Spieler 
{
	
	public String name;
	public int spielstand;
	
	/**
	 * Spiele hat vor jedem neuen Versuch die Chance abzubrechen
	 * und seine Punkte gutschreiben zu lassen, daher die Frage
	 * ob er abbrechen will oder nicht.
	 */
	
	public int wuerfeln()
	{
		int wurf =(int)(Math.random()*6+1);// normaler Würfel mit 6 Seiten.
		int versuch = 0; 
		/* Summe aus der Anzahl der Würfe, ist
		 initial ersteinmal 0, da der Punktestand zu Beginn
		 bei 0 liegt.
		 */
		int a = 0;//Abbruchvariable
		
		
		do
		{
			if (wurf==6)
			{
				System.out.println("Schade, deine gesammelten" +
						"Punkte dieser Runde sind weg.");
				versuch = 0;
				a = 1;
				//Abbruchvariable auf 1, daher verlässt man die do-while Schleife.
			}
			
			else
			{
				/**
				 * Hier wird bei der Variable versuch das
				 * Wurfergebnis addiert.
				*/
				
				versuch +=wurf;
						
				Scanner s = new Scanner(System.in);
				System.out.println("<A>bbrechen oder <W>eiter?");
				String eingabe = s.nextLine();
		
				if(eingabe.equals("A")||eingabe.equals("a"))
				{
					System.out.println("abgebochen");
					return versuch = spielstand;
				}
				else
				{
					System.out.println("weiter");
				}
			}
				return versuch = spielstand;
		}
		while (a == 0);
	}
}
```


```
import java.util.Scanner;

public class Spiel extends Spieler
{
	public int anzSpieler;
	public Spieler [] spieler;
	
	/**
	 * Hier soll erst abgefragt werden wie vieler Spieler
	 * mitspielen und wie diese heißen, damit jeder Spieler
	 * weiß wer wann am Zug ist.
	 */
	
	public void starten()
	{
		Scanner s1 = new Scanner(System.in);
		System.out.println("Wie viele Spieler machen mit?");
		int anzSpieler = s1.nextInt(); //die nächste Zahl wird eingelesen
		int [] spieler = new int [anzSpieler];
		
		Scanner s2 = new Scanner(System.in);
		System.out.println("Wie heißen die Spieler?");
		String name = s2.nextLine();
	}
	
	/**
	 * Hier wird gewürfelt bis einer der Spieler 50
	 * Punkte erreicht hat.
	 */
	
	public void spielen()  
	{
		starten();
		for(int x = 0; x<= spieler.length; x++)
		{
			int y = wuerfeln();
			spieler[x]+=y;
			
			if(spieler[x]>=50)
			{
				
			}
		}// Ende for
	}
}
```


----------



## Timothy Truckle (2. Jan 2013)

Warum ist die Methode 
	
	
	
	





```
würfeln
```
 nicht in in der Klasse 
	
	
	
	





```
Spieler
```
?
Dann könnte jeder Spieler seine Punkte selber zählen. 

Und das 
	
	
	
	





```
Spiel
```
 muss immer nur über die Lister der Spieler iterieren und sie würfeln lassen.

bye
TT


----------



## Chloe (2. Jan 2013)

Es ist doch in der Klasse Spieler (public class Spieler und darunter dann die Methode). Oder habe ich dich grade einfach nur missverstanden? ^^"


----------



## Timothy Truckle (2. Jan 2013)

Chloe hat gesagt.:


> Es ist doch in der Klasse Spieler (public class Spieler und darunter dann die Methode). Oder habe ich dich grade einfach nur missverstanden? ^^"


Oh, ja...
Ich war verwirrt, wiel 
	
	
	
	





```
Spiel
```


```
Spieler
```
 erweitert, aber wieso ist ein Spiel ein besonderer Spieler?


----------



## Landei (2. Jan 2013)

[c]Spiel extends Spieler[/c] ist definitiv falsch. Ein Spiel _hat_ Spieler, es _ist_ aber selbst keiner.


----------



## Timothy Truckle (2. Jan 2013)

Chloe hat gesagt.:


> Der Compiler sagt mir, dass ich += nicht nutzen kann, da es nicht für das Objekt spieler definiert ist.


Da hat er auch recht. 
[JAVA=35]for(int x = 0; x<= spieler.length; x++)
        {
            int y = wuerfeln();
            spieler[x]+=y;

            if(spieler[x]>=50)
            {

            }
        }[/code]
	
	
	
	





```
spieler[x]
```
ist ein Objekt von Typ 
	
	
	
	





```
Spieler
```
 für Objekte gibt es keine primitiven Rechenoperationen (mit Ausnahme von String).
Wie gesagt wäre es besser dem Spieler eine Methode 
	
	
	
	





```
versuche()
```
 zu spendieren in der der Spieler selber würfelt  (und nicht wie bei Dir das Spiel).
Der Gewinnfall ist so selten (nur ein mal je Spiel), dass ich den als Exception (
	
	
	
	





```
GameEndException extends Exception
```
) abgebildet hätte. Dann sähe diese Stelle so aus:[JAVA=35]try{
   for(Spieler aktiverSpieler : spieler )
        {
            aktiverSpieler.versuche();
        }
}catch (GameEndException gee) {
  System.out.println( gee.getMessage());
}[/code]Und ich hätte eine neue Klasse:

```
class GameEndException extends Exception {
  public GameEndException (String gewinnerName){
    super("gewonnen hat: "+gewinnerName);
  }
}
```
In Spieler stände:
	
	
	
	





```
publich void versuche() throws GameEndException {
  int neuePunkte =0;
  do{
     int wurf = wuerfeln();
     if (6 == wurf()) {
       System.out.println("schade, 6 geworfen...");
       return; 
     } else {
       System.out.println("schön, "+wurf+" Punkte dazu");
       neuePunke+=wurf;
    }
     if(50<this.spielstand) {
       throw new GameEndException (this.name);
     }
   } while (weiterwuerfeln());
   this.spielstand+=neuePunkte;
   System.out.println("Spiler "+name +"hat jetzt " + this.spielstand+" Punkte");
}
```

bye
TT


----------



## Chloe (3. Jan 2013)

Danke für die hilfreichen Tipps.:toll:


----------



## hüteüberhüte (3. Jan 2013)

(5/6)^x=0.5 -> x~3.80178, also sollte man 4 mal würfeln, oder?


----------



## Timothy Truckle (3. Jan 2013)

Weil's gerade so'n Spass macht:
Die Methode 
	
	
	
	





```
versuche()
```
 würde ich noch weiter refactorieren:
Die Prüfung auf 6 sollte in die 
	
	
	
	





```
würfeln()
```
 Methode wandern und dort ebenfalls eine Exception auslösen (keine Angst vor Exceptions, die sind nicht böse....)

```
// in Klasse Spieler
private static class SechsGewuerfelt extends Exception {
   SechsGewuerfelt () { super("schade, 6 geworfen...");}
};

private int wuerfeln() throws SechsGewuerfelt {
   int wurf = new Random().nextInt(6)+1;
   if(6== wurf) {
     throw new SechsGewuerfelt ();
   }
   System.out.println("schön, "+wurf+" Punkte dazu");
}

private void pruefeGewinn(int neuePunkte) throws GameEndException {
     if(50<this.spielstand+ neuePunkte) {
       throw new GameEndException (this.name);
     }
}

private void spieleRunde() throws GameEndException, SechsGewuerfelt {
     int neuePunkte =0;
     do{
        neuePunke+= wuerfeln();
        pruefeGewinn(neuePunkte);
     } while (weiterwuerfeln());
     this.spielstand+=neuePunkte;
}
public void versuche() throws GameEndException {
  try {
     spieleRunde()
     System.out.println("Spiler "+name +" hat jetzt " + this.spielstand+" Punkte");
   } catch (SechsGewuerfelt sg){
     System.out.println(sg.getMessage());     
   }
}
```
Selbstverständlich muss man sich bei den Bezeichnern für eine Sprache entscheiden, aber ich wollte das Beispiel nachvollziehbar halten...

bye
TT


----------



## hüteüberhüte (3. Jan 2013)

```
public static void main(String[] args) {
        int[] spieler1und2 = new int[2];
        while (spieler1und2[0] < 999 && spieler1und2[1] < 999) {
            int sum = 0;
            for (int i = 0; i < 3; i++) {
                int r = random.nextInt(6) + 1;
                if (r != 6) {
                    sum += r;
                } else {
                    sum = 0;
                    break;
                }
            }
            spieler1und2[0] += sum;

            sum = 0;
            for (int i = 0; i < 4; i++) {
                int r = random.nextInt(6) + 1;
                if (r != 6) {
                    sum += r;
                } else {
                    sum = 0;
                    break;
                }
            }
            spieler1und2[1] += sum;
        }
        System.out.println("spieler1und2 = " + Arrays.toString(spieler1und2));
    }
```

Ich weiß, es ist nicht schön programmiert, aber bei mir gewinnt immer Spieler 2.


----------



## Timothy Truckle (3. Jan 2013)

hüteüberhüte hat gesagt.:


> Ich weiß, es ist nicht schön programmiert, [...]


Wenn Du das alles in eine Zeile schreibst geht das ja schon fast als Perl-Script durch....
;o)

bye
TT


----------



## hüteüberhüte (3. Jan 2013)

Ich hab nochmal etwas rumprobiert, und bin auf für mich merkwürdige Ergebnisse gekommen:


```
Würfelspieler{summe=2537, runde=999, wurff=0, limit=1, summeRunde=0, verboten=false}
Würfelspieler{summe=4103, runde=999, wurff=0, limit=2, summeRunde=0, verboten=false}
Würfelspieler{summe=5227, runde=999, wurff=0, limit=3, summeRunde=0, verboten=false}
Würfelspieler{summe=5621, runde=999, wurff=0, limit=4, summeRunde=0, verboten=false}
Würfelspieler{summe=6242, runde=999, wurff=0, limit=5, summeRunde=0, verboten=false}
Würfelspieler{summe=6189, runde=999, wurff=0, limit=6, summeRunde=0, verboten=false}
Würfelspieler{summe=5513, runde=999, wurff=0, limit=7, summeRunde=0, verboten=false}
Würfelspieler{summe=5366, runde=999, wurff=0, limit=8, summeRunde=0, verboten=false}
Würfelspieler{summe=5342, runde=999, wurff=0, limit=9, summeRunde=0, verboten=false}
Würfelspieler{summe=5482, runde=999, wurff=0, limit=10, summeRunde=0, verboten=false}
```

Demnach schneidet der Würfler mit Limit 5 am besten ab. Wie ist das mathematisch zu erklären/herzuleiten?



Spoiler: (hier der verwendete Code)





```
/**
 * @author hütte
 */
public class Würfelspieler {

    private static final Random random = new Random();
    private int summe = 0;
    private int runde = 0;
    private int wurff = 0;
    private int limit = 4;
    private int summeRunde = 0;
    private boolean verboten = false;

    public Würfelspieler(int limit) {
        this.limit = limit;
    }

    public Würfelspieler() {
    }

    public boolean weiter() {
        return !verboten && wurff < limit;
    }

    public boolean würfeln() {
        if (verboten) {
            throw new RuntimeException() {

                @Override
                public String getMessage() {
                    return "Weiterer Zug nicht erlaubt.";
                }
            };
        }
        wurff++;
        int r = random.nextInt(6) + 1;
        if (r != 6) {
            summeRunde += r;
            return true;
        } else {
            summeRunde = 0;
            verboten = true;
            return false;
        }
    }

    public void stehenbleiben() {
        summe += summeRunde;
        runde++;
        wurff = 0;
        summeRunde = 0;
        verboten = false;
    }

    public int getSumme() {
        return summe;
    }

    @Override
    public String toString() {
        return "W\u00fcrfelspieler{" + "summe=" + summe + ", runde=" + runde + ", wurff=" + wurff + ", limit=" + limit + ", summeRunde=" + summeRunde + ", verboten=" + verboten + '}';
    }

    public static void main(String[] args) {
        Würfelspieler[] würfler = new Würfelspieler[10];
        for (int i = 0; i < würfler.length; i++) {
            if (i != 3) {
                würfler[i] = new Würfelspieler(i + 1);
            } else {
                würfler[i] = new Würfelspieler();
            }
        }

        for (int i = 0; i < 999; i++) {
            for (Würfelspieler würfelspieler : würfler) {
                do {
                    würfelspieler.würfeln();
                } while (würfelspieler.weiter());
                würfelspieler.stehenbleiben();
            }
        }

        for (Würfelspieler würfelspieler : würfler) {
            System.out.println(würfelspieler);
        }
    }
}
```




Edit: Bei etwas längeren Tests ist sogar aufgefallen, dass Limit 6 in der Summe etwa 0,04 Prozent mehr Punkte hat als Limit 5. :shock:


----------



## Chloe (3. Jan 2013)

Danke für eure Hilfe.^^
Leider versteh ich eure späteren Hilfsansätze nicht. Exception hatten wir noch nicht und ich soll auch bei meinen zwei Klassen bleiben. Ich versuch einfach es mit meinem wenigen Wissen(gerade mal erstes Semester) zusammen zu schustern.^^"


----------



## Landei (3. Jan 2013)

@Timothy Truckle: Insgesamt sieht der Code nicht schlecht aus, aber ich würde nie, nie, nie Applikations-Logik über Exceptions implementieren. Eine Sechs zu würfeln ist eine ganz normales Ergebnis, das Spiel zu beenden ist ein ganz normaler Vorgang - und kein Grund, Exceptions zu werfen. Exceptions sind nicht-lokale und damit schwer zu beherrschende Kontrollstrukturen, und die dazugehörige Syntax "verschmutzt" den Code. Es ist schon schwierig genug, echte Exceptions wirklich korrekt zu behandeln - da binde ich mir nicht noch freiwillig unnötige ans Bein. 

[OT]
Generell werden in Java auch dort Exceptions verwendet, wo eigentlich ein "exakterer" Rückgabewert (der eben auch das mögliche Scheitern beinhaltet) ausreichend wäre. Mit Java 8 sollten auch Klassen wie Scala's [c]Option[/c] und [c]Either[/c] (bzw.  [c]Maybe[/c] und [c]Either[/c] in Haskell) praktikabel werden, die u.a. dafür verwendet werden können. 

Das Typsystem ist dafür da, Typen möglichst genau zu beschreiben. Das Ergebnis einer Division oder [c]Math.sqrt[/c] unterscheiden sich eben vom Ergebnis einer Addition oder [c]Math.abs[/c] dadurch, dass sie auch scheitern können - und man sollte es dem Ergebnis eben auch ansehen können.
[/OT]


----------



## hüteüberhüte (3. Jan 2013)

Gewinnt man denn jetzt mit der gleichen Wahrscheinlichkeit, wenn man 5mal oder 6mal würfelt? Erklärt mir das doch mal einer.


----------



## hüteüberhüte (3. Jan 2013)

Ach so, ((5/6)^x)*(x*3) hat irgendwo eine Extremstelle zwischen 5 und 6, evtl. sogar genau bei 5.5. Hat jemand einen Funktionsplotter, der mir das anzeigt? Wäre super liep von euch.

Edit: Habs: max{(5/6)^x (3 x)}~~6.05325 at x~~5.48481. Also 5 mal würfeln und wenns gerade gut läuft, auch mal 6 mal würfeln. Schönes Spiel. 

Edit 2: Hier nochmal die Werte nach 999.999 Runden mit 10 Spielern:

```
Würfelspieler{summe=2500314, runde=999999, wurff=0, limit=1, summeRunde=0, verboten=false}
Würfelspieler{summe=4170370, runde=999999, wurff=0, limit=2, summeRunde=0, verboten=false}
Würfelspieler{summe=5207800, runde=999999, wurff=0, limit=3, summeRunde=0, verboten=false}
Würfelspieler{summe=5783718, runde=999999, wurff=0, limit=4, summeRunde=0, verboten=false}
Würfelspieler{summe=6029523, runde=999999, wurff=0, limit=5, summeRunde=0, verboten=false}
Würfelspieler{summe=6020375, runde=999999, wurff=0, limit=6, summeRunde=0, verboten=false}
Würfelspieler{summe=5873435, runde=999999, wurff=0, limit=7, summeRunde=0, verboten=false}
Würfelspieler{summe=5573129, runde=999999, wurff=0, limit=8, summeRunde=0, verboten=false}
Würfelspieler{summe=5236000, runde=999999, wurff=0, limit=9, summeRunde=0, verboten=false}
Würfelspieler{summe=4822501, runde=999999, wurff=0, limit=10, summeRunde=0, verboten=false}
```
Die Spieler wurden vor jeder Runde gemischt, so dass immer in einer unterschiedlichen Reihenfolge gespielt wird, obwohl das eigentlich ja egal ist (sein müsste). Wenn einer an dem Code interessiert ist, dann kann ich denn hier posten.


----------



## Chloe (3. Jan 2013)

Jo ich nochmal.
Habe etwas weitergebastelt und bin auf ein Compilerproblem gestoßen.
Der Compiler sagt mir, dass ich die Methode starten() nicht ausführen kann, da sie nicht statisch (static) ist. Ich soll die Methode in einer neuen Klasse SpielTest öffnen. Aber ich kann auch nicht einfach static zu meinem Objekt Spieler hinzufügen... wie kann ich das Compilerproblem lösen?


```
public void starten()
	{
		Scanner s = new Scanner(System.in);
		System.out.println("Wie viele Spieler machen mit?");
		int anzSpieler = s.nextInt(); //die nächste Zahl wird eingelesen
		System.out.println("So viele Spieler spielen mit:"+ anzSpieler);
		
		spieler = new Spieler [anzSpieler];
		
		for(int i=1;i<=anzSpieler;i++)
		{
			System.out.println("Wie heißt Spieler "+i+"?");
			String name = s.nextLine();
			System.out.println("Spieler "+i+" heißt: "+name);
		}
	}
```


----------



## Timothy Truckle (3. Jan 2013)

Chloe hat gesagt.:


> Der Compiler sagt mir, dass ich die Methode starten() nicht ausführen kann, da sie nicht statisch (static) ist.


Zeig maldie Stelle,woDu 
	
	
	
	





```
starten()
```
 aufrufen willst.

bye
TT


----------



## Chloe (3. Jan 2013)

```
public class SpielTest extends Spiel
{
	public static void main(String[] args) 
	{
		starten();
	}

}
```

Wie gesagt, ich solls halt in einer neuen Klasse öffnen und wollte einfach mal kontrollieren obs funktioniert.^^


----------



## Timothy Truckle (3. Jan 2013)

Chloe hat gesagt.:


> ```
> public class SpielTest extends Spiel{
> public static void main(String[] args)
> {
> ...


Und wieder mal hat der Compiler recht...
Du must erst ein Objekt der Klasse Spiel erstellen, bevor Du auf Objekt-Methoden zugreifen kannst...
	
	
	
	





```
public class SpielTest {// extends Spiel{ ist Unsinn
	public static void main(String[] args) {
		new Spiel().starten();
	}
}
```
bye
TT


----------



## Chloe (3. Jan 2013)

Oh mann...warum denkt man nicht an das offensichtliche?^^"
Danke


----------



## adi01 (11. Jan 2015)

Hi 

ich muss den selben Übung machen und habe ein paar Probleme damit. Ich habe 2 Klassen geschrieben: Spieler und Spiel, aber ich komme nicht richtig dazu..


```
Java Code:
import java.util.Random;
import java.util.Scanner;

public class Spieler {

	public String name;
	public int spielstand;
	public Random r = new Random(); //Zufalklasse
	
	Spieler(String name)
	{
		this.name=name;
		spielstand=0;
	}

public int wuerfeln(){
		int augenzahl;
		augenzahl=this.r.nextInt(6)+1; //normaler Wuerfel mit 6 Seiten
		//Spieler wuerfelt bis Abbruch oder bis 6
		return augenzahl; //Summe des Versuch zurueck
	
	//Abfrage anzahl Spieler
	 Spieler[] spieler=new Spieler[3];
	 for (int i=0; i<spieler.length; i++)
	 {
	 String name=scanner.next();
	 spieler[i]=new Spieler(name);
	 }
	 int aktspieler=0;
	 
	 boolean ende=false;
	 int wurf=0;
	 int versuch=0;
	 
	 do
	 {
		wurf=r.nextInt(6)+1;
		if(wurf!=6)
		{
			versuch+=wurf;
			//Ausgabe!
			if(spielstand + versuch>=50)
			{
				ende=true;
				return versuch;
			}
			else
			{
				//weitermachen
				ende=false;
			}
		}
		return 0;
	 }while(!ende);
	 
	 int i=0;
	 boolean ende=false;
	 do
	 {
		 spieler[i].spielstand +=
		 spieler[r].wuerfeln();
		 
		 if(spieler[i].spielstand>=50)
			 ende=true;
		 if(i==spieler.length-1)
		 {
			 i=0;
		 }
		 else
		 {
			 i++;
		 }
	 }while(!ende);
  }
}
```

Es kann auch nicht meinen Import von Scanner und Random finden und nutzen.

Und hier ist die Klasse Spiel:


```
Java Code:
import java.util.Scanner;

public class Spiel{
	
		public int anzSpieler;
		public Spieler [] spieler;
	 
		/**
		 * Hier soll erst abgefragt werden wie vieler Spieler
		 * mitspielen und wie diese heißen, damit jeder Spieler
		 * weiß wer wann am Zug ist.
		 */
	 
		public void starten()
		{
			Scanner s1 = new Scanner(System.in);
			System.out.println("Wie viele Spieler machen mit?");
			int anzSpieler = s1.nextInt(); //die nächste Zahl wird eingelesen
			int [] spieler = new int [anzSpieler];
	 
			Scanner s2 = new Scanner(System.in);
			System.out.println("Wie heißen die Spieler?");
			String name = s2.nextLine();
		}
	 
		/**
		 * Hier wird gewürfelt bis einer der Spieler 50
		 * Punkte erreicht hat.
		 */
	 
		public void spielen()  
		{
			starten();
			for (int i=0; i<Spielearray.length; i++)
			{
				int i = wuerfeln();
				spieler[i]+=y;
	 
				if(spieler[i]>=50)
				{
					System.out.println("Sie sind Gewinner!");	 
				}
			}// Ende
```


----------

