Question
In Part A, you will convert the Tile type to an encapsulated class. You will also add a class invariant that requires the tile genus
In Part A, you will convert the Tile type to an encapsulated class. You will also add a class invariant that requires the tile genus to be strictly less than GENUS_COUNT.
By the end of Part A, your Tile class will have the following public member functions:
Tile ();
Tile (unsigned int genus1, unsigned int species1);
bool isOwner () const;
unsigned int getAffectedPlayer ( unsigned int whose_turn) const;
unsigned int getGenus () const;
unsigned int getSpecies () const;
void setOwner (unsigned int owner1);
void activate (unsigned int whose_turn) const;
void print () const;
You will also have the following private member functions:
void printOwnerChar () const;
void printGenusChar () const;
void printSpeciesChar () const;
bool isInvariantTrue () const;
Perform the following steps:
- Convert the Tile record to a class. The fields should become private member variables.
- Convert the Tile-associated functions to member functions in the interface (i.e., .h) and implementation (i.e., .cpp) files. The tilePrint*Char functions should be private and the others should be pubic. The tileCreate function should become the non-default constructor. Remove the word tile from the function names and change the new first letter to lowercase. In the implementation file, add Tile:: before every function name.
- Reminder: A * in a name means "anything". So tilePrint*Char refers to three functions.
- Reminder: If a member function calls another member function, you will have to update the name in the call as well.
- Remove the Tile parameter from all the functions. Inside the functions, update the member variables to not use dot notation. For example, tile.genus should become plain genus.
- Add a default constructor that sets the owner to NO_OWNER, the genus to GENUS_MONEY, and the species to 1. Remember to add the function prototype.
- Note: If we don't declare a default constructor, the compiler will not allow us to declare an array of Tiles. (Because it has to call the default constructor for each element when an array is created.) So we need the default constructor or the board won't work.
- Add a precondition to the non-default constructor that requires the genus1 parameter to be strictly less than GENUS_COUNT. Use an assert to enforce the precondition.
- Reminder: Every constructor must initialize every member variable. In this case, your constructor must initialize the genus, the species, and the owner.
- Add a private const member function named isInvariantTrue to check the class invariant. It should return true if the tile genus is strictly less than GENUS_COUNT and false if it is the same or greater.
- Check the class invariant at the end of every non-const public member function. For the Tile class, this is both constructors and setOwner. At the end of each of these functions, use an assert to make sure that isInvariantTrue returns true: assert(isInvariantTrue()); The purpose of this is to ensure that these functions do not leave the Tile in an invalid state. The const functions cannot change the tile state, so we don't need to check the invariant there.
- Note: Don't check the invariant in private functions. It will be checked in the functions that call them.
- Check the class invariant at the start of every public member function except the constructors. Use an assert to make sure that isInvariantTrue returns true. The purpose of this is to ensure that the Tile in a valid state when the function is called.
- Reminder: Don't check the invariant in private functions.
Tile Sample Codes:
Tile.cpp:
//
// Tile.cpp
//
#include
#include
#include "Player.h"
#include "Tile.h"
using namespace std;
const unsigned int NO_OWNER = 999999;
Tile tileCreate (unsigned int genus1,
unsigned int species1)
{
assert(genus1 < GENUS_COUNT);
Tile tile;
tile.owner = NO_OWNER;
tile.genus = genus1;
tile.species = species1;
return tile;
}
bool tileIsOwner (const Tile& tile)
{
if(tile.owner != NO_OWNER)
return true;
else
return false;
}
unsigned int tileGetAffectedPlayer (const Tile& tile,
unsigned int whose_turn)
{
if(tile.owner == NO_OWNER)
return whose_turn;
else
return tile.owner;
}
unsigned int tileGetGenus (const Tile& tile)
{
return tile.genus;
}
unsigned int tileGetSpecies (const Tile& tile)
{
return tile.species;
}
void tileSetOwner (Tile& tile,
unsigned int owner1)
{
tile.owner = owner1;
}
void tileActivate (const Tile& tile,
unsigned int whose_turn)
{
unsigned int affected_player = tileGetAffectedPlayer(tile, whose_turn);
switch(tile.genus)
{
case GENUS_MONEY:
playerIncreaseMoneyAndPrint(affected_player, tile.species);
break;
case GENUS_POINTS:
playerIncreasePointsAndPrint(affected_player, tile.species);
break;
default:
cerr << "[Error: Unhandled genus " << tile.genus << " in tileActivate]";
break;
}
}
void tilePrint (const Tile& tile)
{
tilePrintOwnerChar (tile);
tilePrintGenusChar (tile);
tilePrintSpeciesChar(tile);
}
void tilePrintOwnerChar (const Tile& tile)
{
if(tile.owner == NO_OWNER)
cout << ' ';
else
cout << playerGetTileChar(tile.owner);
}
void tilePrintGenusChar (const Tile& tile)
{
assert(tile.genus < GENUS_COUNT);
switch(tile.genus)
{
case GENUS_MONEY:
cout << "$";
break;
case GENUS_POINTS:
cout << "*";
break;
default:
cerr << "[Error: Unhandled genus " << tile.genus << " in tilePrint]";
break;
}
}
void tilePrintSpeciesChar (const Tile& tile)
{
assert(tile.species < 10); // otherwise more than one char long
cout << tile.species;
}
Tile.h
//
// Tile.h
//
// A module to represent a tile in the game. Anything that can
// occupy a cell of the game board is a tile.
//
// A Tile is an encapsulated abstract data type (ADT). Client
// code should only manipulate it using the interface
// functions provided.
//
// Each tile has a genus and a species, which are collectively
// refered to as the tile type. The genus indicates the
// overall function of the tile (e.g. a money tile). The
// species is the exact type of tile (e.g. a $3 money tile).
//
// Note that the species values can overlap between genuses.
// For example, a $1 money tile and a *1 points tile both use
// a species value of 1.
//
#pragma once
const unsigned int GENUS_COUNT = 4;
const unsigned int GENUS_MONEY = 0;
const unsigned int GENUS_DICE = 1;
const unsigned int GENUS_POINTS = 2;
const unsigned int GENUS_BOMB = 3;
// for money tiles, the species is the money value
// for dice tiles, the species is the number of points
// for points tiles, the species is the number of points
// for bomb tiles, there is no species
struct Tile
{
unsigned int owner;
unsigned int genus;
unsigned int species;
};
Tile tileCreate (unsigned int genus1,
unsigned int species1);
bool tileIsOwner (const Tile& tile);
unsigned int tileGetAffectedPlayer (const Tile& tile,
unsigned int whose_turn);
unsigned int tileGetGenus (const Tile& tile);
unsigned int tileGetSpecies (const Tile& tile);
void tileSetOwner (Tile& tile,
unsigned int owner1);
void tileActivate (const Tile& tile,
unsigned int whose_turn);
void tilePrint (const Tile& tile);
void tilePrintOwnerChar (const Tile& tile);
void tilePrintGenusChar (const Tile& tile);
void tilePrintSpeciesChar (const Tile& tile);
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started