I wanted to practice OOP when writing a program so I decided to make a simple test/quiz. I would appreciate any corrections and improvements to make my code cleaner/shorter/more extensible/more efficient/better naming/more loosely coupled, because right now I feel like my program works but it's tightly coupled and frankly looks horrible (and extremely long...).
program.cs
public class Program
{
public static void Main()
{
var test = new UserInterface();
test.RunHowGoodAreYouTest();
}
}
UserInterface.cs
public class UserInterface
{
public void RunHowGoodAreYouTest()
{
var random = new Random();
var possibleQuestions = Enumerable.Range(0, TestGenerator.TotalQuestions).ToList();
var questionsLeft = TestGenerator.TotalQuestions;
var points = 0;
TestGenerator.DisplayIntro();
while (true)
{
var randomQuestionIndex = RandomQuestionGenerator.GenerateRandomQuestion(random, possibleQuestions);
var currentQuestion = TestGenerator.Questions[randomQuestionIndex];
TestGenerator.DisplayCurrentQuestion(currentQuestion);
var chosenAnswer = Console.ReadLine();
while (!Utilities.IsValidInput(chosenAnswer))
{
Utilities.DisplayMessage("\nError. Please type A, B, C or D. Or type 'exit' to quit the test.\n");
chosenAnswer = Console.ReadLine();
}
if (Utilities.ExitTest(chosenAnswer))
break;
var chosenAnswerId = Utilities.TranslateAnswer(chosenAnswer);
points = PointsSum.SumPointsFromInput(points, currentQuestion.Question.Id, chosenAnswerId);
if (questionsLeft == 1)
break;
questionsLeft--;
}
PointsCalculation.CalculatePointsResult(points);
}
}
RandomQuestionGenerator.cs
public static class RandomQuestionGenerator
{
public static int GenerateRandomQuestion(Random random, List<int> possibleQuestions)
{
var randomNum = random.Next(0, possibleQuestions.Count);
var randomQuestionIndex = possibleQuestions[randomNum];
possibleQuestions.RemoveAt(randomNum);
return randomQuestionIndex;
}
}
question.cs
public class Question
{
public Question(int id, string title)
{
Id = id;
Title = title;
}
public int Id { get; set; }
public string Title { get; set; }
}
answer.cs
public class Answer
{
public int Id { get; set; }
public string Title { get; set; }
public int Points { get; set; }
public Answer(int id, string title, int points)
{
Id = id;
Title = title;
Points = points;
}
}
QuestionAndAnswers.cs
public class QuestionAndAnswers
{
public QuestionAndAnswers(Question question, Answer answerA, Answer answerB, Answer answerC, Answer answerD)
{
Question = question;
AnswerA = answerA;
AnswerB = answerB;
AnswerC = answerC;
AnswerD = answerD;
}
public Question Question { get; set; }
public Answer AnswerA { get; set; }
public Answer AnswerB { get; set; }
public Answer AnswerC { get; set; }
public Answer AnswerD { get; set; }
}
PointsSum.cs
public static class PointsSum
{
public static int SumPointsFromInput(int points, int currentQuestionId, int chosenAnswerId)
{
var currentQuestion = TestGenerator.Questions.Find(q => q.Question.Id == currentQuestionId);
if (currentQuestion.AnswerA.Id == chosenAnswerId)
points += currentQuestion.AnswerA.Points;
else if (currentQuestion.AnswerB.Id == chosenAnswerId)
points += currentQuestion.AnswerB.Points;
else if (currentQuestion.AnswerC.Id == chosenAnswerId)
points += currentQuestion.AnswerC.Points;
else if (currentQuestion.AnswerD.Id == chosenAnswerId)
points += currentQuestion.AnswerD.Points;
return points;
}
}
PointsCalculation.cs
public static class PointsCalculation
{
private static readonly int NotGoodLimit =
(int) Math.Floor(TestGenerator.TotalQuestions * TestGenerator.NumberOfAnswersPerQuestion / 3.0);
private static readonly int GoodLimit =
(int) Math.Floor(TestGenerator.TotalQuestions * TestGenerator.NumberOfAnswersPerQuestion / 2.0);
private static readonly int VeryGoodLimit =
(int) Math.Floor(TestGenerator.TotalQuestions * TestGenerator.NumberOfAnswersPerQuestion / 1.3);
private static readonly int SaintLimit =
TestGenerator.TotalQuestions * TestGenerator.NumberOfAnswersPerQuestion;
public static void CalculatePointsResult(int points)
{
if (points <= NotGoodLimit)
Utilities.DisplayMessage("\nYou got " + points + " points out of " + SaintLimit +
". \nYou are quite evil aren't you?\n");
else if (points <= GoodLimit)
Utilities.DisplayMessage("\nYou got " + points + " points out of " + SaintLimit +
". \nYou are borderline good.\n");
else if (points <= VeryGoodLimit)
Utilities.DisplayMessage("\nYou got " + points + " points out of " + SaintLimit +
". \nYou are a good person.\n");
else if (points <= SaintLimit)
Utilities.DisplayMessage("\nYou got " + points + " points out of " + SaintLimit +
". \nYou are pretty much a Saint. Congrats!!\n");
}
}
Utilities.cs
public class Utilities
{
public static void DisplayMessage(string message)
{
Console.WriteLine(message);
}
public static bool ExitTest(string input)
{
return input.ToLower().Equals("exit");
}
public static bool IsValidInput(object input)
{
if (!(input is string))
return false;
var strInput = (string) input;
strInput = strInput.Trim().ToUpper();
switch (strInput)
{
case "A":
case "B":
case "C":
case "D":
case "EXIT":
return true;
default:
return false;
}
}
public static int TranslateAnswer(string choice)
{
switch (choice.Trim().ToUpper())
{
case "A":
return 1;
case "B":
return 2;
case "C":
return 3;
case "D":
return 4;
default:
return -1;
}
}
}
TestGenerator.cs
public static class TestGenerator
{
public static readonly List<QuestionAndAnswers> Questions = new List<QuestionAndAnswers>();
public static readonly int TotalQuestions;
public static readonly int NumberOfAnswersPerQuestion = 4;
public const int QuestionIdHomelessMan = 1;
public const int AnswerIdHomelessManA = 1;
public const int AnswerIdHomelessManB = 2;
public const int AnswerIdHomelessManC = 3;
public const int AnswerIdHomelessManD = 4;
public const int QuestionIdLittleSibling = 2;
public const int AnswerIdLittleSiblingA = 1;
public const int AnswerIdLittleSiblingB = 2;
public const int AnswerIdLittleSiblingC = 3;
public const int AnswerIdLittleSiblingD = 4;
public const int QuestionIdFriendInJail = 3;
public const int AnswerIdFriendInJailA = 1;
public const int AnswerIdFriendInJailB = 2;
public const int AnswerIdFriendInJailC = 3;
public const int AnswerIdFriendInJailD = 4;
public const int QuestionIdOldLady = 4;
public const int AnswerIdOldLadyA = 1;
public const int AnswerIdOldLadyB = 2;
public const int AnswerIdOldLadyC = 3;
public const int AnswerIdOldLadyD = 4;
static TestGenerator()
{
GenerateQuestions();
TotalQuestions = Questions.Count;
}
private static void GenerateQuestions()
{
var questionHomelessMan = new Question(QuestionIdHomelessMan,
"You see a homeless man begging on the street. What do you do?");
var answerHomelessManA = new Answer(AnswerIdHomelessManA, "I give him some money.", 2);
var answerHomelessManB = new Answer(AnswerIdHomelessManB, "I buy him a sandwich.", 3);
var answerHomelessManC = new Answer(AnswerIdHomelessManC, "I just walk past him.", 1);
var answerHomelessManD = new Answer(AnswerIdHomelessManD, "I take him into my home.", 4);
var questionAndAnswersHomelessMan = new QuestionAndAnswers(questionHomelessMan, answerHomelessManA,
answerHomelessManB, answerHomelessManC, answerHomelessManD);
Questions.Add(questionAndAnswersHomelessMan);
var questionLittleSibling = new Question(QuestionIdLittleSibling,
"Your little sibling wants to play with you but you're too busy right now. What do you do?");
var answerLittleSiblingA = new Answer(AnswerIdLittleSiblingA, "You play with him for while.", 4);
var answerLittleSiblingB = new Answer(AnswerIdLittleSiblingB, "You tell him to get the fuck out.", 1);
var answerLittleSiblingC = new Answer(AnswerIdLittleSiblingC,
"You tell him to go play with another family member.", 2);
var answerLittleSiblingD = new Answer(AnswerIdLittleSiblingD,
"You tell him that you will play with him later.", 3);
var questionAndAnswersLittleSibling = new QuestionAndAnswers(questionLittleSibling, answerLittleSiblingA,
answerLittleSiblingB, answerLittleSiblingC, answerLittleSiblingD);
Questions.Add(questionAndAnswersLittleSibling);
var questionFriendInJail = new Question(QuestionIdFriendInJail,
"Your friend has committed a crime and is now in jail. What do you do?");
var answerFriendInJailA = new Answer(AnswerIdFriendInJailA, "You give him a call if it's allowed.", 2);
var answerFriendInJailB = new Answer(AnswerIdFriendInJailB, "You want nothing to do with him anymore.", 1);
var answerFriendInJailC = new Answer(AnswerIdFriendInJailC,
"You may visit him in jail sometime next month.", 3);
var answerFriendInJailD = new Answer(AnswerIdFriendInJailD, "You visit him in jail as soon as possible.",
4);
var questionAndAnswersFriendInJail = new QuestionAndAnswers(questionFriendInJail, answerFriendInJailA,
answerFriendInJailB, answerFriendInJailC, answerFriendInJailD);
Questions.Add(questionAndAnswersFriendInJail);
var questionOldLady = new Question(QuestionIdOldLady,
"This lonely old lady is happily telling you all about her life while you're at the bus stop. What do you do?");
var answerOldLadyA = new Answer(AnswerIdOldLadyA, "You kindly tell her to shut the fuck up.", 1);
var answerOldLadyB = new Answer(AnswerIdOldLadyB,
"You make up a lie (eg you need to phone someone) to get rid of her.", 2);
var answerOldLadyC = new Answer(AnswerIdOldLadyC, "You actively listen to her.", 4);
var answerOldLadyD = new Answer(AnswerIdOldLadyD, "You try to listen to her but do not really engage.", 3);
var questionAndAnswersOldLady = new QuestionAndAnswers(questionOldLady, answerOldLadyA,
answerOldLadyB, answerOldLadyC, answerOldLadyD);
Questions.Add(questionAndAnswersOldLady);
}
public static void DisplayIntro()
{
Utilities.DisplayMessage("\n***** HOW GOOD ARE YOU? *****\n");
}
public static void DisplayCurrentQuestion(QuestionAndAnswers currentQuestion)
{
Utilities.DisplayMessage("");
Utilities.DisplayMessage(currentQuestion.Question.Title + "\n");
Utilities.DisplayMessage("A) " + currentQuestion.AnswerA.Title);
Utilities.DisplayMessage("B) " + currentQuestion.AnswerB.Title);
Utilities.DisplayMessage("C) " + currentQuestion.AnswerC.Title);
Utilities.DisplayMessage("D) " + currentQuestion.AnswerD.Title);
Utilities.DisplayMessage("\nChoose A, B, C or D. Or type 'exit' to quit the test.");
}
}