XNA Game-Themed CS1 Examples (XGC1) | |
Release 2.0 (XNA V3.1) |
References:
Goals:
1. Obtain the example code
When the game starts, you'll
see a screen that looks similar to this:
In this tutorial, the program that you can run closely resembles the program that you ran in the previous tutorial. What's different is the message at the top of the screen. The program displays the sum of all the hit counts as "total", the average (which is the total, divided by the number of rectangles), the smallest hit count as "min", and the largest as "max"
2. Background
The major topic for this tutorial is the pattern for processing arrays. Since we can only interact with arrays one element at a time, we will need a strategy that will allow us to accomplish tasks by only examining 1 element at a time. The tasks that we'll examine in this tutorial include summing up all the numbers in the array, or averaging the numbers, or finding the min/max number. Let's examine the overall pattern using the task of averaging the numbers in the array.
In order to calculate the average of the numbers in the array, we first need to first sum up all the elements in the array, and then divide that total by the number of elements in the array. The we will break up the basic pattern into three phases:
Pre-Loop Initialization
When we start our algorithm, we haven't summed up any elements yet, so the
running total should be initialized to zero (let's call this variable total).
Generally, just about anything we do to 'process' an array will require that we
(at least) initialize some variables.
The Loop
In this stage, we'll process the array, step by step. For our problem,
this is where we'll sum up all the numbers in the array. More detail on
this, below.
Post-Loop Processing
Once we've got the sum of the elements, the only thing left to do is to divide
that total by the number of elements, and then store the resulting average into
a variable.
The second phase ("The Loop") is involved enough that we will examine it separately, here. The key thing to understand is that since we can't deal with the entire array in a single statement, we'll have to approach the problem element-by-element. It may help to mentally break the array down into a couple of regions: the region of the array wherein we've already done the work, the current array element that we're looking at, and the remaining elements in the array, where we'll need to do work in the future. Here's a picture to help visualize that (using the first six elements of the array that keeps track of hits, in the above screenshot):
The green 'Already Done' region starts out being empty, since at the start of the loop, we haven't done any work. The blue 'Current Element' region is just element #0 - in most (but not all) cases, it's easiest to count up from zero. The tan 'Future Work' region consists of all of the elements we haven't looked at yet, which are elements 1 through 5.
How will we sum up all the elements in the array? Simply put, we need to add the element we're currently looking at (number 11, stored in element #0), to the sum of all the elements that we've already looked at. In other words, we need to add 11 to the total of the elements in the green region. Since the variable total stores the sum of the elements in the green region, we just need to add 11 to that total (which starts out at zero). Once we've done that, then we've processed element #0, and it becomes part of the green, 'Already Done' region of the array. In the next iteration through the loop, the blue, 'Current Element' region moves up by one, like so:
In this iteration through the loop, we add the number in the current element (zero) to the total (11), and get 11, which extends the green region to now include the current element.
At the start of the next iteration through the loop, we have:
In this iteration through the loop, we add the number in
the current element (11) to the total (11), and get 22, which extends the
green region to now include the current element.
At the start of the next iteration through the loop, we have:
As you can see, this process will repeat, until the 'Future Work' region is empty, and the entire array is covered by the green 'Already Done' region. Once that's done, phase 2 ("The Loop") is done, and our program will have the sum of all the elements in the array, stored into the variable total. After that, it will go on to phase 3, in which it will divide the sum by the number of elements, in order to get the average.
Please also keep in mind that the 'Three Phase' division, and the green/blue/tan way of thinking about this array processing pattern is something that's specific to this tutorial, and not something that will be commonly recognized anywhere in the computer industry.
3. Examining The Program:
Let's examine the
C# source code that produces the behavior we see on-screen
int total = TotalHits(); float avg = AverageHits(); int min = MinHits(); int max = MaxHits(); EchoToTopStatus("Block Hit Status[total=" + total + " avg=" + avg + " min=" + min + " max=" + max + "] " + "Soccer located at: " + m_SoccerBall.Center); |
///
<summary> /// Compute total number of hits (collisions) by adding up the contents /// of all m_BlockHits. /// </summary> /// <returns>Sum of all elements in m_BlockHits</returns> private int TotalHits() { int total = 0; for (int i = 0; i < m_BlockHits.Length; i++) total = total + m_BlockHits[i]; return total; } |
This is represented pictorially in the first picture, above.
total = total + m_BlockHits[i];
///
<summary> /// returns the average number of hits (collisions) from the m_BlockHits array /// </summary> /// <returns>average of all numbers in m_BlockHits</returns> private float AverageHits() { float total = TotalHits(); return total / m_BlockHits.Length; } |
///
<summary> /// Min hits (collisions) in the m_BlockHits array /// </summary> /// <returns>the smallest value in the m_BlockHits array</returns> private int MinHits() { int min = m_BlockHits[0]; for (int i = 1; i < m_BlockHits.Length; i++) if (m_BlockHits[i] < min) min = m_BlockHits[i]; return min; } |
min = m_BlockHits[i];
///
<summary> /// Max hits (collision) in the m_BlockHits array /// </summary> /// <returns>the largest value in the m_BlockHits array</returns> private int MaxHits() { int max = m_BlockHits[0]; for (int i = 1; i < m_BlockHits.Length; i++) if (m_BlockHits[i] > max) max = m_BlockHits[i]; return max; } |
FURTHER EXERCISES:
public void ComputeAllStats(ref float sum, ref float avg, ref float min, ref float max)
{
}
Index | 0 | 1 | 2 | 3 | 4 |
Value | 0 | 10 | 20 | 30 | 40 |
Then the minimum element is: 0
And the second to smallest number is: 10
Index | 0 | 1 | 2 | 3 | 4 |
Value | 90 | 12 | 20 | 30 | 9 |
Then the minimum element is: 9
And the second to smallest number is: 12
Index | 0 | 1 | 2 | 3 | 4 |
Value | 90 | 12 | 9 | 30 | 9 |
Then the minimum element is: 9
And the second to smallest number is: 9
Index | 0 | 1 | 2 | 3 | 4 |
Value | 0 | 10 | 20 | 30 | 40 |
then after calling the array-reversing function, the array should have
the values:
Index | 0 | 1 | 2 | 3 | 4 |
Value | 40 | 30 | 20 | 10 | 0 |
Keep in mind that this exercise is extra challenging, and may not be a good exercise to start with if you're looking at this topic for the first time.
Kelvin Sung Computing and Software Systems University of Washington, Bothell ksung@u.washington.edu |
Michael Panitz Business And Information Technology Cascadia Community College mpanitz@cascadia.eduu |
This work is supported in part by a grant from Microsoft Research under the Computer Gaming Curriculum in Computer Science RFP, Award Number 15871 and 16531. | |
2/8/2010 |