text: Making The Game – Teil 14: Wissensbasis und Fragenauswahl / Arbeiten mit XML | porzelt.net
  Veröffentlicht Juni 24, 2012 Oktober 4, 2019 max
  Die Wissens- oder Fragenbasis ist das Herzstück des Programms. In ihr werden alle Fragen und Antworten, die den Spielern gestellt werden können, nach Kategorien sortiert eingetragen. Da es nicht erforderlich sein soll, für jeden dieser Fragenkataloge Audiodateien zu hinterlegen, da die Erstellung der einzelnen Sprachdateien den Arbeitsaufwand um ein Vielfaches erhöht, wird in den ersten Zeilen der XML-Datei festgelegt, ob die Fragen im Spiel vorgelesen werden oder nur textuell erscheinen.
  <BASICSETTINGS>
  <ITEM name="audio">trueITEM>
  BASICSETTINGS>
  (Anmerkung: Da die Anwendung und diese Entscheidung alle Audio-Parts manuell einzusprechen mittlerweile bereits ein halbes Jahr alt ist, würde ich diese Vorgehensweise heute komplett über den Haufen werfen und auf eine TTS-API, wie die inoffizielle von Google, zurückgreifen. Ich werde hier dennoch meine damalige Vorgehensweise beschreiben.)
  Jede Frage im Katalog wird dabei durch eine eigene Identifikationsnummer gekennzeichnet. Durch diese könnten später in einem Autoren-Tool die Fragen direkt per ID angesprochen werden. Darüber hinaus ist sie für den Fragen-Autor ein Indikator dafür, wie viele Fragen bereits in einer Kategorie erstellt wurden.
  Die mögliche Punkteanzahl für die Frage spiegelt deren Schwierigkeitsgrad wieder. Der niedrigste Wert, der für eine Frage gegeben werden kann, ist 1000 Punkte, was dem Spielerlevel 1 entspricht. Entsprechende höhere Level werden durch 2000, 3000,… Punkte im Fragenkatalog dargestellt. Bei der Punkteeinteilung besteht keine Obergrenze, jedoch sollten Fragen über 4000 Punkten vermieden werden, da der Spieler durch falsches Beantworten diese abgezogen bekommt, was bei sehr hohen Werten schnell zu Frustrationen führen kann.
  Die wichtigsten Entitäten in der XML-Datei sind jedoch die eigentliche Frage, die Antworten sowie die Nummer der richtigen Antwort. Diese enthalten den Fragentext, welcher im Programm animiert eingeblendet wird sowie die vier möglichen Antworten, die der Spieler vorgegeben bekommt.
  <CATEGORY name="Das Internet? Gibts den Blödsinn immer noch?">
  <CATEGORYAUDIO>
  <ITEM name="category">catalog/cat/cat7.mp3ITEM>
  CATEGORYAUDIO>
  <QUESTION id="3">
  <ITEM name="points">2000ITEM>
  <ITEM name="text">Wie nennt man die Pauschalgebühr für eine
  Internet– oder Telefonverbindung?ITEM>
  <ITEM name="a1">OverrateITEM>
  <ITEM name="a2">ConnectionrateITEM>
  <ITEM name="a3">FlatrateITEM>
  <ITEM name="a4">FreiminutenITEM>
  <ITEM name="correct">3ITEM>
  <ITEM name="pretalk">ITEM>
  <ITEM name="text">catalog/ID005/q_3_0.mp3ITEM>
  <ITEM name="a1">catalog/ID005/q_3_1.mp3ITEM>
  <ITEM name="a2">catalog/ID005/q_3_2.mp3ITEM>
  <ITEM name="a3">catalog/ID005/q_3_3.mp3ITEM>
  <ITEM name="a4">catalog/ID005/q_3_4.mp3ITEM>
  <ITEM name="correct">catalog/ID005/q_3_5.mp3ITEM>
  AUDIOFILES>
  Wie in dem Auszug aus dem Allgemeinwissen-Fragenkatalog zu erkennen ist, stellt die Verlinkung der einzelnen Audio-Komponenten einen großen Teil der Struktur dar.
  (Anmerkung: Und eigentlich hätte man an dieser Stelle eine feste Konvention wählen sollen um zu bestimmen wie die Dateien benannt sind, damit diese automatisch und ohne einTrag in der XML-Datei gelesen und wiedergegeben werden können. Aber auf die Idee kam ich halt nicht. -.-)
  Die Bezeichnung der einzelnen Audio-Einträge wurde korrespondierend zu den textuellen Einträgen angelegt, damit schnell ersichtlich wird, in welcher Ton-Datei welcher Textabschnitt gesprochen wird.
  Die einzigen Ausnahmen stellen dabei die Einträge unter "pretalk" und "correct" dar. In der Aufnahme für den "correct"-Eintrag wird nicht nur die richtige Antwort vorgelesen, sondern es sollte eine erweiterte Erklärung erfolgen, warum die entsprechende Antwort richtig ist. Im Spiel selbst wird die Datei abgespielt, sobald die Lösung der Antwort angezeigt wird.
  Durch die Verwendung des "pretalk"-Eintrags kann der Autor des Fragenkatalogs mit einer kurzen Beschreibung zur eigentlichen Frage hinführen bzw. den Spieler durch eine kurze Erklärung, worum es in der kommenden Frage geht, ins Bilde setzen. Der Eintrag ist dabei optional und muss nicht verwendet werden.
  Die zufällige Auswahl der jeweiligen Frage während der Spielrunde erfolgt automatisch mit dem Aufruf der Funktion selectQuestion() (siehe Code unten). Diese prüft, ob momentan eine Runde gespielt wird oder ob außerhalb der Spielrunden eine Frage angefordert wird, was zum Beispiel im Trainingsmodus vorkommt. Ist derzeit eine Spielrunde im Gange, wird der aktuelle Spieler-Level für spätere Gültigkeitsprüfungen übernommen.
  Aus einer zufälligen Kategorie wird danach eine beliebige Frage gewählt. Um sicherzugehen, dass diese auch geeignet ist, wird geprüft, ob sie im Bereich des Spieler-Levels liegt. In der nächsten Instanz wird geprüft, ob die ID der Frage bereits in der Liste der gestellten Fragen enthalten ist.
  Liegt die Frage außerhalb des Spieler-Levels oder wurde sie bereits gestellt, wird eine neue Frage per Zufall ausgewählt. Dieser Vorgang wird wiederholt, bis eine Frage gefunden wurde, die beide Bedingungen erfüllt.
  function selectQuestion():XML{
  var lvl:int = 999;
  // get current player level if we are in a match
  if(questionNumber>0){
  lvl = game_level;
  var categorySelected:int;
  var questionSelected:int;
  var simpleCounter:int = 0;
  simpleCounter++;
  // GET NUMBER OF CATEGORIES
  var categoryAmmount:int = basicXMLCatalog.CATEGORY.length();
  // select one category randomly
  categorySelected = randomNumber(1,categoryAmmount);
  // GET NUMBER OF QUESTIONS IN THE CATEGORY
  var questionAmmount:int =
  basicXMLCatalog.CATEGORY[categorySelected–1].
  QUESTION.length();
  // select one question randomly
  questionSelected = randomNumber(1, questionAmmount);
  // check if the question is in the current level-range
  var possiblePoints =
  QUESTION[questionSelected–1].ITEM.(@name=="points");
  var outOfRange:Boolean = true;
  if(possiblePoints <= lvl*1000){ outOfRange = false; }
  // check if the question was already asked
  // if indexOf == -1 –> not asked
  var alreadyAsked:Boolean = true;
  if((questionIDStore.indexOf(categorySelected +
  "-" + questionSelected)) < 0){
  // failsafe… no questions… go out of level-range
  if(simpleCounter > 20){ outOfRange = false; }
  // failsafe #2… just ask a question again
  if(simpleCounter > 40){ alreadyAsked = false; }
  // search until the question was not already asked
  } while (outOfRange || alreadyAsked);
  // at this point we have a question selected!
  // save the question ID – we dont want to ask it again
  questionIDStore.push(categorySelected + "-" + questionSelected);
  // save the question data
  question_currentXML =
  QUESTION[questionSelected–1];
  // return the xml-data
  return question_currentXML;
  Da nicht sichergestellt werden kann, dass ausreichend Fragen in der verwendeten Wissensbasis hinterlegt sind, muss eine Notfallstrategie gewählt werden. So werden nach zwanzig ergebnislosen Durchläufen, eine passende Frage zu finden, auch Fragen zugelassen, die außerhalb des Spielerlevels liegen, aber noch nicht gestellt wurden.
  Sollte nach weiteren zwanzig Durchläufen immer noch keine Frage gefunden worden sein, können auch bereits gestellten Fragen wieder gestellt werden. Somit kann sichergestellt werden, dass das Spiel auch mit schlecht erstellten Wissensbasen bis zum Rundenende durchspielbar ist.
  Ist eine Frage gewählt und wurde sie als geeignet bewertet, wird ihre ID zu der Liste der gestellten Fragen hinzugefügt, alle zugehörigen Daten werden aus der XML-Datei gelesen und für die weitere Verwendung zwischengespeichert.