Thursday, August 14, 2014

C++ Yahtzee Game

Second post in 1 day!

Wow, so many things to post, so little time! This time I'm going to be briefly explaining my final project for a summer class I took called Data Structures.

I've always been a fan of Yahtzee, since a kid my parents have engrained the full scorecard into my mind. Whether I'm in a pub or at a friends house, I still have the ability to write down a Yahtzee scorecard on nearly anything. So, when it came to doing a self created final project for a C++ Data Structures, I naturally jumped at the chance to emulate my favorite game. The purpose of the project was to create a program on your own design and do a complexity analysis. A complexity analysis is  simply a data representation of how a program performs if you increase the input size dramatically. For instance, in my Yahtzee program, I varied the number of players from 1 to 100, then counted the number of overall operations and operations of each statistically significant function. An operation counted as anything that accessed or changed a current data structure.

The backbone for this program are 4 main data structures. The first two structures are the most basic. They are structs called Dice and yahtStats. The Dice struct contains two arrays which are used to save and roll the dice.


struct Dice{
  array<int,5> dice;
  array<int,5> savedDice;
};


YahtStats contains most of the statistics involved with the program, including the number of operations. RollsPerNumber, which is an array of the yahtStats struct, is particularly interesting because it shows the distribution of each value of dice rolled over the course of the entire game.


struct yahtStats{
  int operations = 0;
  int autoPlay = 0;
  
  int mainOp = 0;
  int rollDiceOp = 0;
  int printDiceOp = 0;
  int printRollwithSavedOp = 0;
  int autoSaveDiceOp = 0;
  int saveDiceOp = 0;
  int getQtysOfDiceOp = 0;
  int autoConfirmScoreOp = 0;
  int confirmScoreOp = 0;
  int autoScoreTurnOp = 0;
  int scoreTurnOp = 0;
  int autoPlayTurnOp = 0;
  int playTurnOp = 0;
  
  int numPlayers = 0;
  int playerTurn = 0;
  int turnRolls = 0;
  bool keepRolling = true;
  int totalRolls = 0;
  int turns = 0;
  array<int,6> rollsPerNumber;
};


The next data structures are two classes called Scorecard and Score. Scorecard uses the object Score as a data type to fill a 2D array of width 18 and height of the number of players in the game.

Score has two attributes, score and hasBeenScored. ”score” contains the actual integer value of the Score, while hasBeenScored is a boolean field which is set to true if the score is set for the first time. The reason for this is to allow to check if scores equal to 0 have already been scored as 0, and are not just empty categories.

class scorecard{
private:
  int numPlay;
  Score ** playerScores;
  array<string,100> playerNames;
  
public:
  scorecard(int numPlayers);
  ~scorecard();
  
  void setNumPlay(int num);
  void setPlayerScore(int player,int section, int score);
  void setPlayerName(int player, string name);
  int getNumPlay();
  Score getPlayerScore(int player, int section);
  string getPlayerName(int player);
  void printDivider(int numPlayers);
  void print(int numPlayers);
  
};

class Score{
private:
  int score;
  bool hasBeenScored;

public:
  Score();
  ~Score();
  
  void setScore(int s);
  void setHasBeenScored(bool hBS);
  int getScore();
  bool getHasBeenScored();
  string getHasBeenScoredStr();
};
Below is a dependency chart for the main method. Simply put, the main method gathers the mode of which the user would like to play, either standard or auto-play, and the number of players. Based on these inputs, it iterates through either playTurn or autoPlayTurn enough times to fill the scorecard with scores.
The pseudocode for playTurn and autoPlayTurn are shown below.

void playTurn(yahtStats * stats, Dice * myDice, scorecard * myScorecard){
  1. Roll the dice between 1 and 3 times.
  2. Save the dice between 1 and 3 times.
  3. Score the turn.
}
void autoPlayTurn(yahtStats * stats, Dice * myDice, scorecard * myScorecard){
  1. Find a random number of rolls between 1 and 3.
  2. Iterates through for the number of rolls indicated by the randomly generated number.
  3. AutoSave the dice.
  4. autoScore the turn.
}

