XNA Game-Themed CS1 Examples (XGC1) Release 2.0 (XNA V3.1) 2/8/2010
Topic: Topic.5.RepetitionStructures
Example: Ex_20.NestedForWhileLoops

# Repetition: Nesting Different Loops, If Statements

References:

• Pre-requisite: it is assumed that you have read through the prior tutorials, and are familiar with the concepts covered in those tutorials.

Goals:

• In this tutorial, we will:
• Examine a nested loop, which consists of one while loop nested inside of a for loop.
• Examine a loop that has other logic (in this case, conditional ("if") statements embedded inside it)

1. Obtain the example code

Download and unzip the zip file and you will see an ExampleProgram folder. Open the ExampleProgram folder, the EXE folder contains the compiled program and you can double click on the .sln file to work with the source code.

When the game starts, you'll see a screen that looks similar to this:

By using the left thumbstick, you can adjust both the horizontal space between the circles, and the vertical space between the circles.  You'll notice that this program is extremely similar to the previous tutorial's program, except that the rows alternate which image they use (soccer ball or basket ball), and that the bottom-most row and left-most column are no longer directly on the bottom/left edges of the screen.

2. Examining The Program:

Let's examine the C# source code that produces the behavior we see on-screen

• CreateABallAt():
• This method creates a new circle object, so that the new circle's center is at (xPos, yPos).  We've also added a parameter for the texture, so that we can create soccer balls and basket balls.
• UpdateWorld(): int yRow = 0;    // a while loop inside a for loop     for (float yPos = 5.0f; yPos < World.WorldMax.Y; yPos += m_YSpace)     {         string TextureToUse = null;         // Check to see if this is an odd or even row         if (yRow % 2 == 0)         {             // Even row             TextureToUse = "BasketBall";         }         else         {             TextureToUse = "SoccerBall";         }         yRow++;         float xPos = 5.0f;         while (xPos < World.WorldMax.X)         {             CreateABallAt(xPos, yPos, TextureToUse);             xPos = xPos + m_XSpace;         }     }
• The relevant, new code is shown above.  You'll also notice that we keep a separate yRow variable, which serves as a simple counter - it gets incremented each time we move upwards to a new row.  This way, we can easily use the modulus operator to figure out whether we're on an even row, or an odd row, and assign the texture to the circle accordingly:
int yRow = 0;
• You will notice that unlike the previous tutorial, the outer loop sets the value of yPos, instead of xPos.  As a result, the outer loop now controls which row we're on.  Since the inner loop continuously changes xPos, it therefore iterates across the columns in the row.
for (float yPos = 5.0f; yPos < World.WorldMax.Y; yPos += m_YSpace)
• Note also that we initially assign yPos the value 5.0f, which is why the bottom-most row isn't directly on the bottom of the screen.
• For each row, we need to figure out which texture to use.  We'll figure this out once per row, using an if statement that's nested inside the loop.  The first step is to declare a string variable to hold the texture's name:
string TextureToUse = null;
• If you comment out the if/else statement, TextureToUse will continue to be null.  The XNACS1Lib library will interpret this to mean that no texture is requested, and it will instead draw the circles in the default color.
• Next, we use the modulus operator to figure out if we're on an even row, or an odd row:
if (yRow % 2 == 0)

{

// Even row

}

else

{

TextureToUse = "SoccerBall";

}

• We use that information to assign the appropriate string to the TextureToUse variable.  Finally, we increment our row counter.

yRow++;

• On the one hand, it might be better to wait to do this until after the inner loop has finished (i.e., until after we've actually done the work for this row), because if we then decide to add more code, perhaps to the inner loop, that makes use of yRow, yRow will have the wrong value (it will be one too high).  On the other hand, if we wait to increment yPos until after the inner loop, we increase the chance that we'll forget to do it.
• We elected to put this statement here because yPos isn't used in the inner loop, and keeping yPos++ with the other code that uses yPos is therefore probably a good idea.
• Once we've done all that, then we're at the point of executing the inner loop:
float xPos = 5.0f;

while (xPos < World.WorldMax.X)

{

CreateABallAt(xPos, yPos, TextureToUse);

xPos = xPos + m_XSpace;

}

• This is a fairly typical while loop: xPos is assigned a value before the loop (in this case 5, so that the first column isn't directly on the left edge of the screen):
float xPos = 5.0f;
• The loop then continues until xPos passed beyond the right edge of the screen:
while (xPos < World.WorldMax.X)
• The body of the inner loop then creates a ball at the new location, with the appropriate texture
CreateABallAt(xPos, yPos, TextureToUse);

and then increases xPos by m_XSpace:
xPos = xPos + m_XSpace;

FURTHER EXERCISES::

1. Start from a blank starter project (1000.201, if you need it), and re-do the code from memory as much as possible.  On your first try, do what you can, and keep the above code open so that when you get stuck, you can quickly look up what you forgot (and that after you finish a line, so that you can compare your line to the 'correct' line).  On the next try, do the same thing, but try to use the finished code less.  Repeat this until you can type everything, without refering the tutorial's code.
• Repeat this exercise daily for several days, so that you really get the hang of this.  As you go on, periodically review this by re-doing this exercise.
2. Practicing With Nested Conditional Statements
For this exercise, you should use the same project that was explained in the above tutorial.
See if you can modify the provided code so that the first column is all basketballs, then the second column is soccer balls, then the columns continue to alternate.