Project in Review, Part 3: 2D or not 2D?

[cross-posted from my blog here!]

This is a continuation of a multi-part blog series focusing on the development of Archimedean Assault. Go read part 1 and part 2. It’s good!

Once the scope of our game was reasonably well defined, we set forth like good little game jammers and started hammering out code, 2D art assets and music.

Not far into this process, we realized the multiplicative nature our scope had on our art assets. A robot. Alright, he has to walk around and shoot. But, also, he has to transform! A transforming robot. Okay, that doubles the number of art assets for our robot’s actions. We need assets for both versions of the robot. And, we also need a transition animation going from one form to another. Okay, fine. A free-roaming game world in which the player can move 8 directions.

So, we need at least number of actions * number of forms * number of directions (x * 32 for those keeping score at home!) frames for any given action, and that’s before we get into animation. That means, if we want the robot to fire a gun and have muzzle flash, we need to get the muzzle flash from each direction in each form. When we start talking about animation and number of frames per animation, hand-drawn art assets quickly balloon out of control.

That’s before we start talking about the environment assets in which the game will actually take place.

Being the newbs that we are, we don’t have a dedicated pixel artist. We’ve got nguyenn1, who is by my estimation, about 10% of a dedicated artist. It takes us a few weekends to discover that we wrote a check for art assets that our group couldn’t cash. At least, not within a reasonable timeframe, and not within a reasonable quality.

We mitigated our dependency on pixel art by borrowing heavily from anywhere we could. danc’s sprite sheets on Lost Garden quickly became an invaluable asset that we leaned on.

Of course, this restricts us to assets that fit into the kind of game we’re trying to build, and art decisions became something to the effect of “Well, what’ve we got that kind of works?” That strategy doesn’t work when you have very specific demands, like “floating citadel” or “a robot that transforms from 8 different angles.”

After realizing that there was no way we’d effectively deliver on our artistic demands, I started looking at alternatives. 3D models are readily accessible at comparably low costs from sites like TurboSquid. After several months, the art assets for the player weren’t yet complete, and environmental art assets were still quirky and buggy. But, we could buy a 3D model that matched up pretty well with our vision for $5.

If $5 can save months of artist time, it certainly seems like money well spent. However, working with 3D assets requires time elsewhere. It requires non-trivial developer time and ramp-up time on tools and techniques across the team. Once I have a $5 model for the player, then what? The landscape of 3D modeling software isn’t terribly friendly (importers for fixed content, exporters to proprietary formats that either didn’t support our content pipeline or munged content beyond recognition, rigging models and animating them in-game…), and animation seems to be a mess across the board.

So, $5 doesn’t seem to save us time, but does distribute the load across the team a bit more evenly. But, how can we be sure that we aren’t wasting our time chasing something because we think it’s fun?


Setting up a Magento Commerce site with custom template using GoDaddy hosting

My sister runs a business and she recently asked me to setup a web store using a custom template that her client had picked out from The template that was chosen was designed to work with the Magento Commerce framework, a fact that I didn’t realize until after getting the template and reading the instructions. It turns out that the information was available right on the selection screen:

Choosing template

Guess next time I need to read the sites I read more carefully 🙂

The client was hosted on and when I started reading the forums, it looked like there were lots of problems, but after figuring a few things out, the installation went very smoothly for me. There is already a guide detailing how to install Magento, and it was pretty helpful to me, but it’s not very explicit. This guide should be a lot more granular with a few pictures to help out.


Before we start detailing the installation, let’s list out the things you should download prior to reading further if you plan to follow along:

  • Latest Version of Magento Commercever as of the time of the writing of this post
  • Hosting on – PHP + MySQL
  • Custom Template for Magento Commerce

The official Magento Installation Guide is here and here is the cheat sheet version. If you read them carefully (I didn’t, seems to be a recurring issue of mine 🙂 ), you’ll notice that PHP 5.2 is a requirement for the framework. There is a workaround if your hosting is locked to 4, but fortunately GoDaddy is not. They have a guide on how to change your PHP version here. It’s fairly simple, and even though they warn you about a delay up to 24 hours, you should be ready no more than 30 minutes after initiating the change. If you’re not familiar with GoDaddy’s layout, I’ve included a few pictures to go along with their guide. First you’ll want to select the hosting account that you’ve setup:

