I wrote the runsevens game runner program to automate the running of the Tournament of Sevens programming challenge
, and it was an interesting little project. It’s designed to do the following:
- Maintain a ladder of players.
- Run games of Sevens for a number of players by executing standalone exes.
- Update the ladder with games’ results.
That’s a fairly high-level view. Running each game of Sevens also requires shuffling a deck of cards, dealing them to the players and tracking card play. I chose C#
to implement it as it comes with a built in GUI but Python
and most other programming languages would have worked. You could probably even do it in C
, though you'd need a third party data structures library or to roll your own.
Data Structures and Classes
I decided with a bottom up approach, starting with the classes. Most fundamentally the program needs to handle a deck of cards. There are multiple ways to represent deck of cards. One option, for instance, is an array of bytes that each hold a unique value in the range 0-51. I decided it would be more straight-forward to hold the value (ace, two, king) and suit (hearts, clubs, etc.) as explicit properties in a Card class and hold the deck as a list<Card>. To do that, I used two public variables -- cardValue and cardSuit. I also provided two Card class constructors, either of which could be called to build a card.
Note that I've adopted the convention that for the two char Card it's always value then suit, so 2H and never H2. I also overrode the toString() method so it would return 2H, KH, etc. Next, I wrote cardDeck, which creates an unshuffled deck of cards with the following elegantly written piece of code.
From there, shuffling is just a matter of picking a series of pairs of random indices between zero and 51 and swapping them.
When I've programmatically run contests in the past, it's usually been with a collection of .exes, so I initially set this with the expectation of that being the case. However, some of the Java entries produced multiple class files. To avoid the chance of two class files having the same name, I put each entry into its own numbered folder. c:\sevens\bots\1\bot1.exe c:\sevens\bots\2\seven.class
Managing the Ladder
As the contest runs over several weeks, I decided to use a ladder structure to keep track of the results. The first week, since everyone's scores were the same, the ladder's based on the order the bots were entered. In the second and subsequent weeks the bots are sorted by their ratios. Then, the games are run based on the ladder, so the six highest scorers play in the first game, the next six in the next game and so on. I sorted the ladder each week with the following code:
The cards played are held in four columns -- one per suit -- ordered by increasing value. This makes it easy to determine which cards are playable and pre-determine if a player can play or not. If a player has no playable cards then their bot is not called.
I wrote a method, called GetMove() to run a single entry. It gets called for each bot that has a playable card.
It's a little bit more complex running Java, and that delayed the contest considerably. I'll return to that in a future article where I’ll publish the full source code. It's about 800 lines.