Tuesday, March 27, 2012

CIS 217: Array Assignment [Tic-Tac-Toe] Part 2

I decided to post the code for the project now that I've finished it...but forgot to upload the project to my DropBox account...so I'll type this up from memory until I can post the code tonight after my other classes.

// Creates a 3x3 array.
int boardArray[3, 3]

Which makes an array that looks like this, each dimension of the array corresponding to an "x" or "y" value (like a grid):
[1, 1] [1, 2] [1, 3]
[2, 1] [2, 2] [2, 3]
[3, 1] [3, 2] [3, 3]

And I randomly generated the 0 or 1 result (for X or O) and inserted it into the array at the current spot:
for (int x = 0; x < 9; x++)
{
for (int y = 0; y < 9; y++)
{
boardArray[x,y] = rand.Next();
}
}
So the loop will run like this:
x=1/y=1, x=1/y=2, x=1/y=2
x=2/y=1, x=2/y=2, x=2/y=3
x=3/y=1, x=3/y=2, x=3/y=1

perfectly corresponding to the array.

I goofed on the loop that displayed the results, though, so the board was either all X's or all O's, based on the value stored in boardArray[3, 3]. Oops!

Monday, March 26, 2012

CIS 217: Array Assignment [Name Search]

The name search assignment was cake.
  1. Create a StreamReader object.
  2. Read BoyNames.txt file into memory.
  3. Check to see if it matches the name being searched for by the user.
  4. Display the results.
  5. Do the same for GirlNames.txt.
_Load event of the main form, calls methods to load boy and girl names from text files.
private void frmMain_Load(object sender, EventArgs e)
        {
            LoadBoyNames();
            LoadGirlNames();
        }

LoadBoyNames() loads the names for boys from the file.  Loading the names for girls was the same, obviously...just change the name of the method and file, etc.
public void LoadBoyNames()
        {
            try
            {
                // Index used in loops.
                int index = 0;

                // Declare StreamReader.
                StreamReader inputFile;

                // Open file and get SR obj.
                inputFile = File.OpenText("BoyNames.txt");

                // Read contents of BoyNames.txt
                while (index < boyNames.Length && !inputFile.EndOfStream)
                {
                    boyNames[index] = inputFile.ReadLine();
                    index++;
                }

                // Close the file.
                inputFile.Close();
            }
            catch
            {
            }
        }

SearchNames() method...passes reference to array, determines if current array item is the same as what the user entered (passed by value).
private int SearchNames(string[] sArray, string value)
        {
            bool found = false;
            int index = 0;
            int position = -1;

            // Search the array.
            while (!found && index < sArray.Length)
            {
                if (sArray[index] == value)
                {
                    found = true;
                    position = index;
                }

                index++;
            }

            return position;
        }

And finally, the Search button. 
private void btnSearch_Click(object sender, EventArgs e)
        {
            lbResults.Items.Clear();

            if (SearchNames(boyNames, txtBoyName.Text) != -1)
            {
                // MessageBox.Show("Found boy name!");
                lbResults.Items.Add("Boy found:\t" + txtBoyName.Text);
            }
            if (SearchNames(girlNames, txtGirlName.Text) != -1)
            {
                // MessageBox.Show("Found girl name!");
                lbResults.Items.Add("Girl found:\t" + txtGirlName.Text);
            }
        }

Piece of cake ;-)

CIS 217: Array Assignment [Tic-Tac-Toe]

This assignment did not go as planned, to say the least.

The flow of the program was easy enough to figure out - I've done it in the past in other languages for other classes.
  1. Create a form with 9 Labels on it, a button to generate a new game, and an exit button.
  2. Create an 2D array to hold either 0s or 1s (0 = Os, 1 = Xs).  
  3. Loop through the array, then
    1. Generate a 0 or 1.
    2. Loop through the Label controls.
    3. Set the Text property of the current label to either "X" or "O", based on the generated number.
  4. Detect a winner:
    1. Search through the array for possible victories for Xs and Os:
      1. Top Row: Array locations [1,1], [1,2], and [1,3] are the same = Win.
      2. Middle Row: Array locations [2,1], [2,2], and [2,3] are the same = Win.
      3. Bottom Row: Array locations [3,1], [3,2], and [3,3] are the same = Win.
      4. Left Col: Array locations [1,1], [2,1], and [3,1] are the same = Win.
      5. Middle Col: Array locations [1,2], [2,2], and [3,2] are the same = Win.
      6. Right Col: Array locations [1,3], [2,3], and [3,3] are the same = Win.
      7. Left-Right Diag: Array locations [1,1], [2,2], and [3,3] are the same = Win.
      8. Right-Left Diag: Array locations [1,3], [2,2], and [3,1] are the same = Win.
  5. Let player click "New Game" button to generate the outcome again.

 Alas, I ran into a few snags:
  • Random numbers weren't generating, regardless of what I did.  Rebooting my PC and re-running the program fixed this.  Odd...
  • In an outcome set of 9 numbers, with 4 zeroes and 5 ones, the labels seemed to all display whatever the first number in the array was.
    • Yet, if I displayed each result (referencing the array), it showed the correct values.
    • I tested this in a ListBox as well...and sure enough, the random numbers were there.
I think my problem was that I used a control loop to display the outcomes, and might have been setting the Text property of each label to the current value of the current position in the array...so on one pass, all labels = 0.  The next, they = 1, then 0 again on the next pass, and so on...but never a mix of 1s and 0s. 

As an afterthought...I'm almost absolutely certain that this was the problem, as nothing else makes sense.

Monday, March 5, 2012

Tips: C#, Visual Studio 2010 - Get All Control Names, View TabIndex Order.

Here's a neat trick that I have used every-so-often ever since picking up Visual Basic 6 back in the 90's.  Sure, it can be done in other ways, but this way suites me well.  I can keep the notepad file off sitting to the file to refer to it if needed.

Create a Button control on your form, double-click it, and past this code into it:



using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\myControlNames.txt"))
            {
                foreach (Control myControls in this.Controls)
                {
                    //MessageBox.Show(myControls.Name + " = " + myControls.GetType());
                    file.WriteLine(myControls.Name + " = " + myControls.GetType());
                }
            }   

Run your program (F5) and then click the button.
You can then go to C:\myControlNames.txt file in the C drive, which will display this:

btnGetControlNames = System.Windows.Forms.Button
lblProcessed = System.Windows.Forms.Label
txtNumEvents = System.Windows.Forms.TextBox
lblTimeProcessed = System.Windows.Forms.Label
btnReadEvents = System.Windows.Forms.Button
btnExit = System.Windows.Forms.Button
btnCopy = System.Windows.Forms.Button
label5 = System.Windows.Forms.Label
label3 = System.Windows.Forms.Label
label2 = System.Windows.Forms.Label
label1 = System.Windows.Forms.Label
lblIndex = System.Windows.Forms.Label
lbMessage = System.Windows.Forms.ListBox
lbSource = System.Windows.Forms.ListBox
lbTimeGenerated = System.Windows.Forms.ListBox
lbEntryType = System.Windows.Forms.ListBox
lbIndex = System.Windows.Forms.ListBox
So when running that, it will give you a list of all controls in your form! Cool, eh?



Another tip is this:
If you want to see the TabIndex values for all controls on the form, you can go into Design view (so you are looking at your form), and go to the "View" menu and click on "TabOrder".  It will show all the TabIndex values for each control on your form (if it has them; things like PictureBoxes do not).  Use the "Escape" button to exit out of this mode (or use the "View" menu again).  Using the mouse to left-click on different objects can manipulate the TabIndexes.

Have fun!

Sunday, March 4, 2012

CIS 217: Midterm Exam

I hope everyone did well on the midterm exam!  It had some questions that made you think (mostly going through vague decision or loop statements).  Nothing too hard, but I had to increase the magnification on the page (CTRL + MouseWheelUp) to read some of it, because the font was so small.

Did anyone else have questions that were marked wrong, but were in fact correct?  This happened earlier at the start of the semester, and the quizzes were updated.  I went through the book after the exam and looked up most of the answers (those that weren't vague like "programming languages use operators to manipulate data"), and list page numbers.  I let Ms. Mah know, so I'm hoping she has time to fix it (they are the correct answers, after all).

Just curious.  I seem to have the worst luck when using WebStudy, so I'm glad that they're moving away from it in the future!  Hopefully it's easier for instructors to create/edit the exams, because right now it's such a pain (if you saw it, you'd wonder if all online teachers have to take a class on scripting!).

Cheers,

Ken

CIS 217: Midterm Programming Project

The midterm programming project for class was actually easier than some of the other projects that we've had to do, so I decided to play with it a bit.  I went off to images.google.com and found some publically available photographs of some paper, a rock, and a pair of scissors, and used those in the project.

Of course, my 6 year old decided to ask me why we refer to a (singular) scissor as a "pair" of scissors...to which case I had to run to Google and try to find out why we say this ;-)  Gotta love kids, right?

I'm not sure if we're allowed to post code from the midterm or not (everything on the net is cached somewhere (Wayback Machine, etc)), so it wouldn't be hard for a smart student in a future class to pull the code up on Google (not that there aren't crap-tons of P-R-S code out there already, I guess).

I'm not a fan of the "Big Bang Theory" television show...some YouTube clips are funny, but for the most part I just can't sit through sitcoms.  But the "Rock-Paper-Scissors-Lizard-Spock" shout-out to the guy who created it was funny, and I've seen T-Shirts online at places like ThinkGeek.com for it.  While I was waiting for the grill to heat up for some yummy Brats and Burgers, I decided to change our midtem project to this version, which was funny.

Here's a YouTube link to the BBT clip that I originally saw this on:
http://www.youtube.com/watch?v=iapcKVn7DdY

Hope everyone did well!

Thursday, March 1, 2012

C#: EventViewer Program (Part 1) - Reading Windows Event Logs

Yesterday at work, I had an idea - create an event log viewer to retrieve Windows event logs. Below is how I did it. Enjoy()!

Controls used:
  • EventLog component called "myEvents"
  • ListBox control called ListBox1
  • Button control called btnReadEvents
  • TextBox control called txtNumEvents

Variables used:
  • Integer "i", as a loop counter.
  • Integer nEvents, as loop control (which = txtNumEvents as Int).

Here is the project in Run mode for the first time.

It works by entering a number into the TextBox (txtNumEvents), then clicking the "Read Events" ("btnReadEvents"). The program then takes the number from the TextBox ("txtNumEvents") and converts it to an integer (stored in the nEvents variable).

Afterwards, it starts a counted For-Each loop, iterating through all events in the Event Logs in Windows. The loop exits when the number of events read equals the value of nEvents (from the TextBox).

Here is the code for the "Read Events" button's _Click() event:

        private void btnReadEvents_Click(object sender, EventArgs e)
        {
            int i = 0;
            int nEvents = Convert.ToInt32(txtNumEvents.Text);

            EventLog myEvents = new EventLog("Application", "HUACSPMCRAPPDEV");
            Stopwatch logTimer = new Stopwatch();
            logTimer.Start();
            lblTimeProcessed.Text = "";

            foreach (System.Diagnostics.EventLogEntry entry in myEvents.Entries)
            {
                if (i < nEvents)
                {
                    // Add event fields to the listbox, separated by tabspace (\t).
                    ListBox1.Items.Add(entry.EventID 
                                        + "\t" + entry.EntryType
                                        + "\t" + entry.TimeGenerated 
                                        + "\t" + entry.Source 
                                        + "\t" + entry.Message);

                    // Increment control for loop, or it will pull the whole log.
                    i++;
                }
                else
                {
                    // Break out of loop when i = nEvents.
                    break;
                }
            }
            logTimer.Stop();
            lblTimeProcessed.Text = "Processing took " + logTimer.Elapsed.TotalSeconds.ToString() + " seconds.";
        }
And here is what it looks like after reading from the Event Logs:

It looks "uneven" because not all fields have information in them. I'll fix that next time.