GoDaddy selecting product

That will expand and show you the domain you’ve setup. I’m not going to show it because I don’t want to expose my client’s details, but just click on the button that will open up hosting dashboard. After that is done loading you should see this screen:

Godaddy hosting dashboard

Underneath the primary 3 buttons are a set of tabs for your domain. Select “Content” and then select “Add-on language” to go to the PHP version selection screen:

GoDaddy Select language

That will open up the PHP version selection screen. Select 5.X and you’re ready to go. Note the 24-hour delay I mentioned earlier. When I did it, it was ready in about 10 minutes, but budget the time in case there really is a 24-hour delay.

GoDaddy selecting PHP version

Magento Installation

Once this is done, you’re now ready to start the Magento Installation. There are 2 ways to get the files onto your server.

  1. Use the File Manager built-in to GoDaddy’s hosting dashboard
  2. FTP the files onto the server.

I would recommend using a combination of 2) first to upload the files and then 1) to unpack the files from the archive. Whatever you do though, unless it’s absolutely necessary, DO NOT unpack the files locally and then upload them. It will take FOREVER. When I did it, it took well over an hour, probably almost 2 to upload the files. I ended up using a separate FTP program just because it’s a little faster than the browser based File Manager, but either option should work. Once you have uploaded the file, locate it using the File Manager, and don’t forget that it will only show so many files per page.

GoDaddy File Manager pages

I didn’t and consequently ended up copying the unpacked files because I was too dumb to locate the archive. I ended up reinstalling the entire store a 2nd time the right way, and that’s why I know it’s much faster! Once you find the Magento file, select the check box and you’ll notice the “Unarchive” button will light up. Use this to unpack the files into the directory that you want to put the framework into.

GoDaddy Unarchive button

Special Note: I would select the framework directory name very carefully. It’s possible to change it later, but it’s a giant pain in the ass and I never got it working correctly. Just pick something innocuous like \shopping so you don’t have to rename it later.

Once the files are extracted, make sure the directory is executable otherwise the PHP install file will not be able to run. You’ll want it executable for all types of users and you can set this using your FTP program.

Magento directory permissions

Setting up your Database

Once the permissions are set, navigating to the install location in your browser will initiate the installation page for Magento. Continue until you reach the dialog screen prompting you for the database information. Magento will script out the database once it has the proper connection data, so you don’t have to worry about running a script on your own. You will need to create the database and setup the admin account so Magento can do the work for you. If you haven’t created the database already, return to the GoDaddy Hosting dashboard and select the MySQL option from the database tab:

GoDaddy Creating database

If you haven’t created databases before, this will be empty. Either way, you’ll need a fresh database for Magento so you’ll want to select the “Create database” button:

GoDaddy Creating database button

This will start the DB creation wizard – it’s pretty straightforward except for one minor detail. Whatever you name your database will also be your admin account name. It’s a little curious, but this is fair warning to create a database name that isn’t totally crazy because that will be your username account credential. There is an option to create a read only account, but it’s not necessary for Magento and I skipped this step. After creating the database, you’ll need to get the connection string since the database and the website are not co-located and will need to connect across the Internet. You can return to the MySQL page in the Hosting Dashboard and select the little pencil:

GoDaddy database details

It will load a page (this page always looks a little screwed up in Firefox, I dunno why) with your connection details. Take this info and put it into the Magento installer. Once this is done, Magento will finish installing.

Installing Your Custom Template

If you don’t have a custom theme you can skip this section. When the installation is finished, the Magento installer will give you a page with links to your frontpage (the store essentially) and a backend page (the admin page). Click on both and sign into the admin page using the admin credentials you set up. At this point you’ll want to unpack the template if you haven’t already. Again, like with the initial Magento installation, you can use either the GoDaddy File Manager or your FTP program to upload the template.

Inside of the template folder there should be 2 folders: /app and /skin. Magento theme folders

Copy these into these folders into the folder where you installed Magento. So if we used the example I used earlier in the post, you would copy /app and /skin directly into /shopping. You shouldn’t have to worry about overwriting any files as the theme will have all of it’s files in a folder named after it. Once the files are uploaded, head to the admin page and select “Design” from the “System” tab.

