S
S
sulim0003332019-01-12 12:46:23
C++ / C#
sulim000333, 2019-01-12 12:46:23

How to write this code correctly / how to optimize this "code"?

Do not pay attention to the code that is too stupid and incorrectly written, I'm just learning and I wanted to implement the idea with my level of knowledge)

using System;

namespace DefaultProject
{
  class MainClass
  {
    public static void Main (string[] args)
    {
      Console.WriteLine ("Всем привет! И это моя первая мини-программа для проверки ваших знаний языка программирования C#\nЕсли готовы пройти тест напишите Go, а если хотите выйти напишите Exit.");
      string st = Console.ReadLine ();
      switch (st) 
      {
      case "Go":
        Console.WriteLine ("1.Какая команда выводит текст в консоль? \n 1. if/else \n 2. System.out.println(); \n 3. Console.WriteLine(); \n 4. int x = 10;");
        string questionstr1 = Console.ReadLine ();
        int question1 = Convert.ToInt32 (questionstr1);
        if (question1 >= 0) {
          Console.WriteLine("2.Какой тип из списка целочисленный? \n 1. char \n 2. int \n 3. float \n 4. double");
          string questionstr2 = Console.ReadLine ();
          int question2 = Convert.ToInt32 (questionstr2);
          if (question2 >= 0) {
            Console.WriteLine ("3.Какой тип из списка строчный? \n 1. string \n 2. byte \n 3. char \n 4. decimal");
            string questionstr3 = Console.ReadLine ();
            int question3 = Convert.ToInt32 (questionstr3);
            if (question3 >= 0) {
              Console.WriteLine ("4.Какой тип переменной используется в коде: int a = 5? \n 1. Знаковое 32-бит целое \n 2. Знаковое 64-бит целое \n 3. Знаковое 8-бит целое \n 4. 1 байт");
              string questionstr4 = Console.ReadLine ();
              int question4 = Convert.ToInt32 (questionstr4);
              if (question4 >= 0) {
                Console.WriteLine ("5.Сколько условных конструкций есть в C#? \n 1 \n 2 \n 3 \n 4");
                string questionstr5 = Console.ReadLine ();
                int question5 = Convert.ToInt32 (questionstr5);
                if (question5 >= 0) {
                  switch (question1) {
                  case 3:
                    Console.WriteLine ("На первый вопрос вы ответили: 3. Console.WriteLine(); \n Правильно!");
                    break;
                  default:
                    Console.WriteLine ("Первый вопрос: Неправильный ответ!. Вы выбрали: " + question1);
                    break;
                  }
                  switch (question2) {
                  case 2:
                    Console.WriteLine ("На второй вопрос вы ответили: 2. int \n Правильно!");
                    break;
                  default:
                    Console.WriteLine ("Второй вопрос: Неправильный ответ!. Вы выбрали: " + question2);
                    break;
                  }
                  switch (question3) {
                  case 1:
                    Console.WriteLine ("На третий вопрос вы ответили: 1. string \n Правильно!");
                    break;
                  default:
                    Console.WriteLine ("Третий вопрос: Неправильный ответ!. Вы выбрали: " + question3);
                    break;
                  }
                  switch (question4) {
                  case 1:
                    Console.WriteLine ("На четвертый вопрос вы ответили: 1. Знаковое 32-бит целое \n Правильно!");
                    break;
                  default:
                    Console.WriteLine ("Четвертый вопрос: Неправильный ответ!. Вы выбрали: " + question4);
                    break;
                  }
                  switch (question5) {
                  case 3:
                    Console.WriteLine ("На пятый вопрос вы ответили: 3 \n Правильно!");
                    break;
                  default:
                    Console.WriteLine ("Пятый вопрос: Неправильный ответ!. Вы выбрали: " + question5);
                    break;
                    }
                  if ((question1 != 3) && (question2 != 2) && (question3 != 1) && (question4 != 1) && (question5 != 3)) {
                    Console.WriteLine ("Вы на все вопросы ответили неправильно! Тест пройден на 0% ");
                  }
                  if ((question1 == 3) && (question2 == 2) && (question3 == 1) && (question4 == 1) && (question5 == 3)) {
                    Console.WriteLine ("Вы на все вопросы ответили правильно! Тест пройден на 100%! ");
                  }
                }
              }
            }
          }
        }
        break;
      }
      Console.ReadKey ();
    }
  }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
F
Fat Lorrie, 2019-01-12
@sulim000333

The first thing to do is to define the domain entities with which the program will work. In your case it is:

