CLI Trivia

Amanda
4 min readJan 8, 2021

--

At Flatiron School, our first project was to code (in ruby) a CLI terminal application using external data. The API I chose to get data from was one that contained trivia questions from a variety of different categories. The way I envisioned my project functioning was for a user to open up the app, choose a category, answer the question, and get correct/incorrect feedback. I also wanted to a “score” element to make it more fun and competitive.

My approach was to parse data from the API using JSON, then iterate over the hash and create an object in my TriviaQuestion class containing the question, category, correct answer, and an array with 3 incorrect answers. This all seemed great at first, until I realized I had to figure out how to display the question and answers to the terminal in a random and different way than it appeared in the API.

Iterators, arrays, hashes and allllll the variables

def self.random_question(question)puts "#{question.question}"
answers = []
answers << question.correct_answer
answers << question.incorrect_answers
randomized = answers.flatten.shuffle
q_a = {q: question, a: randomized}
randomized.each.with_index do |answer, i|
puts "#{i + 1}. #{answer}"
end
q_aend

This method in my TriviaQuestion class allowed me to combine the correct and incorrect answers into one array, shuffle them, and print them to the terminal. This method takes the argument of question, which is an object containing the question itself, the category, the correct answer, and the incorrect answers.

First, I display the question itself by printing question.question

Then, by creating an empty “answers” array, I was able to shovel in both the correct and incorrect answers, randomize the order, and iterate over this new “randomized” array to print the question and answers to the terminal.

The tricky part here was being able to then “check” if the user’s input was the correct answer. This is where the q_a hash comes in. The :q is the entire question object, while :a is the answers in the order they were displayed to the user.

def self.check_answer(q_a, input)
true if q_a[:q].correct_answer == input
end

The method #check_answer is a part of my TriviaQuestion class and it takes an argument of question/answer as a hash, as well as the user’s input (the string corresponding to the numerical value they input)

def check_question
input = gets.strip.to_i - 1
answer = TriviaQuestion.check_answer(@q_a, @q_a[:a][input])
if answer && input.between?(0, 3)
puts "You got it!"

...

Moving over to my CLI, we ask the user for the number they think is correct and subtract by 1 (to match the :a array indices). If @q_a[:a][input] == q_a.correct_answer, #check_answer will evaluate as “true” and the user will see that their answer was correct.

I had instantiated the CLI with a @score variable set to zero. Each time the user got a question right, 1 would be added to the score. Similarly, each time the user got a question wrong, 1 would be subtracted, unless the score was zero (negative scores are depressing).

Pry is your best friend!!!

Pry was a pretty crucial part throughout the entire project, but the #check_question method is where it was absolutely essential. I used it to view variables and how the computer is interpreting what I’m inputting. For example, I needed to figure out the correct “input” argument to place in the #check_answer method. This needed to be the string of the correct answer in order for it to evaluate as true. Using pry, I was able to play with the @q_a hash. Seeing that @q_a[:a] returns the array of answers in the order the user is seeing it, I could align the users input with the array indices and use bracket notation to get the string value (@q_a[:a][input]).

Instance Variables

I learned a lot (more) about instance variables doing this project. My first approach was to avoid using them as much as possible, but this lead to a lot of loooong and messy methods in my CLI class. Using instance variables, I was able to break up my code. For example, I needed to save the users category selection in #get_category in order to display a corresponding question in #create_question.

@q = sorted_categories[input - 1]

Additionally, I needed to store all the questions in a particular category:

@qs = TriviaQuestion.questions_in_category(@q.category)

This allowed me to have an array of objects for the questions in the chosen category. Therefore, after a particular question is asked, I can remove that question object from the array so if the user wants another question from the same category, they are guaranteed to get a new question.

My misconception about instance variables was that in order to use them, they needed a reader method in the class. I learned that you can use instance variables without a reader method, and that the reader method is really just a functionality for the user to see things in the terminal.

Overall, I really enjoyed this project and coding something of my own, from scratch . A big thanks to my instructor and classmates for helping me along the way!

If you would like to learn more about my project, here is a link and a short demo video.

--

--