Magento setting up theme

This will bring you to the design management page. It shows all of the themes you have installed into your Magento store, but right now it will be blank. Select “Add Design Change” in the upper right hand corner to add the custom theme you have uploaded.

Magento adding theme

The next screen will let you select the theme. Pick it out from the drop down and hit save. You do NOT have to enter in any dates to start or end the theme.

Magento selecting theme

At this point, you can just reload the front page and the theme should be loaded. These themes are pretty barebones, so don’t expect a drastic change from the default – they are meant to provide a good basis for a designer to alter, so it actually might have less functionality than the base theme which I think is designed to be somewhat usable out of the box as a web store.

Final Notes

At this point your installation should be complete and you should be ready to begin actually using the site. Just a few notes about things that messed me up a little bit.

Why don’t my categories show up?

When you start making categories, make sure they are sub categories underneath the default root category. If you don’t do this, you’ll need to select the root category that you’ve created to be the default category for the store. There is a really good post at Noam Design about this issue. You can verify you’re default root category by going to the admin page, and then selecting “Manage Stores”.

Magento check root category

Once you’re in the manage stores section, select the “Main Website Store” and follow the directions from Noam Design.

How come my products don’t show up?

Once you’ve got the categories working, you might also encounter an issue with getting your products to show up. Adding products is pretty self explanatory and the site will guide you through most of the required fields. However, for some reason, it skips over one set of required fields that will prevent your products from showing up. In the “Manage Products” page, there will be a bunch of tabs with different fields that you can fill out with product data. Make SURE you select the inventory tab.

Magento Product inventory

Fill out the quantity and change the stock available from out of stock otherwise the product will never show up. I ran into this problem and this post here on the Magento Commerce forums told me why the products weren’t showing up.

Thoughts on Magento Commerce

Hopefully this helped out some of you with setting up Magento. Several years ago I had setup a customized OS Commerce e-store and this was much easier. There were still a few hairy spots and changing the root directory was much more painful than I had though it should be due to the store caching the user credentials, but overall I think if you were a small business looking to setup a web store, you could do a lot worse than Magento. The site itself is free, and the templates for it are relatively cheap and plentiful so it is not unreasonable to customize the site without having to do lots of custom coding (which makes the site brittle and susceptible to breaking changes I might add as well as being expensive). There are a few components that were not touched such as the credit card/pay pal support, but I have a feeling it will be relatively painless given the mostly cohesive UI. I think that unless you were really moving towards a large scale solution, the overall cost for the enterprise Magento (somewhere north of $3000) would make the free site a much better bet.

Deleting a Category from Windows Live Writer

A quick post here since I ran into this issue while writing my post introducing Costco reviews. I had mispelled “Costco” as “Costo” in the categories field. Naturally this was after adding it, so I thought, hey, no problem, I’ll just edit it.

Removing Bad Category

Problem is, you can’t. See my issue circled in red. Here’s a post on the MSDN forums about it:

Now, that’s a bit of a long thread with some misunderstanding going on, so let me take a quote from the MVP Kirk M.

I think the perceived problem here is that since Writer can add  a category and the blogging platform in question will accept this addition (via it’s API?), by the same token, Writer should be able to use the same path to delete a category as well. I realize that it’s not the same thing in practice but why the function(s) are perceived this way.

Kirk has a pretty good answer but let me summarize what you need to do:

  1. Add-in the correct category.
  2. Select the correct category for your post. See the highlights in the picture below.
    1. Removing Bad Category unselect
  3. Continue writing the blog post as usual
  4. Upload the blog post
  5. Close Windows Live Writer
  6. Restart Windows Live Writer
  7. Check the categories drop down. It should be updated. Check out the screen shot below.
    1. Removing Bad Category successful removal

The issue here is that they didn’t want the tool to override any of the behaviour of the hosted websites that Live Writer supports. I get that – but it’s a crappy user experience not to able to edit a tag they haven’t uploaded yet. This is especially crappy given that you can refresh the list, but it won’t update at all since they probably didn’t want to have refresh remove any non-uploaded categories. An easy way to do this would be to give an option to configure this behaviour, but hey, I know what seems easy on the outside sometimes isn’t for a variety of reasons. I’m just posting the workaround.

