REAL-WORLD COMPUTER PROGRAMMING FOR KIDS
STEP 20: RETROFITTING & RE-PURPOSING (REFACTORING) OUR CODE, CONTINUED (MORE)
Now, rub your hands together in glee and anticipation of what we will accomplish today. Or at least to get the blood flowing a bit. Get your coding fingers all ready. We left off in Step 19 implying, at least, that we would discuss why it is that I feel that the code to calculate the percentage is interesting.
To remind you of that code, it calculates the percentage like so:
percentageCorrect = (Convert.ToDouble(correctAnswers) / Convert.ToDouble(questionsAnswered)) * 100;
Do you notice something odd about this? The count of correct answers (stored in the correctAnswers int variable) is divided by the count of questions so far answered (stored in the questonsAnswered int variable). That makes sense, right?
The first thing that might be confusing, which makes it interesting, is that it is then multipled by 100. Why? Because 1 is the largest the result of that division will be. For example, 10 divided by 10 is 1. And that’s as good as it gets. But we don’t want to show 1% correct, because that’s not correct. Thus, we multiply it by 100 to get the value we would expect to see in that case.
The second head-scratcher is the Convert.ToDouble() jazz. Why is that done? Because otherwise the value is rounded either up to 1 or down to 0 (before being multiplied). Because dealing with integers, that’s all that are available. Anything under half is rounded down to 0, and anything exactly at half (or more) is rounded up to 1.
So when a person gets four questions right out of seven (which equates to around 57%), using integers says the value is 100%. If three out of seven are answered correctly, using integers would say 0%. Crazy, right? That’s why real numbers are used by converting the ints into doubles. The “real numbers” (such as double) are more precise in that way.
The Text property of lblPercentage is then assigned the percentage value, with a percent sign (“%”) appended:
lblPercentage.Text = percentageCorrect.ToString() + "%";
So that the UpdatePercentageCorrect()code above actually does something besides plopping down in the midst of the code file and looking impressive, add a call to it in the “Next” button’s click Event Handler:
private void button1_Click(object sender, EventArgs e) // "Next" button
{
if (questionsAnswered < numberOfQuestions)
{
questionsAnswered++;
}
UpdatePercentageCorrect();
// rest of the code elided
The code is the same for all of the questions until we reach the last one. It has to be handled a little bit differently. When the last Question and set of candidate answers is populated onto the form, set the bool variable freezeAnswer to true in the LoadNextBatch() method:
private void LoadNextBatch()
{
MultipleChoiceClassIndex++;
freezeAnswer = MultipleChoiceClassIndex + 1 == numberOfQuestions;
. . .
That’s what’s happening here (above). It doesn’t say literally or directly, freezeAnswer = true, but that’s what the code above amounts to when the last question is reached. The effect is the same as, or resolves to, “freezeAnswer = true” then. And prior to that, freezeAnswer is always being set to false on that line.
Now, so that the value of freezeAnswer has some effect on what happens, add this to the radioButton1_CheckedChanged() event handler:
if (freezeAnswer)
{
questionsAnswered = numberOfQuestions;
UpdateProgressBarAndAssociatedLabels();
btnNext.Enabled = false;
return;
}
btnNext.Enabled = ... // could simply be btn.Enabled = true;
. . .
What’s happening here is that the result of the “if” statement makes all the difference, like “The Road Not Taken”

In this case, freezeAnswer equating to true, causing the four lines within the “if block” to run, is not a road not taken, but it is a road only relatively seldom taken (once per question-answering session).
Another “housekeeping chore”: Add two lines of code to the Form1_Load() event handler so that it looks like this:
private void Form1_Load(object sender, EventArgs e)
{
originalQuestionNofN = lblQuestionNOfN.Text;
originalPercentageStr = lblPercentage.Text;
}
And yet another thing. Let me show you the code for the cmbxSelectMultiChoiceFile_DropDown() Event Handler. This occurs when the user selects the dropdown arrow on the right side of the ComboBox. It populates the Combo Box if it has not yet been populated. This is called “just-in-time” coding. We don’t populate the Combo Box until it needs to be populated. Then once it’s done, it’s done, and any future drop-down event would just basically be ignored (by checking to see if any items already exist in the Comb Box). Here is how it looks:
private void cmbxSelectMultiChoiceFile_DropDown(object sender, EventArgs e)
{
if (cmbxSelectMultiChoiceFile.Items.Count > 0) return;
string pathToSearch = @"C:\Programming4Kids\";
string[] fileNames;
fileNames = GetFileNames(pathToSearch);
if (cmbxSelectMultiChoiceFile.Items.Count == 0)
{
foreach (string file in fileNames)
{
cmbxSelectMultiChoiceFile.Items.Add(file);
}
}
}
So let’s go through what’s happening here, line by line.
if (cmbxSelectMultiChoiceFile.Items.Count > 0) return;
If there are already items in the ComboBox, we just “exit” (C# calls it “return”) from the method, so that none of the code that follows (in that method) is run.
Although there is no “else” block literally added, like so:
if (cmbxSelectMultiChoiceFile.Items.Count > 0) return;
else
{
string pathToSearch = @"C:\Programming4Kids\";
. . .
}
...the effect is the same as if there was. The reason for this is the call to “return” in the “if” block. If that runs, then the second line of code does not run (just as if it were in an “else” block); if the equation in the “if” block is not true (that is to say, the number of questions answered plus 1 is not the same as the total number of questions), then “return” is not called, and the code continues to run on the next line.
So, whether you put the “else” block in doesn’t really matter; the same thing happens either way. Which way should you write it, then? If you’re interested in having your code be as concise as possible, leave out the explicit “else” code. On the other hand, if an “else” block helps you to understand the code better, by all means put it in. It won’t hurt anything.
Note: Whether you add the “else” block or not won’t cause your code to run any faster or slower – not even a teensy-weensy little bit. Why? The compiler will “optimize” the code before it’s run, anyway, and turn your code into something it understands and is more efficient for its purposes, but looks like gobbledyflunk to all but the nerdishest and geekiest of programmers.
For example, the entire code in that event handler will be turned into something that looks kind of like this: 1100011 botellas de Cervaza 60011 an der sQuIrCh Wand... In other words, you can pretty much leave the optimizing of your code to the compiler. But we’ll talk more about what we can do (good and bad practices, coding-wise) in a future Step.
Next line of code:
string pathToSearch = @"C:\Programming4Kids\";
This sets up where we will look for the CSV files. You can change it if you want to store your CSV files in a different folder.
string[] fileNames;
This declares a string array in which to store the names of the CSV files.
fileNames = GetFileNames(pathToSearch);
Any and all files found in the directory assigned to the pathToSearch variable are assigned to the fileNames string array. The GetFileNames() method retrieves the names of files in the path stored in the pathToSearch variable, and stores these file names in the fileNames string array.
Notice that it only selects files with a .CSV extension:
private string[] GetFileNames(string pathToSearch)
{
string[] _fileNames;
_fileNames = Directory.GetFiles(pathToSearch, "*.csv");
return _fileNames;
}
In the GetFileNames() method above, a local string array (_fileNames) is declared. The native method GetFiles() is called to retrieve files from pathToSearch which have the extension .CSV.
Note: “Native” (in this sense, anyway) means that the method “comes with C#” -- we didn’t have to write it ourselves. It’s part of the C# language, or at least part of the code that supports C# that Microsoft provides.
Going back to the cmbxSelectMultiChoiceFile_DropDown() Event Handler method, each of the file names retrieved is added to the Combo Box in the foreach part of the code:
foreach (string file in fileNames)
{
cmbxSelectMultiChoiceFile.Items.Add(file);
}
If you’re beginning to feel a little lost with all this code being thrown at you, don’t worry, in the next Step, I will post all the code for the project (just in case you missed some of it along the way). Unless you would like to do that right now. Would you?

All right, then, I will let you “off the hook” for now, and we’ll leave that until next time. Besides, we have accomplished enough for this Step.
After providing all the code next time, we will thereafter continue by “stepping through” that code to see exactly what sequence it follows, and what logic is taking place as we go along. In fact, there is a bit of a bug we need to fix, and the way for us to discover why something is going awry will be deduced by stepping through it and examining the State of things and the value of variables at various points along the way.
Until then!
Earth-shakingly Important Notice: If you have a basic programming question (suitable to an audience of “Kids”), send it to idiolectable@gmail.com, specifying whether you would like your name and location used if it is printed in a future “Step” of this newsletter. If you are a subscriber to the newsletter, you can also leave a question at the bottom of this Step, in the “Comments” section.
If you do not want to give your real name, a nickname is acceptable (the first “Letter to the Editor” of mine that was printed appeared in Rolling Stone magazine back in the early 1970s, and I signed it “Sylvester” for some reason which I no longer remember).
Finally, it’s always interesting to see where people are from, so please provide your City or Town and the State it’s in, too (or Province, or whatever the region where you live is called).
To listen to this Step, the audio of it can be found here: