Problem solving and finding algorithms that work comes with experience.
As for how this code works:
unsigned short string_names[num_strings]
is an array of
unsigned shorts
, whose elements will be used as indices to elements of the
std::string note_names[num_notes]
array.
To be more specific, I could write:
std::cout << note_names[string_names[0]] << std::endl;
And it would print the fourth element of
note_names
, which is "E". In this way we can represent string names without having to rewrite the letters, but there's a more practical use for this as you will see.
As you correctly pointed out, line 25 is the meat of the algorithm.
To walk you through it, let's take an example - let's assume the following:
1 2 3 4 5
|
note = 0
//note is "C"
string = 3;
//string is "G"
|
So we have:
if((string_names[string] + response) % num_notes == note)
Which, in our example, can be rewritten as:
if((string_names[3] + response) % 12 == 0)
Which can further be reduced to:
if((7 + response) % 12 ==0)
Let's say the user's response was '2':
(In other words, the user is saying "C is two half-steps above G".)
if((7 + 2) % 12 == 0)
if((9) % 12 == 0)
9 modulo 12 is nine, it's not zero. Therefore, the user's response is incorrect.
If the user had entered '5' instead of '2':
(In other words "C is five half-steps above G")
if((7 + 5) % 12 == 0)
if((12) % 12 ==0)
The user would have been correct, because 12 modulo 12 is zero.
I'll probably edit this post once I can get myself to write a more mathematical explanation.