Editing Quicktime .MOV movies and burning them to DVD on Windows 7 without(!) Adobe Premiere

I wanted to get back into salsa dancing and was thinking about taking classes again. Century Ballroom offers tons of classes, but I had some experience before and wasn’t sure what level to take. Fortunately for me, I had taken some classes before at Century and they give you a DVD with a review of the lessons on it when you’re done. I wanted to be able to view these on the TV, but unfortunately, all the movies are in QuickTime (.MOV) format. This means if I want to watch them, I have do it on the computer unless I burn the files to a DVD that is viewable on any ole’ DVD player. If I was on a Mac, this would be trivial, but I happen to be on Windows 7 Ultimate. Now, let’s get some things out of the way:

1) Nothing native to windows 7 will play quicktime movies. Nothing. Nadda. Zip.

2) You can download some hacky programs but 1/2 of them looked like scamware to me so I didn’t try any of them. On top of that, the few that looked 1/2 way legit had problems with the sound syncing up and stuff. Caveat emptor, I didn’t try any of these and I wouldn’t even try to begin to delve into it.

3) Quicktime player can play your films…but you need to Pro version to save it in a different format. It’s no great shakes, but it looked sufficient for my needs and costs $29.99 + tax.

I chose 3) from the list above. The primary reason is that I didn’t want to spend loads of time figuring out how to convert the movies – I wanted to spend loads of time learning salsa!

Ok, so you can just buy the software from Apple electronically and they just give you a key. Once you have the key you just put it into Quicktime and all the grayed out options light up. Ah….so satisfying. See, take a look!

Registered quicktime

So I had 3 different .MOV files that I needed to combine. Lesson 1, 2a, and 2b. At this point it’s dead simple: open up the first movie and then move the top carrot slider to the end. Then just open up an Explorer window the contains your files.Salsa files

The file I wanted to be first was Century Salsa 1 so I opened that up in Quicktime first. Drag the slider over to the end of the film so that it looks like this:

First file in Quicktime

Notice the slider at the end and also note the time. The file should be at the end before you start inserting other film data, otherwise it will insert the new footage at the point you have selected in the film. Ok, now select the next file you want and drag it into the first window.

Adding second file in Quicktime

Notice how the selection carrot stays at the end, but the time changes to include the new file. Keep doing this until your done. Once you’ve got all the files in, save the results to a new quicktime film.

At this point you’ve got 2 options: you can try to add chapters or you can just burn the film to DVD. I’m going to go through adding chapters to your file, but let this be a warning to those interested: Windows Live Movie Maker doesn’t honor the chapters. I don’t know why, but since I went through the work, I thought I’d share how to make chapters anyway. Ok, on to the chapters!

You’re first resource is located right in Apple help and it will take you to this page. It’s mostly correct, but there are a few things that don’t work anymore or are a bit unclear for beginners for the version of Quicktime that I’ve written this for (7.6.8). And if you’re reading this, you’re probably a beginner like me, right. Smile

1) The arrows keys DO scroll through the movie, but you have to hold them down for a bit. I thought this wasn’t working at first because I thought it was 1 second per push, but it’s 1 frame and you’ll need to hold it down to advance quickly.

2) Don’t sweat the frame stuff in the chapter list. I just defaulted everything to 0.

3) Whenever they talk about importing, they really mean just opening the file. I have no idea why they talk about importing everything.

4) Unless you want the chapter title to show up during the entire move, in the movie properties, uncheck the text track. The chapters will still be there, but they will not up in the movie.

Ok! Almost done with the DVD. Here’s the real news: Windows DVD maker can’t open up MPEG-4 content. Say what? You heard me, it won’t open up MPEG-4 which is the only MPEG format Quicktime will let you export as. So go online and download Windows Live Essentials. You’ll want to install Windows Live Movie Maker; Live writer is keen as well (if you’re into writing blog posts it’s great. I’ve been using it for a while and it’s great.). Windows Live Movie Maker will open the MPEG-4 file. You don’t need to do anything other than select “Burn a DVD”. The program will make you save the file to a WMV first, but then you’re set! Windows Live Movie Maker will automatically add a menu for you and after you burn the DVD, all you need to do it pop the DVD in to check if it works correctly.

Designing and implementing a Simpletron using C#

The last problem in Chapter 8 of Deitel’s Visual C# 2005: How to Program 2/e is to design and implement a simple machine-language processor called a Simpletron. I won’t go into the basics of the machine in great detail, since the book does so at great length. It is a really interesting problem, but there isn’t a great deal of information regarding C# implementations on the web, so hopefully this post will serve to fill part of that void. There are 2 parts to the problem:

1) Implement the Simpletron class in an extensible manner – This teaches you how to use Arrays in yet another way. Essentially in this problem, the Arrays are used both as RAM ( memory ) and as registers to hold changing values.

2) Enhance the Simpletron by adding the capability to perform additional operations – This portion of the problem forces the student to understand the nuances of low-level CPU operation.

I’ll only be posting code for part 1. Since this problem is often used in academic settings, I won’t be posting the other code, but what I’ll do instead is post errata I’ve found in the advanced problem, and my own interpretations of the enhancement requests. I found the wording in the book to be quite vague regarding how far to go with the modifications, so I hope this proves helpful. I searched fruitlessly for many hours with finding anything, so maybe someone else will be spared my pain. 🙂

Code outline for the Simpletron:

namespace Exercise8._32 {
    class Simpletron {
        // Input/output operations
        private const int READ = 10;
        private const int WRITE = 11;

        // Load/store operations
        private const int LOAD = 20;
        private const int STORE = 21;

        // Arithmetic operations
        private const int ADD = 30;
        private const int SUBTRACT = 31;
        private const int DIVIDE = 32;
        private const int MULTIPLY = 33;

        // Transfer of control operations
        private const int BRANCH = 40;
        private const int BRANCHNEG = 41;
        private const int BRANCHZERO = 42;
        private const int HALT = 43;

        private const int SIZE_OF_MEMORY = 100;
        private const int MIN_MEMORY_RANGE = -9999;
        private const int MAX_MEMORY_RANGE = +9999;
        private const int STOP_PROGRAM = -99999;

        private int accumulator;
        private int instructionCounter;
        private int operationCode;
        private int operand;
        private int instructionRegister;

        private int[] memory;

        public Simpletron() {
            memory = new int[SIZE_OF_MEMORY];
            accumulator = 0;
            instructionCounter = 0;
            operationCode = 0;
            operand = 0;
            instructionRegister = 0;

        public void Run() {

        private void DisplayWelcomeMessage() {


        private void DisplayMemoryDump() {


        private void UserDialogue() {


        private int ValidateUserInput(int currentUserInput) {


        private void ExecuteProgram() {


        private int EvaluateOperationCode(int currentOperationCode,
                                          int currentOperand) {


        private int AccumulatorOverflowValidation(int currentOperationResult) {


You can see that I have a Run method that is the primary execution method inside the class. There are also various validation methods that are called inside of some of the major methods. This code could have been placed inside of the main methods, but since it is called by many times, I thought it was wise to separate this code out. I would like to say that the particulars of the implementation aren’t super important – in this part of the problem, the main issue is the design. Another important thing to remember is to consistently use Test Driven Development. After each piece of code was created, I would run a few programs stressing those functions to ensure that the program was working correctly. It’s important that you test at least 3-4 variations of data to make sure that you are not designing only for a subset of your data.

I could have automated the testing by creating an overload of the run method that bypassed the userinput method, but for the scale of this project, performing the testing manually wasn’t time intensive. I would like to stress that had we wanted to continue modifying the program, we would have wanted to create automation at that point.

Okay, part 2 – the advanced section. I’d like to point out an errata on page 407: “In Exercises 25.10 and 25.11, we propose building a compiler that converts programs written in a high-level programming language (a variation of Basic) to Simpletron Machine Language. Some of the following modifications and enhancements may be required to execute the programs produced by the compiler: “ Well, I looked these problems up hoping for some clarification, but they don’t exist. 🙂

I believe requests a), b), c), and e) to be pretty self-explanatory. Below is some additional information that I believe will help with the remaining modifications.

d) Modify the simulator to use hexadecimal values rather than integer values to represent SML instructions – This modification is kind of weird, because if you followed the book, you almost certainly used an integer Array as your memory structure. It’s also kind of redundant to ask us to store things as Hex, since the computer is doing that anyway, but to shoehorn hex into your existing memory array would be a nightmare. And to what end? So I ended up interpreting this request to mean that on output, you should display all memory registers as Hex. I also added a section to the beginning asking the user which format: Decimal or Hex they would prefer. I know for troubleshooting I wanted Decimal since that is how I wrote the programs!

f) Modify the simulator to process floating-point values in addition to integer values – This one is a doozy. There are 2 possible ways to interpret this – Add a double memory array, accumulator, and a whole new set of instructions. The other is to continue to use integer memory and registers and instead encode the floating point data to fit within an integer field. I used the latter interpretation, since the former is kind of cheesy. One point in favor of the latter is that it will teach you an important lesson about CPU’s. Hint: Up until Intel’s 386 DX processors, all CPUs only had a single accumulator register. I really enjoyed this modification.

g) and h) Modify the simulator to handle string input – The only thing I need to mention is pay attention to this sentence in the clue the book gives you: Each two-digit integer represents the ASCII decimal equivalent of a character. That is the most important sentence in the clue. If you look up an ASCII table, you’ll see that they all have decimal representations, but that there are some with more than 2 digit representations. For instance, “h” or lower case h, is 104, so it’s impossible to fit into a 2 decimal bit memory location. If you did part f as I did, this problem might be easier for you, since similar thinking ( i.e. encoding/shifting ) is required.

Hope this helps! I had loads of fun solving this problem, and I hope that these hints help you focus on the important parts of the problem.

Things I learned about comparing two poker hands in C#

I’ve been going through Visual C# 2005: How to Program, 2/e and I recently got stuck on problem 30 in chapter 8. Chapter 8 deals with arrays and problem 30 is an innocent thing asking you to compare 2 hands of poker. Well, I spend a good month fucking around with this problem thinking to myself, there is NO WAY it should be this convoluted and hard. After finishing it yesterday, it turns out it is. The Coding the Wheel site has an entire page devoted to poker hand evaluations and my code looks remarkably like the naive implementation. My implementation is more difficult because beyond the initial hand evaluation, it tries to compare the hands and account for ties all the way down to a perfect tie, which in poker results in a pot split. I always thought suits would be used to break ties, but that isn’t an official rule according to Wikipedia. I found a few things significantly hampered me in my particular implementation.

  1. I should have developed using TDD. I developed the test code below AFTER I had written a significant portion of code, which killed me since I had to scrap a lot of that poorly tested code and rewrite my algorithms. I’ve posted a portion of the test code below. The only thing of note here is that I created an Enumeration called Hands which contained all of all the poker hands which I passed into this method.

    BuildHand method of DeckOfCardsTest class

     private void BuildHand(Card[] pokerHand, Hands typeOfHand) {
                int counter;
                string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" };
                string[] faces = { "Ace", "Deuce", "Three", "Four", "Five", "Six",
     "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
                // designate default suit 
    for cards as Hearts and default face as deuce
                string testSuit = suits[0];
                string testFace = faces[1];
                Card card;
                switch (Convert.ToInt32(typeOfHand)) {
                    // Create high card hand
                    case 0:
                        testSuit = suits[0];
                        for (counter = 0; counter < pokerHand.Length; ++counter) {
                            switch (counter) {
                                case 0:
                                    testFace = faces[2];
                                    testSuit = suits[3];
                                case 1:
                                    testFace = faces[9];
                                    testSuit = suits[1];
                                case 2:
                                    testFace = faces[12];
                                    testSuit = suits[2];
                                case 3:
                                    testFace = faces[4];
                                    testSuit = suits[3];
                                case 4:
                                    testFace = faces[random.Next(4,9)];
                                    testSuit = suits[1];
                            card = new Card(testFace, testSuit);
                            pokerHand[counter] = card;
                    // Create pair hand
                    case 1:
                        int pair = random.Next(0, 7);
                        for (counter = 0; counter < pokerHand.Length; ++counter) {
                            switch (counter) {
                                case 0:
                                    testFace = faces[pair];
                                    testSuit = suits[0];
                                case 1:
                                    testFace = faces[pair];
                                    testSuit = suits[1];
                                case 2:
                                    testFace = faces[7];
                                    testSuit = suits[2];
                                case 3:
                                    testFace = faces[9];
                                    testSuit = suits[3];
                                case 4:
                                    testFace = faces[10];
                                    testSuit = suits[1];
                            card = new Card(testFace, testSuit);
                            pokerHand[counter] = card;
  2. I REALLY should have implemented a HandOfPoker class instead of using a Card array directly. This would have cleaned up my code quite a bit because each HandOfPoker object could have contained the frequency arrays I was using to store my face and suit counts. I also could have stored the hand results directly as properties instead of having to immediately compare after evaluation. See some of my ugly code below. Notice the massive redundancy as I compare the two hands. Sorry about some of the code getting cut off, but I can’t make it appear without ruining the formatting which will make it impossible to read. It’s not really for analysis, but to demonstrate what I could have improved.
    CompareTwoHands method from DeckOfCards class
    public void CompareTwoHands(Card[] firstHand, Card[] secondHand) {
                Hands firstHandResult;
                Hands secondHandResult;
                int counter;
                int cardCounter;
                int highestCardCount;
                int firstHandHighCard = faceValues.Length;
                int secondHandHighCard = faceValues.Length;
                // for each hand we will create 
    a frequency array for the faces (13) and suits (4)
                int[] faceCountsFirstHand;
                int[] suitCountsFirstHand;
                int[] faceCountsSecondHand;
                int[] suitCountsSecondHand;
                faceCountsFirstHand = CountFaceCards(firstHand);
                suitCountsFirstHand = CountSuitCards(firstHand);
                faceCountsSecondHand = CountFaceCards(secondHand);
                suitCountsSecondHand = CountSuitCards(secondHand);
                firstHandResult = 
    		AssessHand(faceCountsFirstHand, suitCountsFirstHand);
                secondHandResult = 
    		AssessHand(faceCountsSecondHand, suitCountsSecondHand);
                if (firstHandResult > secondHandResult) {
                    Console.WriteLine("The first hand won with "
     + DisplayHand(firstHandResult,faceCountsFirstHand,suitCountsFirstHand) + 
    " beating " +
                else if (firstHandResult < secondHandResult) {
                    Console.WriteLine("The second hand won with " + 
    DisplayHand(secondHandResult,faceCountsSecondHand,suitCountsSecondHand) + " beating " +
                else if (firstHandResult == secondHandResult) {
                    switch (Convert.ToInt32(firstHandResult)) {
                        case 1:
                            highestCardCount = 2;
                            for (cardCounter = highestCardCount; cardCounter > 0; --cardCounter) {
                                for (counter = faceCountsFirstHand.Length - 1; counter > 0; --counter) {
                                    if (faceCountsFirstHand[0] == highestCardCount || faceCountsSecondHand[0] == highestCardCount) {
                                        if (faceCountsFirstHand[counter] != faceCountsSecondHand[counter]) {
                                            firstHandHighCard = faceCountsFirstHand[counter];
                                            secondHandHighCard = faceCountsSecondHand[counter];
                                            cardCounter = 0;
                                    else if (faceCountsFirstHand[counter] == highestCardCount || faceCountsSecondHand[counter] == highestCardCount) {
                                        if (faceCountsFirstHand[counter] != faceCountsSecondHand[counter]) {
                                            firstHandHighCard = faceCountsFirstHand[counter];
                                            secondHandHighCard = faceCountsSecondHand[counter];
                                            cardCounter = 0;
                                if (counter == 1 && firstHandHighCard == secondHandHighCard) {
                                    highestCardCount = highestCardCount - 1;


But you  know what? After doing all this, I’m pretty content with finishing it. I’m really fired up about what I learned, and after looking over some of the better solutions on Coding the Wheel, I realize that my solution is hampered by my tools, in this case my tool being the data structure Array which I’m being asked to use exclusively ( and I don’t really know anything else either. 🙂 ).

Hope this helps someone else trying to learn about this problem!