# Zufälliges Wort direkt aus einer Liste ausgeben



## Pio (10. Mai 2017)

Hallo zusammen,

In einem HangMan-Spiel habe ich zusätzlich einen Editor erstellt, womit man mindestens 20 Wörter eingeben kann und in liste.bin gespeichert werden.
Soweit kann ich auch auf die Liste zu greifen. Hier soll jetzt aus der Liste ein zufälliges Wort ausgewählt und angezeigt werden.

Das Anzeigen wird nicht das Problem sein. Ich habe das Problem, dass ich es nicht schaffe direkt aus der Liste ein zufälliges Wort auszuwählen. Dies soll nicht über ein Array passieren (dies habe ich geschafft).

Hier geht es eigentlich nur rein um den Weg, wie ich es umsetzen kann. Die Liste selbst ist als .bin gespeichert (soll auch sol bleiben).

Idee:
Da ich den Zeiger in der .bin-Liste mit seek() verschieben kann, wäre das eine Möglichkeit. Also müsste ich nur eine Zufallszahl erstellen, die mir sagt, welches Wort ausgewählt wird und den Zeiger dorthin verschieben zum Lesen und dann Ausgeben.

 Aber wie schaffe ich es jetzt eine Zufallszahl ((int)Math.random() -> soweit klar) zu erstellen, die ich mit seek() verbinden kann, dass er mir das Wort ausgeben kann. Das Problem ist seek() erwartet ein Tpy long. Die Position des Zeigers bekomme ich mit getFilePointer() heraus -> auch kein Problem. Mit readUnsignedShort() bekomme ich die Wortlänge heraus -> auch ok. Über length() bekomme ich die Anzahl der ganzen Datei angezeigt. Dort könnte ich dann über die Zufallszahl auf einen x-beliebigen Wert der Datei zugreifen. Dennoch könnte hier auch ein Wert angesprochen werden, der mitten im Wort ist und somit bekomme ich eine Ausnahme.

Egal wie ich mir dies vorstelle, lande ich immer mit meiner Zufallszahl irgendwo und nicht da wo ich hin will. 

Das sind soweit die Mittel, die ich kenne und erstmal nutzen soll. Und nochmals: Hier soll es nur um einen Weg gehen, wie man sowas umsetzen kann. Ich möchte keinen Quellcode oder so (das möchte ich schon selber machen).

mfg


----------



## Flown (10. Mai 2017)

Warum nicht einfach alle Wörter einlesen und dann das Wort selektieren ala `words.get((int)Math.random() * words.size())`?


----------



## Pio (11. Mai 2017)

Ein kleines Feedback von mir!

Ich habe es soweit geschafft. Ich habe es wie folgt gelöst. Ich lese die Datei ein und über While zähle ich die anzahl der Wörter die ich in zaehler speicher. Danach setze ich den Zeiger auf die Anfangsposition zurück. Weiterhin erstelle ich eine Zufallszahl (max Wert ist hier die gespeicherten Wörter minus 1). Danach laufe ich die Liste so oft wie die Zufallzahl es mir vorgibt in der for-Schleife durch. Zum Schluss werden noch die Buchstaben durch * ersetzt und in einem Label im Spiel ausgegeben. 

Da ich noch sehr unerfahren bin würde ich mich freuen, wenn hier ein kurzes Feedback kommen würde. 


```
private void neuesWort()
    {

        //aus der Liste lesen
        try (RandomAccessFile datei = new RandomAccessFile("liste.bin","r"))
        {

            int zaehler = 0;
            int zufall = 0;
           
            //Anzahl der Wörter ermitteln und in der Var zaehler speichern
            while(datei.getFilePointer() < datei.length())
            {
                long naechstePosition = 0;
               
                naechstePosition = datei.readUnsignedShort();
                datei.seek(datei.getFilePointer() + naechstePosition);
               
                zaehler++;
            }
           
            //Zeiger zurücksetzen auf die Anfangsposition
            datei.seek(0);

            //Zufallzahl ermitteln. Max Anzahl = zaehler - 1 damit ich nicht bei der Ausgabe über das Dateiende hinauslese und eine Ausnahme auslöse
            //Hier werden die Zahlen 0 - 19 (sind auch 20zig) verwendet.
            zufall = (int)(Math.random() * (zaehler - 1));
           
            //Die Zufallszahl ist der maximale Durchlauf
            //
            for(int i = 0; i< zufall; i++)
            {
                long neuePosition = 0;

                //Ein Wort weitergehen
                neuePosition = datei.readUnsignedShort();
                datei.seek(datei.getFilePointer() + neuePosition);
               
            }

            //das Suchwort und die Zeichen für die Anzeige setzen
            suchwort = new String(datei.readUTF());
            anzeige = new StringBuilder(suchwort);
           
            //alle Zeichen in der Anzeige ersetzen durch *
            for (int zeichen = 0; zeichen < suchwort.length(); zeichen++)
                anzeige.setCharAt(zeichen, '*');

            //die Sternchen anzeigen
            ausgabeText.setText(anzeige.toString());

        }
        catch(IOException e)
        {
            JOptionPane.showMessageDialog(this, "Beim Laden ist ein Problem aufgetreten");
            e.printStackTrace();
        }
       
    }
```


----------



## JStein52 (11. Mai 2017)

Also ganz ehrlich: komplizierter geht es nicht. Warum machst du es nicht wie @Flown oben geschrieben hat ?


----------



## Xyz1 (11. Mai 2017)

RAF sieht man auch relativ selten. Wie ist denn deine "liste.bin" aufgebaut? Komplett alles kann ich nicht lesen. xD

Optionen:

```
LinkedList<String> liste = new LinkedList();
        liste.add("aale");
        liste.add("bald");
        liste.add("cent");
        liste.add("dank");
        // usw.

        // Option 1.:
        System.out.println(liste.get((int) (Math.random() * liste.size() ) ) );

        // Option 2.:
        Collections.shuffle(liste, new Random(0));
        System.out.println(liste.getFirst());
```


----------



## JStein52 (12. Mai 2017)

Ja genau so.


DerWissende hat gesagt.:


> LinkedList<String> liste = *new* LinkedList();


Aber warum ist die Liste "Linked" ?


----------



## Pio (12. Mai 2017)

@DerWissende
Die Liste wird durch Eingabe des Users erstellt. Hier wird ein extra Fenster geöffnet, wo der User min. 20 Wörter eingeben muss. Schaue mir gerad an, wie ich über randomAccessFile prüfen kann, ob es die Datei schon gibt und dann die Anzahl der Wörter auszulesen. 


```
private void speicherPanel()
    {
       
        try(RandomAccessFile datei = new RandomAccessFile("liste.bin", "rw"))
        {
            //aus dem eingabefeld das Wort auslesen und in text speichern
            String text = eingabeFeld.getText();
           
            //wenn das Eingabefeld leer ist
            if(eingabeFeld.getText().equals(""))
            {   
                //wird eine Meldung ausgegeben
                JOptionPane.showMessageDialog(null, "Sie haben noch kein Wort eingegeben");
            }
            //Wenn das Eingabefeld nicht leer ist, wird das Wort in der Datei gespeichert.
            else
            {
                //an das Ende der Datei gehen
                datei.seek(datei.length());
               
                //Wort in die Liste schreiben
                datei.writeUTF(text);
               
                //Zähler für die Anzahl der Wörter hochzählen
                zaehler++;

                //Textfeld leeren
                eingabeFeld.setText("");
               
                //Zaehler neu ausgeben bzw hochzählen
                anzahl.setText(Integer.toString(zaehler));
            }
           
        }
    catch (IOException e)
        {
            JOptionPane.showMessageDialog(this, "Beim Schreiben ist ein Problem aufgetreten");
        }   
    }
```

Option 1 werde ich mir anschauen. Das sieht recht vielversprechend aus.


----------



## VfL_Freak (12. Mai 2017)

Moin,


Pio hat gesagt.:


> Schaue mir gerad an, wie ich über randomAccessFile prüfen kann, ob es die Datei schon gibt


versuche einfach die Datei zu öffnen. Wenn sie nicht vorhanden ist, wird ein Fehler ausgelöst !

VG Klaus


----------



## mrBrown (12. Mai 2017)

Vergiss besser RandomAccessFile, das ist der so ziemlich umständlichste Weg, um die Datei einzulesen 
Da kann man, wenn man unbedingt händisch einlesen will, deutlich besser mit FileReader oder BufferedReader und einer Liste arbeiten.


----------



## Pio (12. Mai 2017)

@mrBrown 
FileReader ist auch eine sehr gute Idee. Bin ich gar nicht drüber gestolpert. Ich werde gleich mal mein Versuch mal starten. Feedback kommt!


----------

