C# :: Aufgabe #67
3 Lösungen

Quiz mittels LINQ in einer Xml-Datei
Fortgeschrittener - C#
von Miako
- 17.09.2014 um 21:13 Uhr
Schreibe ein Quiz-Programm, welches seine Fragen und Antworten durch LINQ (XmlReader-Klasse ist tabu) aus einer Xml-Datei bezieht.
Die Xml-Datei soll frei erweiterbar sein, sofern ein vorgegebenes Schema eingehalten wird.
Das Programm soll die Xml-Datei auslesen und dem Benutzer die Fragen in eine zufällige Reinfolge ausgeben. Bereits verwendete Fragen sollen kein zweites mal an die Reihe kommen. Die Anzahl der möglichen Antworten bleibt euch überlassen. Natürlich soll geprüft werden, ob die Antwort des Benutzers korrekt ist. Zu guter Schluss soll die korrekte Antwort in der Xml-Datei angegeben werden können.
Viel Spaß beim Planen und schreiben. Ich freue mich auf eure Fragen und Lösungen!
Die Xml-Datei soll frei erweiterbar sein, sofern ein vorgegebenes Schema eingehalten wird.
Das Programm soll die Xml-Datei auslesen und dem Benutzer die Fragen in eine zufällige Reinfolge ausgeben. Bereits verwendete Fragen sollen kein zweites mal an die Reihe kommen. Die Anzahl der möglichen Antworten bleibt euch überlassen. Natürlich soll geprüft werden, ob die Antwort des Benutzers korrekt ist. Zu guter Schluss soll die korrekte Antwort in der Xml-Datei angegeben werden können.
Zitat:
Tipps und Hinweise
Am besten benutzt ihr für das Einlesen der Fragen und Antworten, sowie das Entfernen beantworteter Fragen ein Array, oder eine Liste.
Zum bestimmen der korrekten Antwort eignet sich ein Attribut für die jeweiligen Antwort in der Xml-Datei.
Viel Spaß beim Planen und schreiben. Ich freue mich auf eure Fragen und Lösungen!
Lösungen:
Hier meine Lösung:
Meine XML-Datei sieht so aus:
XML-Code
Mit dem Attribut "istrue" gibt man an, ob diese Antwort die richtige ist.
C#-Code
die darin enthaltenen Extension-Methods:
C#-Code
Meine XML-Datei sieht so aus:

<?xml version='1.0' encoding='UTF-8'?> <quiz> <frage wortlaut="Hier ist die 1. Frage?"> <antwort wortlaut="richtige Antwort" istrue="true" /> <antwort wortlaut="falsche Antwort 1" istrue="false" /> <antwort wortlaut="falsche Antwort 2" istrue="false" /> </frage> <frage wortlaut="Hier ist die 2. Frage?"> <antwort wortlaut="richtige Antwort" istrue="true" /> <antwort wortlaut="falsche Antwort 1" istrue="false" /> <antwort wortlaut="falsche Antwort 2" istrue="false" /> <antwort wortlaut="falsche Antwort 3" istrue="false" /> </frage> </quiz>
Mit dem Attribut "istrue" gibt man an, ob diese Antwort die richtige ist.

void Main() { string xmlFile = "quiz.xml"; var xmlDoc = XDocument.Load(xmlFile); var fragen = xmlDoc.Descendants("frage").Select(f=> new Frage { Wortlaut = f.Attribute("wortlaut").Value, Antworten = f.Descendants("antwort").Select(a => new Antwort() { Wortlaut = a.Attribute("wortlaut").Value, isTrue = a.Attribute("istrue").Value.ToLower() == "true"}).ToArray() }); //Fragen in zufällige Reihenfolge bringen var randomFragen = fragen.ToList().ShuffleSimple(); //Antworten der Fragen in zufällige Reihenfolge bringen randomFragen.ForEach(x=>x.Antworten = x.Antworten.ShuffleSimple().ToArray()); for (int i = 0; i < randomFragen.Count; i++) { //Frage ausgeben Console.WriteLine(string.Format("Frage {0}: {1}", (i+1), randomFragen[i].Wortlaut)); //Antworten dazu ausgeben for (int j = 0; j < randomFragen[i].Antworten.Count(); j++) { Console.WriteLine(string.Format("\t{0}) {1}", (j+1), randomFragen[i].Antworten[j].Wortlaut)); } Console.Write("Deine Antwort: "); string antw = Console.ReadLine(); if (randomFragen[i].Antworten[int.Parse(antw)-1].isTrue) { Console.WriteLine("richtig\n"); } else { Console.WriteLine("falsch\n"); } } } public class Frage { public string Wortlaut { get; set; } public Antwort[] Antworten { get; set; } } public class Antwort { public string Wortlaut { get; set; } public bool isTrue { get; set; } }
die darin enthaltenen Extension-Methods:

public static IList<T> ShuffleSimple<T>(this IList<T> list) { Random rng = new Random(); int n = list.Count; while (n > 1) { n--; int k = rng.Next(n+1); T value = list[k]; list[k] = list[n]; list[n] = value; } return list; } public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action) { foreach (T v in collection) action(v); }
XML:
C#-Code
<?xml version="1.0" encoding="utf-8"?>
<Quiz>
<Frage Id="0" Richtig="A" Text="Welche Farbe hat der Himmel?" A="Blau" B="Grün" C="Braun" D="Rosa"/>
<Frage Id="1" Richtig="C" Text="Wie viel Räder hat ein Dreirad?" A="1" B="2" C="3" D="4"/>
</Quiz>

