Ein Wort aus einer Datei zufällig ermitteln

Hallo,

ich möchte gerne den folgenden Code erweitern, so dass via Zufall ein Wort aus der Datei gezogen wird. Das Wort soll später für ein anderen Code verwendet werden (Hangman-Spiel), daher wäre ein String sinnvoll.
Meine Herausforderung liegt daran das ich nicht weiß in welcher Position die jeweiligen Wörter vorhanden sind. Zumindest fällt mir kein Weg ein die Datei zu durchsuchen und dann ein zufälliges Wort auszugeben.

Kurzbeschreibung meiner Frage:
Ein Wort aus einer Datei zufällig ermitteln.

Weiß wer weiter?

Beschreibung des Codes:
Beim starten des Programmes wird eine Datei Namens "wortliste_hangman.dat" erstellt, zumindest wenn noch keine Datei vorhanden ist. Sobald man etwas im "JTextArea" einträgt und auf "Speichern" klickt wird das Wort in die Datei "wortliste_hangman.dat" gespeichert.
Sobald man "Einlesen" anklickt erscheinen alle gespeicherten Wörter im "JTextArea".

Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class WortlisteHangman1 extends JFrame {
    private static final long serialVersionUID = 6468516705291496250L;
    private JTextArea feld;//für das Eingabefeld
    private JButton einlesen, beenden, speichern;//für die Schaltflächen
    private String dateiName;//für den Dateinamen
    private int anzahlWoerter = 0;//für die Anzahl der Wörter

    class MeinListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {   
            if (e.getActionCommand().equals("lesen"))//wurde auf Einlesen geklickt?
            dateiLesen();
            if (e.getActionCommand().equals("speichern"))//wurde auf Speichern geklickt?
            dateiSchreiben();
            if (e.getActionCommand().equals("ende"))//wurde auf Beenden geklickt?
            System.exit(0);
    }
}
    //Konstuktor
    public WortlisteHangman1(String titel) {
        super(titel);
        dateiName = "wortliste_hangman.dat";
        JPanel tempPanel;//für das Panel mit den Schaltflächen
        feld = new JTextArea();//ein neues Eingabefeld erstellen
        
        einlesen = new JButton("Einlesen");//die Schaltflächen
        einlesen.setActionCommand("lesen");
        speichern = new JButton("Speichern");
        speichern.setActionCommand("speichern");
        beenden = new JButton("Beenden");
        beenden.setActionCommand("ende");

        MeinListener listener = new MeinListener();
        einlesen.addActionListener(listener);
        speichern.addActionListener(listener);
        beenden.addActionListener(listener);
        
        setLayout(new BorderLayout());//ein BorderLayout anwenden
        add(new JScrollPane(feld), BorderLayout.CENTER);//das Eingabefeld mit Scrollbars
        tempPanel = new JPanel();//ein Panel für die Schaltflächen
        tempPanel.setLayout(new FlowLayout(FlowLayout.LEFT));//ein Panel für die Schaltflächen
        tempPanel.add(einlesen);
        tempPanel.add(speichern);
        tempPanel.add(beenden);
        add(tempPanel,BorderLayout.SOUTH);
        setMinimumSize(new Dimension(400,300));//Größe setzen, Standardverhalten festlegen und anzeigen
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    /**Methode zum Lesen*/
    private void dateiLesen() {
        try {
            RandomAccessFile datei = new RandomAccessFile(dateiName, "r");//die Datei zum Lesen öffnen
            anzahlWoerter = datei.readInt();//die Anzahl der Wörter lesen bzw. gespeicher Zahl lesen
            feld.setText("");//zum Löschen des Feldtextes, so dann man auf Laden klicken kann wir man möchte
            for (int index = 0; index < anzahlWoerter; index++) {//es wird solange gelesen bis die "anzahlWoerter" erreicht ist
                datei.skipBytes(2);//den Zeiger verschieben, 2 Bytes überstpringen
                feld.append(datei.readUTF() + "\n");//Daten aus der Datei lesen und in Feld übertragen
                }
            datei.close();
            }
        catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Problem aufgetreten");
            }
        }

    /**Methode zum Schreiben*/
    private void dateiSchreiben() {//die Datei zum Lesen und Schreiben öffnen
        if (feld.getText().isEmpty()) {//ist im Eingabefeld eine Information enthalten? / wenn nein, dann verlassen wir die Methode direkt wieder
            return;
        }
        try {
            RandomAccessFile datei = new RandomAccessFile(dateiName, "rw");       
            anzahlWoerter ++;
            System.out.println(anzahlWoerter);
            datei.writeInt(anzahlWoerter);//Am Anfang der Datei die Anzahl der Wörter
            datei.seek(datei.length());//An das Ende der Datei
            datei.writeChar('*');//das Trennzeichen
            datei.writeUTF(feld.getText());//das Wort reinschreiben
            feld.setText("");
            datei.close();
        }
        catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Problem aufgetreten");
        }
    }
      
      public static void main(String[] args) {
        new WortlisteHangman1("Wortliste für Hangman");
    }
}
 
Zumindest fällt mir kein Weg ein die Datei zu durchsuchen und dann ein zufälliges Wort auszugeben.

Also prinzipiell so...
Java:
	public static void main(String[] args) throws IOException {
		System.out.println(Files.lines(Paths.get("test1.txt"))
				.collect(Collectors.collectingAndThen(Collectors.toCollection(ArrayList::new), list -> {
					Collections.shuffle(list);
					return list;
				})).stream().findFirst().orElse(null));
	}
 
Also prinzipiell so...
Kann man so machen, aber ich denke Speicher-schonender und performanter wäre vermutlich RandomAccessFile.

Java:
File yourFile = new File(yourFilePath);
try (RandomAccessFile reader = new RandomAccessFile(yourFile, "r")) {
  reader.seek(new Random().nextInt(yourFile.length));
  // der "Cursor" befindet sich nun an einer zufälligen Stelle im File
  // du musst nun nur noch das Wort oder die Zeile identifizieren, in dem sich der Cursor befindet
}

Nachteil dieser Lösung ist jedoch, dass die Einrittswahrscheinlichkeit eines Tokens von seiner Länge abhängt, d.h. für ein Gleichgewicht müsstest du eventuell mit Leerzeichen auffüllen
 

Zurück
Oben