Thorsten F.: Höchste Zahl ermitteln

Hi,

ich schreibe gerade an einem kleinen Programm. U.a. generiert mir das Programm 4 Zufallszahlen und packt diese in ein Array.

Z.B. 1,5,5,4.

So, anhand dieser Zahlen muss das Porgramm noch einmal 2 Zufallszahlen ermitteln und zwar für die Zahl 5. Die anderen beiden Zahlen (1,4) sind bereits ausgeschieden.

Das muss solange durchlaufen werden, bis eine eindeutige höchste Zahl ermittelt worden ist.
Wenn die ersten Zufallszahlen wie folgt aussehen: 1,2,4,6, dann gibt es bereits eine eindeutige Zahl.

Das Prinzip kennt ihr sicherlich von dem Brettspiel Mensch ärgere dich nicht, bei dem immer der Spieler anfängt, der die höchste Zahl geworfen hat. Kommt diese Zahl 2mal vor, so müssen diese beiden Spieler noch einmal würfeln, auch "Stechen" genannt.

Ich möchte das gerne in Java lösen, jedoch denke ich, dass das Prinzip in fast jeder Programmiersprache gleich ist, oder?

Mit der Fkt. generiere ich 4 Zufallszahlen:

public int genZahl()
    {
        return  (int) ((Math.random()*6)+1);
    }

und hier schreibe ich diese in ein Array:

public void schreibeZahl()
    {
     for(int i=0;i<4;i++)
          wuerfel[i] = genZahl();
    }

Aber jetzt muss ich ja das Array auf die oben genannten Bedingungen testen. Wie würdet ihr das machen?
PS: Ich erwarte hier keine Lösung, sondern lediglich ein paar Denkanstöße.

