2.4 Beispiel: Quiz
In diesem umfangreicheren Beispiel nehmen wir an, dass Sie ein einfaches Ratespiel programmieren möchten: Aus einem Pool von Fragen wählt das Programm zufällig einige aus. Es stellt die Fragen und stellt mehrere mit den Buchstaben a, b, c … gekennzeichnete Multiple-Choice-Antworten zur Wahl. Die Spielerin gibt eine Zeichenkette an (z. B. ad, wenn die erste und die vierte Antwort zutreffen). Das Programm wertet die Antwort aus, stellt die nächste Frage usw.
Klassendesign
In diesem Abschnitt geht es primär darum, die für das Programm notwendigen Klassen zu organisieren. Sie sind noch unerfahren, was das Klassendesign angeht, und bitten ein KI-Tool um Hilfe. Im ersten, sehr ausführlichen Prompt umreißen Sie die Grundfunktionen des Programms und nennen die Programmiersprache.
Sie machen dem KI-Tool gleich klar, dass es bei den Multiple-Choice-Fragen solche gibt, bei denen mehrere richtige Antworten zulässig sind. Für das Design des Programms ist das eine wichtige Information. Ohne diese Angabe wird ChatGPT höchstwahrscheinlich davon ausgehen, dass es pro Frage nur eine richtige Antwort gibt. Wenn Sie das Programm vorerst unter dieser Annahme entwickeln, sind später umfangreiche Änderungen notwendig, um die Funktionalität zu erweitern. Deswegen ist es besser, dieses Detail bereits jetzt zu klären.
Prompt: I would like to write a small quiz game in Java. There is a predefined pool of questions. When the program starts, the player has to answer five questions randomly chosen from the pool.
For each question there is a set of possible answers (min. 2, max. 6). At least one answer has to be correct. Some questions may have more than one correct answer. In this case, ALL correct answers must be selected.
Please help me design the necessary classes. Don’t provide any finished code yet. Just help me decide on good class names and define the right instance variables. Leave constructors and methods for later.
Designing a quiz game in Java requires clear and well-structured classes to manage questions, answers, and the gameplay itself. Below is a proposed class design with suggested instance variables:
-
QuizGame: Manages the overall game flow and logic. Instance Variables:
-
List<Question> questionPool: Holds all possible questions for the game.
-
List<Question> selectedQuestions: Stores the randomly chosen questions for the current game.
-
int score: Tracks the player’s score.
-
int currentQuestionIndex: Keeps track of the current question in the game.
-
-
Question: Represents a single quiz question. Instance Variables:
-
String text: The text of the question.
-
List<Answer> answers: A list of possible answers for this question.
-
List<Answer> correctAnswers: A list of correct answers.
-
int id: Unique identifier for the question (optional, for easier management).
-
-
Answer: Represents a possible answer to a quiz question. Instance Variables:
-
String text: The text of the answer.
-
boolean isCorrect: Indicates whether the answer is correct.
-
int id: Unique identifier for the answer (optional, for easier management).
-
-
Player: Represents the player in the game (…)
-
QuizUtil: Utility class for helper methods (e.g., random selection, validation …)
(detailed description …)
Der Vorschlag ist absolut brauchbar. Sie entscheiden sich dazu, den Code anfänglich in drei Klassen zu organisieren: Main, Question und Answer. Sie beginnen selbstständig mit der Implementierung, richten in Main den Start-Code ein und programmieren die triviale Klasse Answer.
Realisierung der Question-Klasse
Im nächsten Prompt wünschen Sie sich Unterstützung bei der Programmierung der Question-Klasse. Wichtig ist, dass Sie Ihrem KI-Tool mitteilen, welchen Code es schon gibt, weil es darauf in der Question-Klasse Bezug nehmen muss.
Prompt: OK. I created a Main class to run/test the program. I also wrote the Answer class like this:
public class Answer {
public String text;
boolean isCorrect;
// constructor
public Answer(String text, boolean isCorrect) {
this.text = text;
this.isCorrect = isCorrect;
}
}
Next I want to implement Question. Please suggest initial code (only instance variables and the constructor, without the optional id variable).
import ...;
public class Question {
public String text;
public List<Answer> answers;
public List<Answer> correctAnswers;
// Constructor
public Question(String text,
List<Answer> answers,
List<Answer> correctAnswers) {
this.text = text;
this.answers = answers;
this.correctAnswers = correctAnswers;
}
}
Ein Fragen-Pool zum Testen
Bevor Sie sich um die weiteren Methoden dieser Klassen kümmern, brauchen Sie Testmaterial, also einige Quiz-Fragen. Deren Erstellung ist eine eher triste Aufgabe, die sich wunderbar an ChatGPT & Co. delegieren lässt.
Prompt: As a base for testing the code, please provide a method for the Main class to initialize a pool of ten geographic questions.
ChatGPT liefert anfänglich nur Fragen mit genau einer richtigen Antwort. Erst auf Rückfrage fügt das KI-Tool Fragen mit mehreren zutreffenden Antworten hinzu.
Prompt: Perfect. However, you could include a few questions with more than one correct answer (e.g. rivers in Brazil)?
Methoden für die Question-Klasse
Ausgestattet mit ersten Quiz-Fragen geht es nun um die Ausgestaltung der Question-Klasse. Hier sind zumindest zwei Methoden notwendig: eine zur Anzeige einer Frage samt ihrer Lösung sowie zur Eingabe der Antwort, die zweite zur Auswertung der Antwort. Im folgenden Prompt bitten Sie um die Realisierung der ersten Methode, wobei Sie relativ genau angeben, wie die Frage präsentiert werden soll (die Antworten sollen mit Kleinbuchstaben gekennzeichnet werden) und in welchem Format das Programm die Antwort erwartet. Damit das KI-Tool nicht den gesamten Klassen-Code ausgibt, bitten wir darum, dass es nur die neue Methode liefert.
Prompt: Add a method to the Question class to print the question text and all of the enumerated answers such as a), b), c), etc. The method prompts the user for an answer string (for example, "ad" if answers a) and d) are correct). Provide code only for the method, not for the entire class.
Das KI-Werkzeug schlägt gleich zwei neue Methoden vor: askQuestion implementiert die Vorgaben des Prompts und liefert die Antwort als Zeichenkette zurück. Die unaufgefordert mitgelieferte Methode validateAnswer wertet diese Zeichenkette aus und überprüft, ob sie alle zutreffenden Antworten enthält – aber keine weiteren Buchstaben für nicht zutreffende Antworten.
Im vorliegenden Beispiel ist die Methode validateAnswer am kniffeligsten. Aber bevor Sie sich auch nur Gedanken hätten machen können, wie Sie die Auswertung der Zeichenkette selbst programmieren könnten, hat ChatGPT schon eine fertige Methode präsentiert. Ärgerlich.
Den bis hierher erstellten Code finden Sie in den Beispieldateien zu diesem Buch. An dieser Stelle brechen wir dieses Beispiel ab. Natürlich fehlen noch diverse Methoden, um das Programm zu vervollständigen (Spielablauf, zufällige Auswahl von fünf Fragen, Präsentation der Fragen, Anzeige des Ergebnisses, also z. B. drei von fünf Fragen richtig beantwortet etc.). Vielleicht haben Sie Lust, das Beispiel fertigzustellen – das wäre eine gute Übung zur Anwendung von KI-Tools. Oder wir können Sie mit diesem Beispiel dazu motivieren, dieses oder ein ähnliches Spiel selbst mit KI-Hilfe zu realisieren? Dabei entscheiden Sie selbst, in welchem Ausmaß Sie sich unterstützen lassen.
Übereifrige Lernhilfe
Leider sind ChatGPT & Co., soweit es um ihre Anwendung als Lernhilfe geht, tendenziell übereifrig: Die KI-Tools liefern oft mehr Code als notwendig (selbst wenn Sie sich im Prompt explizit das Gegenteil wünschen). Sobald der Code auf dem Bildschirm steht und Sie ihn gelesen haben, sind Sie schon beeinflusst.
Natürlich zwingt Sie niemand, den Code zu übernehmen – aber die Versuchung ist groß. Der Lerneffekt wäre größer, wenn Sie mehr Methoden selbst entwickeln. Wenn Sie dann doch bei einem Problem scheitern, können Sie immer noch um Verbesserungstipps für Ihren halb fertigen Code bitten.
UML-Diagramm
Die grafische Zusammenfassung von Klassen, Variablen bzw. Attributen oder Eigenschaften und Methoden ist eine wertvolle Hilfe, den Überblick zu bewahren.
Abbildung 2.1 UML-Diagramm des Quiz-Programms in einer PlantUML-Darstellung
Mitte 2024 waren die gängigen KI-Tools diesbezüglich leider noch heillos überfordert. Wie der folgende Prompt beweist, gelingt nicht einmal die ASCII-Darstellung des Diagramms fehlerfrei. (Beachten Sie den rechten Rand der Kästchen!)
Prompt: Can you present a UML diagram of the classes so far?
Certainly! Below is a UML diagram that represents the classes and their relationships as described so far for the quiz game. The diagram includes the Main, Question, and Answer classes with their respective attributes and methods.
+-------------------------+
| Main |
+-------------------------+
| + main(args: String[]): void |
| + initializeQuestionPool(): List<Question> |
+-------------------------+
+-------------------------+
| Question |
+-------------------------+
| - text: String |
| - answers: List<Answer> |
| - correctAnswers: List<Answer> |
+-------------------------+
| + Question(text: String, answers: List<Answer>,
| correctAnswers: List<Answer>) |
| + askQuestion(): void |
| - validateAnswer(userInput: String): boolean |
+-------------------------+
Diese Einschränkung können Sie umgehen, wenn Sie das KI-Tool im Prompt bitten, statt des Diagramms Code für ein gängiges Diagramm-Tool zu liefern. Gut geeignet sind Mermaid (https://mermaid.live) und PlantUML (https://www.planttext.com). Zu diesen Bibliotheken gibt es Webseiten, auf denen Sie den UML-Code einfügen und sofort darstellen können.
Prompt: Please generate PlantUML code instead.
@startuml
class Main {
+ main(args: String[]): void
+ initializeQuestionPool(): List<Question>
}
...
KI-Bot oder Code-Assistent?
Je umfangreicher Ihr Code wird und je mehr Arbeit Sie an KI-Tools delegieren, desto ungeeigneter ist die Verwendung eines Chat-Systems (also von ChatGPT oder eines ähnlichen Tools). Das Problem besteht darin, dass das KI-Tool den Überblick über den Code verliert, wenn Sie Teile davon selbst entwickeln.
Natürlich können Sie hin und wieder den aktuellen Stand des Programms in den Prompt einfügen oder per Drag-and-drop zur Verfügung stehen. Dieses mit zunehmender Klassenanzahl immer mühsamere Hin und Her ersparen Sie sich, wenn Sie einen Code-Assistenten verwenden. Dieser hat stets Zugriff auf den gesamten Code.
Gegen den Einsatz eines Code-Assistenten spricht, dass dieser nicht nur auf explizite Aufforderung hin aktiv wird, sondern bei jeder Code-Eingabe oder Änderung Ergänzungsvorschläge macht. Zum effizienten Verfassen von Code ist das hilfreich, zum Lernen weniger.