Создание сложной структуры данных - PullRequest
1 голос
/ 03 апреля 2020

Я пытаюсь самостоятельно изучить c# (asp. net ядро), создав небольшое приложение для викторины, но я не совсем понимаю, как создать сложную модель данных. Представьте себе модель викторины с набором вопросов, таких как:

    public class Quiz
    {
       public int Id { get; set; }
       public Icollection<Question> Questions { get; set; }
    }

Но что, если я хочу разные типы квестов (множественный выбор, true / false, текстовый ответ ...) Могу ли я использовать наследование, чтобы сократить что-то или я просто должен создать другую модель для каждого типа вопроса и вставить их следующим образом:

Public class Quiz
{
   public Icollection<MultipleChoicQuestion> Questions { get; set; }
   public Icollection<TrueOrFalseQuestion> Questions { get; set; }
   public Icollection<TextQuestion> Questions { get; set; }
}

Ответы [ 2 ]

2 голосов
/ 03 апреля 2020

Один из способов сделать это - создать IQuestion интерфейс, содержащий все методы и свойства publi c, необходимые для запуска теста:

public interface IQuestion
{
    void AskQuestion();
    string CorrectAnswer { get; }
    bool IsCorrect { get; }
}

Затем вы можете получить коллекция этого интерфейса в вашем Quiz классе:

public class Quiz
{
    public ICollection<IQuestion> Questions { get; set; }
}

Теперь мы можем создать отдельные классы, каждый из которых реализует свойства и методы IQuestion по-своему.

Например:

public class TextQuestion : IQuestion
{
    public bool IsCorrect => string.Equals(_userAnswer?.Trim(), CorrectAnswer?.Trim(),
        StringComparison.OrdinalIgnoreCase);

    public string CorrectAnswer { get; }

    private readonly string _question;
    private string _userAnswer;

    public TextQuestion(string question, string answer)
    {
        _question = question;
        CorrectAnswer = answer;
    }

    public void AskQuestion()
    {
        Console.WriteLine(_question);
        _userAnswer = Console.ReadLine();
    }
}

public class MultipleChoiceQuestion : IQuestion
{
    public bool IsCorrect => _userIndex == _correctIndex + 1;

    public string CorrectAnswer => (_correctIndex + 1).ToString();

    private readonly string _question;
    private readonly List<string> _choices;
    private readonly int _correctIndex;
    private int _userIndex;

    public MultipleChoiceQuestion(string question, List<string> choices, int correctIndex)
    {
        _question = question;
        _choices = choices;
        _correctIndex = correctIndex;
    }

    public void AskQuestion()
    {
        Console.WriteLine(_question);

        for (var i = 0; i < _choices.Count; i++)
        {
            Console.WriteLine($"{i + 1}: {_choices[i]}");
        }

        _userIndex = GetIntFromUser($"Answer (1 - {_choices.Count}): ",
            i => i > 0 && i <= _choices.Count);
    }

    private static int GetIntFromUser(string prompt, Func<int, bool> validator = null)
    {
        int result;

        do
        {
            Console.Write(prompt);
        } while (!int.TryParse(Console.ReadLine(), out result) &&
                 (validator == null || validator.Invoke(result)));

        return result;
    }
}

public class TrueOrFalseQuestion : IQuestion
{
    public bool IsCorrect => _userAnswer == _correctAnswer;

    public string CorrectAnswer => _correctAnswer.ToString();

    private readonly string _question;
    private readonly bool _correctAnswer;
    private bool _userAnswer;

    public TrueOrFalseQuestion(string question, bool correctAnswer)
    {
        _question = question;
        _correctAnswer = correctAnswer;
    }

    public void AskQuestion()
    {
        _userAnswer = GetBoolFromUser(_question + " (true/false)");
    }

    private static bool GetBoolFromUser(string prompt)
    {
        bool result;

        do
        {
            Console.Write(prompt + ": ");
        } while (!bool.TryParse(Console.ReadLine(), out result));

        return result;
    }
}

Пример использования

static void Main()
{
    var quiz = new Quiz
    {
        Questions = new List<IQuestion>
        {
            new MultipleChoiceQuestion("Which color is also a fruit?",
                new List<string> {"Orange", "Yellow", "Green"}, 0),
            new TextQuestion("What is the last name of our first president?", 
                "Washington"),
            new TrueOrFalseQuestion("The day after yesterday is tomorrow", false),
        }
    };

    foreach (var question in quiz.Questions)
    {
        question.AskQuestion();
        Console.WriteLine(question.IsCorrect
            ? "Correct!\n"
            : $"The correct answer is: {question.CorrectAnswer}\n");
    }

    Console.WriteLine("Your final score is: " +
        $"{quiz.Questions.Count(q => q.IsCorrect)}/{quiz.Questions.Count}");

    GetKeyFromUser("\nPress any key to exit...");
}
1 голос
/ 04 апреля 2020

Этот вопрос не имеет полного отношения к. NET Ядро или EF, как вы отметили, касается моделирования данных.

Для таких моделей разных типов я предлагаю вам сделать это следующим образом.

Вот модель Quiz.

public class Quiz
{
    public int Id { get; set; }
    public List<Question> Questions { get; set; }
}

Вопрос с перечислением

public class Question
{
    public int Id { get; set; }

    public QuestionType Type { get; set; }

    public List<Answer> Answers { get; set; }
}

public enum QuestionType
{
    MultipleChoice,
    TrueFalse,
    Text
}

И последний Answers

public class Answer
{
    public int Id { get; set; }

    public int QuestionId { get; set; } 

    public Question Question { get; set; }

    public bool IsCorrect { get; set; }

    public string Value { get; set; }
}

Для этого Кстати, прикладной уровень будет обрабатывать все процессы, но вы будете хранить данные очень легко.

Для MultipleChoice вопросов добавьте несколько ответов и задайте IsCorrect = true, которые являются правильными.

Для TrueFalse, добавьте только 2 ответа и установите IsCorrect = true для правильных.

Для Text, добавить только 1 ответ и установить IsCorrect = true.

...