Gruß,
Thorsten F.

  1. Hi,

    ich schreibe gerade an einem kleinen Programm. U.a. generiert mir das Programm 4 Zufallszahlen und packt diese in ein Array.

    Z.B. 1,5,5,4.

    So, anhand dieser Zahlen muss das Porgramm noch einmal 2 Zufallszahlen ermitteln und zwar für die Zahl 5. Die anderen beiden Zahlen (1,4) sind bereits ausgeschieden.

    Das muss solange durchlaufen werden, bis eine eindeutige höchste Zahl ermittelt worden ist.
    Wenn die ersten Zufallszahlen wie folgt aussehen: 1,2,4,6, dann gibt es bereits eine eindeutige Zahl.

    Wenn ich richtig verstanden habe, liegt das eigentliche Problem darin, dass bei der ersten Zufalls-Auswahl Zahlen mehrfach vorkommen.

    Das kannst Du vermeiden, indem Du aus einer (gemischen) Menge von Zahlen die (Zufalls)Zahlen ziehst (wie beim Lotto).

    --roro

    1. Hi,

      so habe mir mal folgendes zusammengebastelt. Das funktioniert auch soweit, dass ich 4 ungleiche Zahlen zwischen 1 und 6 geliefert bekommen.
      Aber ist das auch alles fair so? Wird anhand dieser Funktion jeder Spieler gleichberechtigt behandelt oder hat dadurch irgendeiner Vorteile?

      int counter = 0;
           while(counter<wuerfel.length)
           {
            erg = gibZufallszahl();
            wuerfel[counter]=erg;

      for(int i = 0; i < counter; i++)
            {
             if(wuerfel[i] == erg)
             {
              counter--;
                   }
            }
            counter++;
           }

      Gruß,
      Thorsten F.

      1. hi,

        so habe mir mal folgendes zusammengebastelt. Das funktioniert auch soweit, dass ich 4 ungleiche Zahlen zwischen 1 und 6 geliefert bekommen.
        Aber ist das auch alles fair so? Wird anhand dieser Funktion jeder Spieler gleichberechtigt behandelt oder hat dadurch irgendeiner Vorteile?

        Übertrage es auf das Mensch-ärgere-dich-nicht-Beispiel:
        Kann ich bei der anfänglichen Auswürfelung, wer beginnen darf, keine 6 mehr würfeln, weil die schon vor mir jemand gewürfelt hat?

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hi,

          ok, dann scheint das ja nicht eine allzu faire Fkt. zu sein.
          Ähmm....ich belass es trotzdem mal dabei...vielleicht mach ich mich dann mal später daran, dass es ein Stechen gibt.

          Denn wenn man sowas macht, dann sollte es ja auch vernünftig und regelkonform ablaufen.

          Gruß,
          Thorsten F.

  2. Hej,

    Das muss solange durchlaufen werden, bis eine eindeutige höchste Zahl ermittelt worden ist.

    Das ist der Trick! Ein schönes Beispiel für Rekursion.

    Geh davon aus, dass grundsätzlich nach einem Durchlauf (Rekursionsanfang) alle Spieler einen weiteren Durchlauf machen. Von diesem werden diejenigen ausgeschlossen, die nicht die maximale Zahl gewürfelt haben (Rekursionsschritt). Das wird so lange durchgeführt, bis die Menge der Spieler nur noch einen Spieler enthält (Rekursionsende).

    Aber jetzt muss ich ja das Array auf die oben genannten Bedingungen testen.

    Du meinst, ob eine höchste Zahl, zwei mal drin vorkommt? Das Array durchlaufen, bei jedem Durchlauf prüfen, ob der Wurf höher ist der maximal gewürfelte und dir die Indizes merken, für die der maximale Wurf mehrmals vorkam. Für diese Indizes erneut würfeln lassen. Ein Problem sehe ich nur bei diesem Verfahren über mehrere Rekursionsschichten hinweg, die Indizes wieder zuzuordnen, weshalb ich einen Objektorientierten Ansatz vorziehen würde.

    PS: Ich erwarte hier keine Lösung, sondern lediglich ein paar Denkanstöße.

    Die Lösung die ich dir zeigen möchte, ist soweit von deiner entfernt, dass sie dir hoffentlich mehr Denkanstoß als Lösung ist.

      
    private Set<Spieler> stechen( Set<Spieler> spieler ) {  
      
      Set<Spieler> anfaenger = new HashSet<Spieler>( 6 );  
      int max = 0;  
      for( Spieler s : spieler ) {  
        int wurf = s.wuerfel();  
        if( wurf > max ) {  
          max = wurf;  
          anfaenger.clear();  
          anfaenger.add( s );  
        }  
        else if(wurf == max) {  
          anfaenger.add( s );  
        }  
      }  
      return ( anfaenger.size() == 1 ) ? anfaenger : stechen( anfaenger );  
    }  
      
    public Spieler werFaengtAn( Set<Spieler> spieler ) throws AnfaengerException {  
      if( spieler.isEmpty() ) {  
        throw new AnfaengerException( "Irgendjemand muss schon anfangen." );  
      }  
      return stechen( spieler ).iterator().next();  
    }  
      
    public class Spieler() {  
      
      public static int wuerfel() {  
        return (int) ((Math.random()*6)+1);  
      }  
    }  
    
    

    Beste Grüße
    Biesterfeld

    --
    Art.1: Et es wie et es
    Art.2: Et kütt wie et kütt
    Art.3: Et hätt noch immer jot jejange
    Das Kölsche Grundgesetz
    1. Hey,

      [31 Zeilen Code]

      du meine Güte, ist die Sprache furchtbar ausschweifend.

      use utf8;  
      use Games::Dice::Advanced;  
      use List::Util qw(max);  
        
      sub stechen {  
          my @spieler = @_;  
          my %würfel;  
          push @{$würfel{Games::Dice::Advanced->roll}}, $_ for @spieler;  
          return @{$würfel{max keys %würfel}};  
      };  
        
      my @spitzenspieler = stechen(qw(Anton Berta Cäsar Dora));  
      while (@spitzenspieler > 1) {  
          @spitzenspieler = stechen(@spitzenspieler);  
      };  
      print @spitzenspieler;
      
      --
      水-金-地-火-木-土-天-海-冥
      1. Hej,

        [31 Zeilen Code]

        ey, das ist unfair ... das sind nur 27 Zeilen gewesen, du hast Leerzeilen mitgezählt. :(

          
        
        > push @{$würfel{Games::Dice::Advanced->roll}}, $_ for @spieler;
        
        

        Hier versteckt sich etwas (roll) was in bei mir mindestens 3 Zeilen gekostet hat.

          
        
        > my @spitzenspieler = stechen(qw(Anton Berta Cäsar Dora));  
        > while (@spitzenspieler > 1) {  
        >     @spitzenspieler = stechen(@spitzenspieler);  
        > };
        
        

        Sicher, dass du die letzten 3 Zeilen nicht in einer eigenen Routine kapseln möchtest?

          
        
        > print @spitzenspieler;
        
        

        Wenn ich solche Ausdrücke sehe bin ich heilfroh noch nie ernsthaft in Perl programmiert haben zu müssen. :)

        Ferner habe ich eine eigene Klasse und eine Exception eingeführt, was zwar beides nicht nötig gewesen wäre, die Strukturiertheit zum einen und Robustheit zum anderen deutlich erhöht hat.

        Aber wenn ich aus der Java Insel zitieren darf: Jede Programmiersprache hat ihren Platz – ja, auch Perl. >:-]

        Beste Grüße
        Biesterfeld

        --
        Art.1: Et es wie et es
        Art.2: Et kütt wie et kütt
        Art.3: Et hätt noch immer jot jejange
        Das Kölsche Grundgesetz
      2. Hallo $unleserlichername,

        [31 Zeilen Code]
        du meine Güte, ist die Sprache furchtbar ausschweifend.

        Nun ja, Du musst auch zugeben, dass viel überflüssiger Überbau dadurch kommt, dass Biesterfeld (für die Absicht des Spieles zurecht) objekt-orientiert programmiert hat. Vergleiche mal diese minimale Lösung in Python:

        ~~~python #!/usr/bin/env python

        import sys
          from random import choice

        players = sys.argv[1:]

        round = dict([(player, choice(range(1,7))) for player in players])
          while len(round) > 1:
              maximum = max(round.values())
              round = dict([(player, choice(range(1, 7))) for player in round
                            if round[player] == maximum])

        print round.keys()[0]

          
          
        mit dieser längeren objekt-orientierten:  
          
          ~~~python
        #!/usr/bin/env python  
          
          import sys  
          from random import choice  
          
          class NoPlayerError(Exception):  
              pass  
          
          class Game(object):  
              def __init__(self, players):  
                  if not players:  
                      raise NoPlayerError  
                  self.players = players  
          
             def calcbeginner(self):  
                 round = dict([(p, p.rolldice()) for p in self.players])  
                 while len(round) > 1:  
                     maximum = max(round.values())  
                     round = dict([(p, p.rolldice()) for p in round.keys()  
                                   if round[p] == maximum])  
                 return round.keys()[0]  
          
              def start(self):  
                  beginner = self.calcbeginner()  
                  print "%s startet das Spiel" % beginner.name  
                  # Tue irgendwas, was zum Spiel gehört  
          
          class Player(object):  
              def __init__(self, name):  
                  self.name = name  
          
              def rolldice(self):  
                  return choice(range(1, 7))  
          
          if __name__ == '__main__':  
              names = sys.argv[1:]  
              players = [Player(name) for name in names]  
              game = Game(players)  
              game.start()
        

        Dadurch kommt schon was zusammen, hilft einem aber im größeren Konzept des Spieles. Der restliche Krempel ist natürlich Java-Syntax und das explizite Typing, ja.

        Tim