  • test, which consists of questions;
  • a question that consists of text and answers (ordered by index);
  • the answer, which consists of text and a sign of correctness.
The code
public class Test
{
    public IList<Question> Questions { get; set; }
}

public class Question
{
    public string Text { get; set; }
    public IList<Answer> Answers { get; set; }
}

public class Answer
{
    public string Text { get; set; }
    public bool IsRight { get; set; }
}

It is necessary to decompose the task into atomic subtasks. Each subtask can be moved to a separate function to limit the scope of code responsibility ( in the spirit of SOLID in general and SRP in particular ), in order to protect yourself from the "butterfly effect" when a small change in a piece of code in one part of the application destroys the rest of the work in another part . Yes, and it will be easier to read the code without getting confused in the implementation details from a huge footcloth of inextricable code with non-obvious variable connections. It turns out something like this:
Then it is necessary to form the structure of the test. To do this, you can create a factory function that returns a new test object (the data is hardcoded like this, read from the database, go to the Internet for them ... whatever, we are interested in testing itself):
The code
public static Test CreateTest()
{
    return new Test
    {
        Questions = new List<Question>
        {
            new Question
            {
                Text = "Какая команда выводит текст в консоль?",
                Answers = new List<Answer>
                {
                    new Answer { Text = "if/else" },
                    new Answer { Text = "System.out.println();" },
                    new Answer { Text = "Console.WriteLine();", IsRight = true },
                    new Answer { Text = "int x = 10;" }
                }
            },
            new Question
            {
                Text = "Какой тип из списка целочисленный?",
                Answers = new List<Answer>
                {
                    new Answer { Text = "char" },
                    new Answer { Text = "int", IsRight = true },
                    new Answer { Text = "float" },
                    new Answer { Text = "double" }
                }
            }
            //,...
        }
    };
}

Let the program, like yours, greet the user, and then, until he enters one of the two correct outputs (case insensitive ( ...IngoreCase)), will show a prompt with a hint. If Go- we call the creation of the test and go into the game. If the game is over or the user initially entered Exit- print the famous Press any key...and exit the program.
The code
public static void Main()
{
    Console.WriteLine("Всем привет! И это моя первая мини-программа для проверки ваших знаний языка программирования C#");
    string input;
    
    do
    {
        Console.WriteLine("Если готовы пройти тест напишите Go, а если хотите выйти напишите Exit.");
        input = Console.ReadLine();

        if (input.Equals("Go", StringComparison.InvariantCultureIgnoreCase))
        {
            var test = CreateTest();
            PlayGame(test); // <----- Логика тестирования находится здесь
        }
    } while (   !input.Equals("Go", StringComparison.InvariantCultureIgnoreCase)
             && !input.Equals("Exit", StringComparison.InvariantCultureIgnoreCase));

    Console.WriteLine("Для выхода нажмите любую клавишу...");
    Console.ReadKey();
}

For the game, we need an array with numbers of "failed" questions (which will be useful for statistics at the end - CalculateResult). We bypass all questions from the test by first displaying their text with options on the screen ( PrintQuestion), then asking the user for his choice ( GetUserChoice). Then the answer is checked ( IsCorrectAnswer), if it is wrong - add the number of the answer ( iis the array index from zero, so +1) to the error array. After all the questions, we calculate and display the statistics.
The code
private static void PlayGame(Test test)
{
    var mistakes = new List<int>();
    for (int i = 0; i < test.Questions.Count; ++i)
    {
        var question = test.Questions[i];
        PrintQuestion(question, i);

        int choice = GetUserChoice(question.Answers.Count);

        if (!IsCorrectAnswer(choice, question.Answers))
        {
            mistakes.Add(i + 1);
        }
    }

    CalculateResults(test.Questions.Count, mistakes);
}

The question is printed in an elementary way: first its text, then the answer options, which are preceded by a tab ( \t) to indent the list:
The code
private static void PrintQuestion(Question question, int questionIndex)
{
    Console.WriteLine($"{questionIndex + 1}. {question.Text}");

    for (int i = 0; i < question.Answers.Count; ++i)
    {
        Console.WriteLine($"\t{i + 1}. {question.Answers[i].Text}");
    }
}

Getting the user's variant is done in a loop similar to the Go / Exit input at the beginning. Its completion is controlled by the variable isCorrectInput, which is set equal trueonly at the very end, when the value is successfully parsed and passes the check for the validity of the response number (from 1 to the maximum response number):
The code
private static int GetUserChoice(int answersCount)
{
    bool isCorrectInput = false;
    int choice = -1;
    do
    {
        try
        {
            Console.WriteLine("Введите номер ответа:");
            string input = Console.ReadLine();
            choice = Convert.ToInt32(input);
            if (choice >= 1 && choice <= answersCount) isCorrectInput = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Неправильный формат ввода");
        }
    } while (!isCorrectInput);

    return choice;
}

To check the correctness, we first highlight the correct answers to the question ( rightAnswers), and then compare their ordinal indices with the index selected by the user. If at least one answer matches (yes, there may be several) - will return true:
The code
private static bool IsCorrectAnswer(int choice, IList<Answer> answers)
{
    var rightAnswers = answers.Where(x => x.IsRight);
    int chosenAnswerIndex = choice - 1;
    return rightAnswers.Any(x => answers.IndexOf(x) == chosenAnswerIndex);
}

Well, cherry - a printout of the results. If there are no errors - everything is buzzing, 100% solutions. If there are errors, then we solve a simple proportion by calculating how many percent of the wrong answers were given, and then subtract them from 100%, getting the percentage of success.
The code
private static void CalculateResults(int questionsCount, IList<int> mistakes)
{
    if (mistakes.Count == 0)
    {
        Console.WriteLine("Вы на все вопросы ответили правильно! Тест пройден на 100%! ");
    }
    else
    {
        string invalidQuestionsString = string.Join(", ", mistakes.Select(x => $"#{x}"));
        int progressPercentage = 100 - (int)Math.Ceiling(100 * (double)mistakes.Count / questionsCount);
        Console.WriteLine($"Среди ваших ответов есть неправильные ({mistakes.Count}: {invalidQuestionsString})). Тест пройден на {progressPercentage}% ");
    }
}

PS You can play with the code, try to add more questions, force interruption after the first wrong answer, handle multiple correct answers (add or points for partial guessing), diversify the types of questions and so on.
Full listing on ideone

P
Pavel, 2019-01-12
@youkerni

Imagine that your test has 1000 questions, not 5. You will get a little tired, I think.
Well, if from primitive errors - what will happen if you are given a string as an answer, and not a number?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question