Question & Answer: in C++ write a program that simulates one turn of the Monopoly game example. For this program, only the…..

in C++ write a program that simulates one turn of the Monopoly game example. For this program, only the following squares exist: RegularSquare, GoSquare, IncomeTaxSquare, JailSquare, and GoToJailSquare.

Using the UML sketches in the text as your blueprint, the design utilizes the following patterns: polymorphism, indirection, pure fabrication, and protected variations.

Here are the UML sketches from the text from which to base your implementation:

A player has a location, but thanks to the polymorphism pattern, that location could have different effects based on the landedOn responsibility.

Figure 25.3 is not the final design. A new class by Pure Fabrication is introduced at the end. The final design for your implementation is reflected in figure 25.9 which replaces figure 25.3. However, there is still important information here for the design, so it’s included here.

Note in figure 25.3 a player passes itself to the square through the landedOn message.

When landing on a RegularSquare, nothing happens. In this case, landedOn is a NO-OP method.

IncomeTaxSquare can send a message to Player because it receives a reference to the Player through the landedOn message.

IncomeTaxSquare has to ask the player for it’s net worth so it can figure out the amount of tax and then send a message to Player telling it how much to reduce it’s cash attribute.

Here, the GoToJailSquare is initialized with a reference to JailSquare so it can be passed as an argument to Player.

By Pure Fabrication, we can lower coupling and increase cohesion by introducing a “made up” class named Cup to roll the dice for us. Figure 25.9 should replace figure 25.3 in your final implementation.

Make sure your identifiers match up with the UML. For example, class Player needs to have a variable named loc and class Board must have a method named getTotal with two parameters. Have the player start the turn with $1500 and display the cash total at the end of the turn. Have the Player display the dice roll total to the screen. Have each square display to the user they landed on the square.

Yes, we’re violating the Model-View separation principle for the assignment so we don’t have to include a UI layer and we’re not following the layered architecture pattern.

Grading will be based on how accurately your solution implements the above design, identifiers and all.

Hints:

Create a array of Shape references/pointers in class Board. These references can be used for the loc attribute in class Player.

Since there are only 5 squares in our simple program, the array should be 5 elements long.

Everything you need to create design classes is provided by the UML sketches. Some design class attributes are implicit.

There is no requirement for a layered architecture in this assignment.

Incorporate the logic for taking the turn within the Player class constructor. As a result, your main function will only contain a statement instantiating the Player object.

Don’t panic, this looks like a lot, but it’s really not. Each class usually has one method. Divide and conquer. Just take it one class at a time.

Here are three sample runs from my solution:

Here’s what my Player class’s constructor looks like:

And here’s my main function:

Expert Answer

 

#include <iostream>
#include <iomanip>
#include <ctime>
using namespace std;
//status equivalence to the L, S, D, O, W
enum State
{ N, L, S, D, O, W};  //N means nothing, it is my default situation means no situation
const SquareNum = 100;  //number of squares
const TokenNum =4;  //number of players
const SnakeNum =9;  //number of snake tails
const LadderNum =9; //number of ladders
const LadderShift =16;  //min number of squares to advance for ladders
const LadderScale = 15;  //max -min of number of squares to advance for ladders
const SnakeShift = 12; //min number of squares to retreat for snake
const SnakeScale = 37; //range of snake = max -min of snake
//array of game
int board[SquareNum] = {0};
//array of player, record the index of array, not the position
int token[TokenNum] = {0};
//the variable recording numbers of turns
int turnCounter = 1;
//check status of the new position, and write the new position back to array of game
//if there is any change 
State checkState(int player, int step);
//a general function to generate random number for range of scale, and shift by shift
int randNum(int scale, int shift);
//roll 1 dice
int roll1Dice();
//roll 2 dice
int roll2Dice();
//play game
void playGame();
//initialize the array of game
void initialize();
//display the array of game
void displayBoard();
//this is the cpp file game.cpp
#include "game.h"
int main()
{
        char choice[3];
        //in order to try different seed to get different outcome of same code
        cout<<"Do you want a fixed seed 248?";
        cin>>choice;
        if (strcmp("yes", choice)==0)
        {
                srand(248);
        }
        else
        {
                srand(time(0));
        }
        initialize();
        displayBoard();
        playGame();
        return 0;
}
//check specific position to see if there is other token on it
bool checkPlayer(int newPos)
{
        for (int i=0; i<TokenNum; i++)
        {
                if (token[i]==newPos)
                {
                        return true;
                }
        }
        return false;
}
//check all situation of new position
State checkState(int player, int step)
{
        int newPos;
        newPos = token[player] + step; //newPos is the index of array
        
        //at the biginning of game the position should minus 1
        if (token[player] == 0)
        {
                newPos --;
        }
        
        //if find there is another token in your new position, don't move
        if (checkPlayer(newPos))
        {
                return D;
        }
        
        //if new position is exceeding board, it is "O"
        if (newPos > 99)
        {
                return O;
        }
        //the winning situation
        if (newPos == 99)
        {
                token[player] = 99;
                return W;
        }
        //if it is snake
        if (board[newPos]<0)
        {
                //and if the tail of snake is not occupied by other token, then move to it.
                if (!checkPlayer(board[newPos]+newPos))
                {
                        token[player] = board[newPos] + newPos;
                        return S;
                }
                else
                {
                        return D;
                }
        }
        //if it is ladder,
        if (board[newPos]>0)
        {
                //and there is no other token occupying new position
                if (!checkPlayer(board[newPos]+newPos))
                {
                        token[player] = board[newPos] + newPos;
                        return L;
                }
                else
                {
                        return D;
                }
        }
        //if no status is found, it is ok to go, write the new pos to array of player
        token[player] = newPos;
        return N;
}
//output total of dice, status, and new position
void outPut(int player, int step)
{
        State state;
        
        //output turn number at beginning of each turn
        if (player%TokenNum==0)
        {
                cout<<setiosflags(ios::right)<<setw(3)<<turnCounter<<".";
        }
        //output total of dice
        cout<<setiosflags(ios::right);
        if (token[player]>=93)
        {
                cout<<setw(8)<<setiosflags(ios::right)<<step<<"*";
        }
        else
        {
                cout<<setw(9)<<setiosflags(ios::right)<<step;
        }
        //output moves, if next pos is free to go
        cout<<" - ";
        
        state = checkState(player, step);
        //at the beginning the position is 0, but elsewhere it is "index +1 = position"
        if (token[player]!=0)
        {
                cout<<setw(3)<<resetiosflags(ios::right)<<setiosflags(ios::left)
                        <<token[player] + 1;
        }
        else
        {
                cout<<setw(3)<<resetiosflags(ios::right)<<setiosflags(ios::left)
                        <<0;
        }
        
        switch(state)
        {
        case L:
                cout<<"L";
                break;
        case S:
                cout<<"S";
                break;
        case D:
                cout<<"D";
                break;
        case O:
                cout<<"O";
                break;
        case W:
                cout<<"W";
                break;
        case N:
                cout<<" ";
                break;
        }
        //if it is last player of this turn, new line
        if (player == TokenNum -1)
        {
                cout<<endl;
        }
}
bool checkWinner(int player)
{
        int step =0;
        if (token[player]>= 93)   //index is 93, pos is 94
        {
                step = roll1Dice();
        }
        else
        {
                step = roll2Dice();
        }
        outPut(player, step);
        return token[player]==99;
}
void playGame()
{
        int player =0;
        cout<<"nSimulation of the game:nn";
        cout<<"Turn";
        for (int i =0; i<TokenNum; i++)
        {
                cout<<setiosflags(ios::right)<<setw(15)<<"token #"<<i+1;
        }
        cout<<endl;
        cout<<"----";
        for (i=0; i<TokenNum; i++)
        {
                cout<<setw(16)<<setiosflags(ios::right)<<"--------";
        }
        cout<<endl;
        
        while (!checkWinner(player))
        {               
                player++;
                //when reached 4, new turn
                if (player == TokenNum)
                {
                        turnCounter++;
                        player =0;
                }
        }
        cout<<endl;       
}

//this is a general function to randomize number based on a range(or scale)
//and then shift by "shift" numbers
int randNum(int scale, int shift)
{
        return rand()%scale + shift;
}
int roll1Dice()
{
        return randNum(6, 1);
}
int roll2Dice()
{
        return roll1Dice() + roll1Dice();
}
//this function will be called by function initialize to check when generating
//Ladders and snakes to prevent they occupy the same square
bool checkOccupy(int occupy[], int size, int pos, int effect)
{
        //the rule is eliminate situations that snake or ladders is at winning position=100
        //or exceed bounds(negative or bigger than 99)
        if (pos+effect<0||pos+effect>=99||pos==99)
        {
                return false;
        }
        
        //prevent same position of two snakes or ladders and their tails or heads
        for (int i=0; i< size; i++)
        {
                if (pos==occupy[i]||(pos + effect)==occupy[i])
                {
                        return false;
                }
        }
        return true;
}
void initialize()
{
        //I simply cannot find a better way to avoid repeat position of ladders and 
        //snakes. So I use a temporary array to record the position of each S's&L's
        //and their "high end" or "head place".
        int occupy[2*LadderNum+2*SnakeNum] = {0};
        //
        int pos=0, //position of snake or ladder in board
                effect =0;//either advance or retreat number of ladder or snake
        
        //generate snakes
        for (int snake = 0; snake < SnakeNum; snake++)
        {
                pos = randNum(100, 0);
                effect = - randNum(SnakeScale, SnakeShift);//snake is minus effect
                while (!checkOccupy(occupy, snake*2, pos, effect))
                {
                        pos = randNum(100, 0);
                        effect = - randNum(SnakeScale, SnakeShift);                     
                }
                board[pos] = effect;   //put snake on board
                //record snake tail and head place in array "occupy"
                occupy[2*snake] = pos;
                occupy[2*snake+1] = pos + effect;
        }
        //generate ladders
        for (int ladder =0; ladder< LadderNum; ladder++)
        {
                pos = randNum(100, 0);
                effect = randNum(LadderScale, LadderShift);
                //check if generated position and its effect until they are ok,
                while (!checkOccupy(occupy, SnakeNum*2 + ladder* 2, pos, effect))
                {
                        pos = randNum(100, 0);
                        effect = randNum(LadderScale, LadderShift);
                }
                board[pos] = effect;   //put ladder on board
                //record ladder and end place in array "occupy"
                occupy[SnakeNum*2 + ladder* 2] = pos;
                occupy[SnakeNum*2 + ladder* 2+1] = pos + effect;
        }
}
void displayBoard()
{
        for (int i=0; i< SquareNum; i++)
        {
                
                cout<<"Square no."<<setw(3)<<setiosflags(ios::right)<<i+1<<" = "
                        <<setiosflags(ios::right)<<setw(3)<<board[i];
                //display in 4 column, change line when i+1 mod 4
                //use i+1 simply to avoid 0%4 for the first case
                cout<<((i+1)%4!=0?"t":"n");
        }
}
Still stressed from student homework?
Get quality assistance from academic writers!