Rand function

Hi folks. I started teaching myself C++ this month, and I have just completed my first program. It's a simple music theory quiz. It's supposed to randomly generate a key and scale, and then the user guesses how many sharps/flats are in the given scale.

Everything works the way it's supposed to, except that when the user selects "Play again," the program generates the same key and scale as the first time. The only way to get a new, randomly selected key/scale is to quit and restart the program.

I'm sure I must be making a very simple mistake, but, like I said, I'm very new to C++, and I've got a lot to learn about the rand function (along with every other function!).

 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 #include #include #include #include using namespace std; int main () { srand(static_cast(time(0))); short int key=1; short int mode=1; short int guess, assess, correctA, correctB; char keyLtr; char again='y'; string modeName; while (again=='y') { // Generate random key while (key==1 || key==3 || key==6 || key==8 || key==10) { key=rand()%12; } // Generate random mode while (mode==1 || mode==3 || mode==6 || mode==8 || mode==10) { mode=rand()%12; } // Generate key name switch (key) { case 0: keyLtr='C'; break; case 2: keyLtr='D'; break; case 4: keyLtr='E'; break; case 5: keyLtr='F'; break; case 7: keyLtr='G'; break; case 9: keyLtr='A'; break; case 11: keyLtr='B'; break; default: cout << "\nUh oh, key=" << key << endl; } // Generate mode name switch (mode) { case 0: modeName="Ionian"; break; case 2: modeName="Dorian"; break; case 4: modeName="Phrygian"; break; case 5: modeName="Lydian"; break; case 7: modeName="Mixolydian"; break; case 9: modeName="Aeolian"; break; case 11: modeName="Locrian"; break; default: cout << "\nUh oh, modeName=" << modeName << endl; } cout << "\nHow many sharps/flats are in " << keyLtr << " " << modeName << "?\n(Use negative numbers for flats)\n"; cin >> guess; // Generate correct answer assess=key + (12-mode); if (assess>11) { assess-=12; } switch (assess) { case 0: correctA=0; correctB=0; break; case 1: correctA=7; correctB=-5; break; case 2: correctA=2; correctB=2; break; case 3: correctA=-3; correctB=-3; break; case 4: correctA=4; correctB=4; break; case 5: correctA=-1; correctB=-1; break; case 6: correctA=6; correctB=-6; break; case 7: correctA=1; correctB=1; break; case 8: correctA=-4; correctB=-4; break; case 9: correctA=3; correctB=3; break; case 10: correctA=-2; correctB=-2; break; case 11: correctA=5; correctB=-7; break; default: cout << "\nUh oh, assess=" << assess << endl; } // Compare user response to correct answer if (guess==correctA || guess==correctB) { cout << "\nYou are correct, sir!\n"; } else { cout << "\nNope, the correct answer is " << correctA; if (correctB != correctA) { cout << " or " << correctB; } cout << ".\n"; } cout << "\nShall we give it another go? (y/n)\n"; cin >> again; } cout << "\nOkay, later tater.\n"; return 0; }
in while (again=='y')
 12 key=1; mode=1;

at the beginning (before while (key==1 || key==3 || key==6 || key==8 || key==10)).
meanwhile ... Your first time has found a valid number according to the while loop condition. It is still valid on next iteration, so there is no need to call rand again.

Consider this:
 1234 std::string keys( "CDEFGAB" ); int key = rand() % 7; cout << keys[ key ]; std::vector modes = { "Ionian", ...

Ah, of course. I knew it would be something simple. Thanks for your help, tath and keskiverto!

Incidentally, the reason I don't just use a random number between 1 and 7 is because I need a number that represents the note's position on the piano, so that the "assess" expression will work properly. Anyway, thanks again.
 I need a number that represents the note's position on the piano

But, what if you could compute the position?
 123 const int position[] = { 0, 2, 4, 5, 7, 9, 11 }; ... int keyvalue = position[key];

The array 'position' is a simple "(math) function" that maps values from [0..6] into [0..11]. Your switch statements perform similar mappings.
Ahh.. I see. Good to know, thanks! Looks like I've got a lot to learn!
in this case you could also use structures to hold the data:
 12345678910111213141516171819202122232425262728293031323334353637383940414243444546 #include #include #include #include using namespace std; struct note_t { char letter; int position; string modeName; }; int main () { srand(static_cast(time(0))); short int key; short int mode; short int assess; note_t notes[7] = { {'C',0,"Ionian"}, {'D',2,"Dorian"}, {'E',4,"Phrygian"}, {'F',5,"Lydian"}, {'G',7,"Mixolydian"}, {'A',9,"Aeolian"}, {'B',11,"Locrian"}}; key=rand()%7; cout << "Letter: " << notes[key].letter << endl; cout << "Position: " << notes[key].position << endl; cout << "-------------------------" << endl; mode=rand()%7; cout << "Mode name: " << notes[mode].modeName << endl; cout << "Position: " << notes[mode].position << endl << endl; system ("pause"); return 0; }