Homepage von Jean-René Thies — Projekte & Tools rund um Java, Groovy, Grails, PHP, Scala, MySQL...
    « Framework zum Spielen?Tutorial: Erste GUI-Anwendungen mit Scala »

    Eine tierische Basic-to-Java Übersetzung

    Permalink 02.12.09 17:56, von jrt, Kategorien: Site Seeing, Java, Minigames , Schlagworte: animal, basic, datenstruktur, java

    Kürzlich habe ich zwei Bücher im Web wiedergefunden, die mich vor langer Zeit mal beschäftigt haben: BASIC Computer Games und More BASIC Computer Games. Alle Quellcodes sind als GIFs enthalten, so dass man genau wie früher abtippen muss. Sehr nostalgisch...
    Dabei helfen die vielen GOTO-Anweisungen nicht gerade beim Verständnis. Nach der Lektüre von Clean Code tun einem die BASIC-Programme geradezu in den Augen weh - und das liegt nicht nur an der niedrigen Scanauflösung der GIFs. Programme sollten beim Durchlesen auch zu verstehen sein, und das mit möglichst wenigen Kommentaren.
    Ich habe eines der Spiele herausgepickt und in Java neu geschrieben. Gespielt wird in der Textkonsole, und als kleines Bonbon speichert das Programm seine gesammelten Erfahrungen am Ende des Spiels in eine Neodatis-Datenbank.

    Fortsetzung:

    Das Spiel heißt im Original Animal und vermittelt Programmieranfängern einen guten Eindruck, wie man eine baumartige Datenstruktur aufbauen kann. Zu Beginn kennt das Programm zwei Tiere und eine Frage, mit der man die beiden unterscheiden kann. Nun denkt sich der Spieler weitere Tiere aus und fügt diese zusammen mit neuen Fragen in den Fragenbaum ein. Auf diese Weise "lernt" das Spiel dazu. Das sieht dann etwa so aus:


    -------- Neues Tier --------
    Kann es fliegen?
    j
    Heißt Dein Tier Amsel?
    n
    An welches Tier hast Du gedacht?
    Schmetterling
    Bitte gib eine ja/nein-Frage ein, die Amsel von Schmetterling unterscheidet:
    Ist es ein Vogel?
    Für Schmetterling wäre die Antwort?
    n
    -------- Neues Tier --------
    Kann es fliegen?
    liste
    ----- Liste der bekannten Tiere -----
    Amsel
    Schmetterling
    Zebra
    ----- Ende der Liste -----
    Kann es fliegen?
    j
    Ist es ein Vogel?
    n
    Heißt Dein Tier Schmetterling?
    n
    An welches Tier hast Du gedacht?
    Fledermaus
    Bitte gib eine ja/nein-Frage ein, die Schmetterling von Fledermaus unterscheidet:
    Ist es ein Insekt?
    Für Fledermaus wäre die Antwort?
    n
    -------- Neues Tier --------
    Kann es fliegen?
    n
    Heißt Dein Tier Zebra?
    n
    An welches Tier hast Du gedacht?
    Wal
    Bitte gib eine ja/nein-Frage ein, die Zebra von Wal unterscheidet:
    Lebt es an Land?
    Für Wal wäre die Antwort?
    n
    -------- Neues Tier --------
    Kann es fliegen?
    liste
    ----- Liste der bekannten Tiere -----
    Amsel
    Fledermaus
    Schmetterling
    Wal
    Zebra
    ----- Ende der Liste -----
    Kann es fliegen?
    ende
    Die Liste der Tiere wurde gespeichert.

    Ein Tipp für Windows-Nutzer: Damit die Zeichen ä, ö, ü und ß richtig in der Textkonsole dargestellt werden, muss man das Programm mit dem Parameter file.encoding=cp850 starten. Im DOS-Fenster sieht das dann so aus: java -Dfile.encoding=cp850 -jar TiereRaten.jar.

    Für die Datenstruktur habe ich die kurze Java-Klasse "Frage" geschrieben:

    Code:

    package tiereraten;
     
    public class Frage {
     
        Frage folgefrageJa = null;
        Frage folgefrageNein = null;
        String fragetext = "";
        String tiernameZuAntwortJa = "";
        String tiernameZuAntwortNein = "";
     
        public boolean hatFolgefrageJa() {
            if (folgefrageJa == null) {
                return false;
            } else {
                return true;
            }
        }
     
        public boolean hatFolgefrageNein() {
            if (folgefrageNein == null) {
                return false;
            } else {
                return true;
            }
        }
    }

    Eine Frage könnte z.B. lauten "Lebt es an Land?". Für ein Tier muss die Antwort ja lauten und für das andere nein. Im Lauf des Spiels hängen an jeder Frage weitere Fragen, und zwar sowohl am "ja"-Zweig als auch am "nein"-Zweig.

    Nun zum eigentlichen Spiel:

    Code:

    package tiereraten;
     
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
     
    import java.util.ArrayList;
    import java.util.TreeSet;
     
    public class Spiel {
     
        private ArrayList<Frage> fragensammlung = new ArrayList<Frage>();
        private Frage startFrage;
        private Frage aktuelleFrage;
     
        public Spiel() {
            spielVorbereiten();
            beginneNeueRunde();
            boolean weiterspielen = true;
            while (weiterspielen) {
                String kandidat = "";
                String antwort = beantworteFrage(aktuelleFrage.fragetext);
                if (antwort.equals("j")) {
                    kandidat = aktuelleFrage.tiernameZuAntwortJa;
                    if (aktuelleFrage.hatFolgefrageJa()) {
                        aktuelleFrage = aktuelleFrage.folgefrageJa;
                    } else {
                        if (beantworteJaNeinFrage("Heißt Dein Tier "
                                + kandidat + "?").equals("j")) {
                            ausgabe("Erraten!");
                            beginneNeueRunde();
                        } else {
                            Frage neueFrage = neueFrageAnhaengenAn(kandidat);
                            aktuelleFrage.folgefrageJa = neueFrage;
                            beginneNeueRunde();
                        }
                    }
                } else if (antwort.equals("n")) {
                    kandidat = aktuelleFrage.tiernameZuAntwortNein;
                    if (aktuelleFrage.hatFolgefrageNein()) {
                        aktuelleFrage = aktuelleFrage.folgefrageNein;
                    } else {
                        if (beantworteJaNeinFrage("Heißt Dein Tier "
                                + kandidat + "?").equals("j")) {
                            ausgabe("Erraten!");
                            beginneNeueRunde();
                        } else {
                            Frage neueFrage = neueFrageAnhaengenAn(kandidat);
                            aktuelleFrage.folgefrageNein = neueFrage;
                            beginneNeueRunde();
                        }
                    }
                } else if (antwort.equals("ende")) {
                    weiterspielen = false;
                    Datenbank.speichern(fragensammlung);
                    ausgabe("Die Liste der Tiere wurde gespeichert.");
                } else if (antwort.equals("liste")) {
                    listeAusgeben();
                } else if (antwort.equals("neu")) {
                    vergissAlles();
                    spielVorbereiten();
                    beginneNeueRunde();
                } else {
                    ausgabe("Bitte nur j, n, liste, ende oder neu eingeben!");
                }
            }
        }
     
        private void spielVorbereiten() {
            fragensammlung = Datenbank.laden();
            if (fragensammlung.isEmpty()) {
                startFrage = erzeugeErsteFrage();
                fragensammlung.add(startFrage);
            } else {
                startFrage = fragensammlung.get(0);
            }
        }
     
        private Frage erzeugeErsteFrage() {
            Frage frage = new Frage();
            frage.fragetext = "Kann es fliegen?";
            frage.tiernameZuAntwortJa = "Amsel";
            frage.tiernameZuAntwortNein = "Zebra";
            return frage;
        }
     
        private void beginneNeueRunde() {
            aktuelleFrage = startFrage;
            ausgabe("-------- Neues Tier --------");
        }
     
        private String beantworteFrage(String frage) {
            String antwort = "";
            while (antwort.length() == 0) {
                ausgabe(frage);
                antwort = eingabe();
            }
            return antwort;
        }
     
        private String beantworteJaNeinFrage(String frage) {
            String antwort = "";
            while (!antwort.equals("j") && !antwort.equals("n")) {
                ausgabe(frage);
                antwort = eingabe();
            }
            return antwort;
        }
     
        private Frage neueFrageAnhaengenAn(String letztesBekanntesTier) {
            String neuesTier = beantworteFrage("An welches Tier hast Du gedacht?");
            String frageZuNeuemTier = beantworteFrage(
                    "Bitte gib eine ja/nein-Frage ein, die " + letztesBekanntesTier
                    + " von " + neuesTier + " unterscheidet:");
            String antwortNeuesTier = beantworteJaNeinFrage("Für " + neuesTier
                    + " wäre die Antwort?");
            Frage neueFrage = new Frage();
            neueFrage.fragetext = frageZuNeuemTier;
     
            if (antwortNeuesTier.equals("j")) {
                neueFrage.tiernameZuAntwortJa = neuesTier;
                neueFrage.tiernameZuAntwortNein = letztesBekanntesTier;
            } else {
                neueFrage.tiernameZuAntwortNein = neuesTier;
                neueFrage.tiernameZuAntwortJa = letztesBekanntesTier;
            }
            fragensammlung.add(neueFrage);
            return neueFrage;
        }
     
        private void listeAusgeben() {
            TreeSet<String> tierliste = new TreeSet<String>();
            for (Frage frage : fragensammlung) {
                tierliste.add(frage.tiernameZuAntwortJa);
                tierliste.add(frage.tiernameZuAntwortNein);
            }
            ausgabe("----- Liste der bekannten Tiere -----");
            for (String tier : tierliste) {
                ausgabe(tier);
            }
            ausgabe("----- Ende der Liste -----");
        }
     
        private void vergissAlles() {
            Datenbank.leeren();
            fragensammlung.clear();
            ausgabe("xxxxx Alle gespeicherten Tiere wurden gelöscht! xxxxx");
        }
     
        private String eingabe() {
            String eingabetext = "";
            try {
                BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
                eingabetext = input.readLine();
            } catch (Exception e) {
                ausgabe(e.getMessage());
            }
            return eingabetext;
        }
     
        private void ausgabe(String text) {
            System.out.println(text);
        }
     
        public static void main(String[] args) {
            new Spiel();
        }
    }

    Und hier noch die Datenbank-Klasse, für die man zusätzlich die Neodatis-Library benötigt:

    Code:

    package tiereraten;
     
    import org.neodatis.odb.ODB;
    import org.neodatis.odb.ODBFactory;
    import org.neodatis.odb.Objects;
     
    import java.util.ArrayList;
     
    class Datenbank {
     
        private static final String ODB_DATEINAME = "tiere.odb";
        private static ODB datenbank = null;
     
        public static ArrayList<Frage> laden() {
            ArrayList<Frage> fragen = new ArrayList<Frage>();
            try {
                datenbank = ODBFactory.open(ODB_DATEINAME);
                Objects<Frage> objects = datenbank.getObjects(Frage.class);
                while (objects.hasNext()) {
                    fragen.add(objects.next());
                }
            } finally {
                datenbank.close();
            }
            return fragen;
        }
     
        public static void speichern(ArrayList<Frage> fragen) {
            leeren();
            try {
                datenbank = ODBFactory.open(ODB_DATEINAME);
                for (Frage frage : fragen) {
                    datenbank.store(frage);
                }
                datenbank.commit();
            } finally {
                datenbank.close();
            }
        }
     
        public static void leeren() {
            try {
                datenbank = ODBFactory.open(ODB_DATEINAME);
                Objects<Frage> objects = datenbank.getObjects(Frage.class);
                while (objects.hasNext()) {
                    Frage frage = objects.next();
                    datenbank.delete(frage);
                }
                datenbank.commit();
            } finally {
                datenbank.close();
            }
        }
    }

    Den Code gibt es natürlich auch als Download.

    Einen Kommentar hinterlassen »

    Noch kein Feedback

    Einen Kommentar hinterlassen


    Ihre E-Mail-Adresse wird nicht auf dieser Seite angezeigt.

    Ihr URL wird angezeigt.
    (Zeilenumbrüche werden zu <br />)
    (Name, E-Mail-Adresse & Webseite)
    (Benutzern erlauben, Sie durch ein Kontaktformular zu kontaktieren (Ihre E-Mail-Adresse wird nicht weitergegeben))

    ©2010 by Jean-René Thies

    Kontakt |