I want to adopt good coding habits now. the below code was written under tight constraints. We don't do assignment post mortems in class to discuss "real world" best practices -- we just get letter grades with little or no feedback. What are some examples of good questions I can ask myself to determine when code that works for an assignment would be re-written in real world applications?
(I'm also very interested in memory management, which we haven't covered in class. Any memory management tips re: the below code would be super-appreciated!)
Note: this is a finished assignment; I'm not looking for help to complete it, just help to develop good habits as early as possible.
Assignment:
- simulate 5,500 craps games and print out the results.
- other than
main(), use only one function --dice_roll(). All calculations are inline. - the assignment covers,
enums, output precision andrand()andsrand()functions. - use
enumto define WIN, LOSE, and CONTINUE to give the results for each roll. - use
constdata sizes:int SIZEandint ROLLS.
Please feel free to provide any comments/questions as you see fit.
#include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> // this is what will hold our data during the games struct nodeType { int num_rolls; int win; int loss; nodeType* link; }; // these pointers will be used to traverse and perform operations // on the nodes as we figure out what to do with them nodeType *first, *last, *current, *trailCurrent, *newNode, *temp; int roll_dice(); int main() { enum gameOutcome { CONTINUE, WIN, LOSE }; gameOutcome game_result; const int MAX_GAMES(5500); int sum, point, roll; first = NULL; // start of our list last = NULL; // end of our list srand(time(0)); // give rand() new seed for (int i = 1; i <= MAX_GAMES; ++i) // this for loop simulates all games { sum = roll_dice(); newNode = new nodeType; // create new node for this game newNode->link = NULL; // make sure it doesn't point to anything switch (sum) // first roll test { case 7: game_result = WIN; roll = 1; case 11: game_result = WIN; roll = 1; break; case 2: game_result = LOSE; roll = 1; case 3: game_result = LOSE; roll = 1; case 12: game_result = LOSE; roll = 1; break; default: game_result = CONTINUE; point = sum; roll = 1; break; } // end of switch while (game_result == CONTINUE) // if no win/lose after 1st roll { sum = roll_dice(); ++roll; if (sum == point) game_result = WIN; else if (sum == 7) game_result = LOSE; } // these assignments prepare our node fields to accept the // game outcome data newNode->num_rolls = roll; newNode->win = 0; newNode->loss = 0; if(game_result == WIN) newNode->win = 1; // adds one win for unique # of rolls else newNode->loss = 1; // adds one loss for unique # of rolls if(first == NULL) // if empty list creates list on first roll { first = newNode; last = newNode; } else { current = first; // starts search at beginning of list int found(0); // use for list elem search while (current != NULL && found < 1) // search to insert ascending order { if (current->num_rolls == roll) // has a game w/ this number of rolls { // been played? if (game_result == WIN) current->win += 1; // if so add one win to that "row" else current->loss += 1; // if so add one loss to that "row" found = 1; } else if (current->num_rolls > roll) // if game's #rolls is < than some found = 2; // #rolls in the list else { trailCurrent = current; current = current->link; // advances the search one node } } // end of while if (found == 1) delete[] newNode; // if #rolls for complete game already exists, // delete this node. this is like "deduping" a // database to first normal form else if (current == first) // inserts node at beginning of list { newNode->link = first; first = newNode; } else { trailCurrent->link = newNode; // inserts node in middle of list newNode->link = current; if (current == NULL) // if it's the biggest #rolls so far last = newNode; // insert node at end of list } // end of last else } // end of 1st else } // end of main for loop int sum_wins(0), sum_loss(0); current = first; // set to first node in list before iterating over it while (current != NULL) // print results and sum wins/losses { std::cout << std::setw(4) << current->win << " games won and " << std::setw(3) << current->loss << " games lost on roll " << current->num_rolls << std::endl; sum_wins += current->win; // summing wins for use below sum_loss += current->loss; // summing losses for use below current = current->link; } // calculate the odds based on game results std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << "\nodds of winning are " << sum_wins << " / " << sum_wins + sum_loss << " = " << std::setprecision(2) << 100.0 * sum_wins / (sum_wins + sum_loss) << "%." << std::endl; // calculate avg num rolls per game double avg_length(0); current = first; while (current != NULL) { avg_length += (current->win + current->loss) * current->num_rolls; current = current->link; } std::cout << "avg num rolls/game is " << std::setprecision(2) << avg_length / 5500.00 << " rolls." << std::endl; while (first != NULL) // destroy list { temp = first; first = first->link; delete[] temp; } last = NULL; std::cout << "press RET to exit"; std::cin.get(); return 0; } // end of int main() int roll_dice() { return (rand() % 6) + (rand() % 6) + 2; }
Will I remember what this method does next month?Next isCan I make this easier to read?anotherIs my method doing more than 1 thing?\$\endgroup\$