A critical portion of this project was to do a complexity analysis. I chose to do my analysis based on the number of players. Because my independent variable was linear, and each player had a set number of turns to complete, I hypothesized that the program's complexity would increase linearly. To test this, I made the auto-play mode. Since the outcome score-wise was irrelevant, I chose to randomize the player input at any opportunity. In this way, I simulated the average game with players. While convenient, it did not replace the high scores of an actual AI player. To keep track of the operations, I placed incrementing counters at places inside of each local function inside main.cpp.
 These counters can be found in the yahtStats struct.

Originally, I had the autoPlayTurn function print off the scorecard each time. For reference, the scorecard looked like something below.


By printing the scorecard each time a turn was finished, I printed off the scorecard numPlayers^2 times. This resulted in the following exponential complexity plot based on operations.
After removing the offending quadratic printing, the complexity plot became very linear, which proved my original hypothesis.

In the end, this project taught me the value of complexity analysis and data structures. It was good project to work on because it had a medium high code complexity and great "Fun Factor". For those of you who would like to try out the program, it is available here: Yahtzee.

-John "My computer is at 1% so I have to FINISH THIS QUI"

Friday, August 8, 2014

The Idea Forge in Review

Hello Readers,

Over the course of the summer I have learned much about how to manage groups of people to achieve a larger end goal. While there were a few hiccups along the way (the necessity of locking castors for tables, etc.), work on the Idea Forge has gone better than imagined. We have nearly completed construction of 20 whiteboards of two unique designs, three work tables, and seven design tables.

With each of these projects, the goal was to make something functional and visually stimulating. To show just how easy this is to accomplish, I have created a venn diagram illustration.


Sufficed to say, it was a challenge to make this happen. I was part of the second round of employees to come through the project, and as such, I had some catching up to do with the projects. After a short while though, we were organized as a group and were working as a well oiled machine.

Upon arrival, there were a few things mostly completed, including the whiteboards, and some things that needed lots of work, like the design and work tables.

The first issue we ran across with the design tables was squaring the frames. Made out of galvanized piping, the frames could be described as "artisnally crafted", each table is unique. It took almost a week of shifting and cranking with pipe wrenches to make the seven frames level and square enough to add on the steel angle bars that would serve as a rim for the specially designed wood table toppers. Even though we made the steel frames as square as possible, it was still necessary to muscle the bars to slot connecting bolts through to the galvanized base. We certainly do not envy those who have to manipulate those frames in the future. Given the opportunity, we should have gone with a more exact material, like fully cut and bored steel bars. This would have made the construction process 100% easier, even if it did put the tables on the far left of our Venn Diagram above. That being said, the final products with the galvanized piping look incredible and will be functional for many years to come.

The work tables presented a whole other host of issues. Breakdowns in communication between multiple supervisors had given us, the student workers, a limited view on the purpose of the tables. One minute we would hear the tables would see light construction work, like assembling small pieces of acrylic, and the next we would be expected to have the table support an entire engine block.

At some point as a group, we got frustrated enough that we confronted our superiors and had them detail specifically what they required. After this event, we were able to move forward with renewed purpose and energy. The design was finished shortly thereafter and we spent a whole day constructing the work table. Made from 80-20 aluminum, these work tables were lighter, stronger and more expensive, than their galvanized pipe counterparts. Since then we have constructed two additional tables, bringing the total number of work tables to three.

The most fun that I had working on these projects was designing and crafting the design table toppers. We ended up constructing three tables with sealed and stained Colorado beetle kill pine, two tables stained with gears branded into them, one table with a looping gear and chain design inlaid into the table, and a final table with an inlaid steampunk blimp.

Overall, this summer job has been an eye opening experience. It has confirmed my interest in the engineering field and peaked my desire to become involved with engineering management.

Please take a look at the pictures posted below. They show just some of the people who have put in the hard work necessary to make this project a success.

...