using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Xml.Linq; namespace WPFQuiz { /// <summary> /// Interaktionslogik für MainWindow.xaml /// </summary> public partial class MainWindow : Window { static Random rnd = new Random(); XDocument doc; List<Question> questions; Question currentQuestion; public MainWindow() { InitializeComponent(); doc = XDocument.Load(@"Dateipfad"); questions = (from q in doc.Descendants("Frage") select new Question() { Id = Convert.ToInt32(q.Attribute("Id").Value), CorrectAnswer = q.Attribute("Richtig").Value, Text = q.Attribute("Text").Value, AnswerA = q.Attribute("A").Value, AnswerB = q.Attribute("B").Value, AnswerC = q.Attribute("C").Value, AnswerD = q.Attribute("D").Value }).ToList(); NextQuestion(); } private void NextQuestion() { int index = rnd.Next(0, questions.Count); currentQuestion = questions[index]; textBlockCount.Text = currentQuestion.Id.ToString(); textBlockFrage.Text = currentQuestion.Text; buttonA.Content = currentQuestion.AnswerA; buttonB.Content = currentQuestion.AnswerB; buttonC.Content = currentQuestion.AnswerC; buttonD.Content = currentQuestion.AnswerD; } private void EnableAll(bool enabled) { buttonA.IsEnabled = enabled; buttonB.IsEnabled = enabled; buttonC.IsEnabled = enabled; buttonD.IsEnabled = enabled; } private void button_Click(object sender, RoutedEventArgs e) { EnableAll(false); string button = ((Button)sender).Name.Substring(6, 1); if (button == currentQuestion.CorrectAnswer) { MessageBox.Show("Richtig"); } else { MessageBox.Show("Falsch! Richtig ist: " + currentQuestion.CorrectAnswer); } } private void buttonNext_Click(object sender, RoutedEventArgs e) { EnableAll(true); NextQuestion(); } } class Question { public int Id { get; set; } public string CorrectAnswer { get; set; } public string Text { get; set; } public string AnswerA { get; set; } public string AnswerB { get; set; } public string AnswerC { get; set; } public string AnswerD { get; set; } } }
XML:
XML-Code
Code:
C#-Code

<?xml version="1.0" encoding="utf-8" ?> <Quiz> <Fragen> <Frage> <Fragestellung>Wie schwer werden Elefanten? (in KG)</Fragestellung> <Antworten> <Antwort>6000</Antwort> <Antwort>schwer</Antwort> </Antworten> </Frage> <Frage> <Fragestellung>Welche Farbe hat eine Käse?</Fragestellung> <Antworten> <Antwort>Gelb</Antwort> <Antwort>manchmal auch braun</Antwort> </Antworten> </Frage> <Frage> <Fragestellung>Wie groß werden Bäume?</Fragestellung> <Antworten> <Antwort>groß</Antwort> <Antwort>ein paar Meter</Antwort> </Antworten> </Frage> <Frage> <Fragestellung>Wieviele Fliegen fliegen wenn Fliegen fliegen?</Fragestellung> <Antworten> <Antwort>10</Antwort> <Antwort>10000</Antwort> <Antowrt>237537853582</Antowrt> </Antworten> </Frage> <Frage> <Fragestellung>Was machen Sachen?</Fragestellung> <Antworten> <Antwort>Sachen</Antwort> </Antworten> </Frage> <Frage> <Fragestellung>Wie geht es dir?</Fragestellung> <Antworten> <Antwort>Gut</Antwort> </Antworten> </Frage> <Frage> <Fragestellung>Wieviele Würste braucht man um glücklich zu sein?</Fragestellung> <Antworten> <Antwort>17</Antwort> </Antworten> </Frage> <Frage> <Fragestellung>Wasabi</Fragestellung> <Antworten> <Antwort>Ja</Antwort> </Antworten> </Frage> </Fragen> </Quiz>
Code:

static void XML_Auslesen_LINQ() { string path = @"C:\Users\cklein\source\repos\TrainYourProgrammer\TrainYourProgrammer\XMLFile1.xml", answer; Random rnd = new Random(); int random; List<string> listQuestions = new List<string>(), listAnswers = new List<string>(); XDocument xDoc = XDocument.Load(path); var queryQuestions = from qst in xDoc.Descendants("Fragestellung") select qst.Value; listQuestions = queryQuestions.ToList(); while (listQuestions.Count > 0) { random = rnd.Next(0, listQuestions.Count); Console.Write(listQuestions[random] + " "); answer = Console.ReadLine(); var queryAnswers = from answ in xDoc.Descendants("Antworten").Descendants() where answ.Parent.Parent.Element("Fragestellung").Value == listQuestions[random] select answ.Value; listAnswers = queryAnswers.ToList(); if (listAnswers.Contains(answer, StringComparer.OrdinalIgnoreCase)) { Console.WriteLine("Die Antwort ist korrekt."); } else { Console.WriteLine("Die Antwort war.. falsch!"); } Console.WriteLine("Korrekte Antwortmöglichkeiten: " + String.Join(", ", listAnswers.ToArray())); Console.WriteLine(); listQuestions.Remove(listQuestions[random]); } }