For Loop - In C use zero based loops

In C based languages as array indices start at zero it’s generally good practice to use zero in most loops.
for(int Idx = 0; Idx < SIZE_OF_ARRAY; Idx++) {…}

Here it could be argued that as we are referring the count of guesses then starting at GuessCount=1 makes more sense than GuessCount=0.
for(int GuessCount = 1; GuessCount <= MAX_GUESSES; GuessCount++) {…}

But for beginners seeing for loops starting at one may be misleading

The loop here is interesting. I agree that counting iterations should be zero-based whenever it makes sense, but I think counting down is also important. I foresaw the greater need for “number of tries remaining” over “current try”, so I wrote my loop like this:

void PlayGame() {
	constexpr int MAX_TRIES = 5;
	for (int tries = MAX_TRIES; tries > 0; tries--) {
		cout << "Try " << (MAX_TRIES - tries + 1) << ": ";
		if (tries > 1) {
			cout << "You have " << tries << " guesses remaining...\n";
		} else {
			cout << "This is your last guess! make it count!\n";
		}
		GetGuess();
	}
}

Here’s what it looks like for me:

Welcome to Bulls and Cows!
Can you guess the 5 letter isogram I'm thinking of?

Try 1: You have 5 guesses remaining...
Guess the word: one
Wrong!

Try 2: You have 4 guesses remaining...
Guess the word: two
Wrong!

Try 3: You have 3 guesses remaining...
Guess the word: three
Wrong!

Try 4: You have 2 guesses remaining...
Guess the word: four
Wrong!

Try 5: This is your last guess! make it count!
Guess the word: five
Wrong!

Do you want to play again (Y/N)?: n

Game Over :(

Press any key to continue . . .

I’m a PHP developer, so the for and if syntax is very familiar to me. I like to count down in for loops for a number of reasons. One reason is that I only have to use the variable value in the initialiser (currently a constant, but it will be variable later). More relevant is that the last iteration of the loop is always 1 (tries > 0). Personally, I find it looks more logical to always have > 0 or >= 0 as the condition. It’s much easier to plan for zero than to plan for a number which could change once the program is running.

In this particular case I have easy access to the number of guesses remaining which I think is more relevant than which try we are on. As an added bonus in later sections of the course, I’m pretty sure that checking a variable against a constant (like 0) is a tiny bit faster than checking a variable against a “getter”.

For example, this:

for (int tries = Game.GetMaxTries(); tries > 0; tries--) 

… runs Game.GetMaxTries() once, which is probably faster than…

for (int current = 1; current <= Game.GetMaxTries(); current++)

… which runs the function for each iteration of the loop on top of your initialiser.

If you break it down, it works like this:

for ( A ; B ; C )
  • A is done before the loop starts (this is the initialiser)
  • B is done before each iteration of the loop to check if we should read the next line
  • C is done after each iteration of the loop to prepare for the next check

In my game so far A happens once, B happens 5 times and C happens 4 times.

This could unintentionally have a performance impact later on in the course when we have one or more loops running each frame at 60fps.

2 Likes

Like your thinking on counting down.

Although I’d probably go with a global constant in a header file available to all my classes rather than a method.

That said the GetMaxTries() method does have the potential to provide special rules and bonuses.

When it comes to optimising for something happening 60 times a second I’ll go with Donald Knuth "Premature optimisation is the root of all evil "

On a personal note I’m mostly doing B&C as revision to pickup on some of the differences in C++ 11 and the way people are coding these days. It’s been 15 years since my last serious C++ project.

Privacy & Terms