1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
|
template<class T>//add dynamic array parameter
ColLabeledTable<T>::ColLabeledTable(char startLbl, int lblWidth, int rows, int cols)
{
startLabel = startLbl;
labelWidth = lblWidth;
row = rows;
col = cols;
table = new T *[rows];
//set values to default
for (int i = 0; i < rows; i++) {
table[i] = new T[col];
for (int j = 0; j < cols; j++) {
table[i][j] = T();
}
}
}
template<class T>
ColLabeledTable<T>::ColLabeledTable(const ColLabeledTable &otherTable)
{
//copy of non dynamic members
//copy label
startLabel = otherTable.startLabel;
//copy rows
col = otherTable.col;
//copy columns
row = otherTable.row;
//new pointer pointer
//T **table;
//allocate 1st array to row size
table = new T *[row];
for (int i = 0; i < row; i++) {
//allocate 2d array
table[i] = new T[col];
for (int j = 0; j < col; j++) {
//copy values in the 2d array
table[i][j] = otherTable.table[i][j];
}
}
}
template<class T>
ColLabeledTable<T> &ColLabeledTable<T>::operator=(const ColLabeledTable &otherTable)
{
//check for self assignment
if (this != &otherTable)
{
//deallocate old array
for (int i = 0; i < row; i++)
{
delete[] table[i];
}
delete[] table;
table = NULL;
//copy objects members
//non dynamic members
startLabel = otherTable.startLabel;
labelWidth = otherTable.labelWidth;
col = otherTable.col;
row = otherTable.row;
//allocate new array
table = new T *[row];
for (int i = 0; i < row; i++) {
//allocate 2d array
table[i] = new T[col];
for (int j = 0; j < col; j++) {
//copy values in the 2d array
table[i][j] = otherTable.table[i][j];
}
}
}
return *this;
}
//destructor
template<class T>
ColLabeledTable<T>::~ColLabeledTable()
{
cout << "in destructor " << table[0][0];
//deallocate 2d array
for (int i = 0; i < col; i++)
delete[] table[i];
delete[] table;
//prevent dangling pointer
table = NULL;
//reset non dynamic members
startLabel = 'a';
row = 0;
col = 0;
}
// Return number of rows in table.
template<class T>
int ColLabeledTable<T>::getNumRows() const
{
return row;
}
// Return number of columns in table.
template<class T>
int ColLabeledTable<T>::getNumCols() const
{
return col;
}
// Display table with column labels on standard output.
template<class T>
void ColLabeledTable<T>::display() const
{
int i, j;
// Display header with column labels.
T colLabel = startLabel;
for (j = 0; j < col; j++)
{
cout << "|" << setw(labelWidth) << colLabel;
colLabel++;
}
cout << endl;
// Nested loop to display values at all positions.
T rowLabel = startLabel;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
// Display value at position.
cout << setw(labelWidth + 1) << table[i][j];
}
cout << endl; // each row on own line
}
}
template<class T>
T ColLabeledTable<T>::getPos(int row, int col) const
{
return table[row - 1][col - 1];
}
//rows and columns passed should be
// numbered starting with 1 (not zero) and be within
// size of table.
template<class T>
void ColLabeledTable<T>::setPos(int row, int col, const T &val)
{
//set row col and char
// Place value at specified position in table.
table[row - 1][col - 1] = val;
}
const char EMPTY_CHAR = ' ';
const char PEG_CHAR = '.';
const char CHIP_CHAR = '*';
void generateBoard(ColLabeledTable<char> &board);
int advanceChip(const ColLabeledTable<char> &board, int &row, int &col);
// Test copying by invoking the copy constructor and
// assignment operator.
void testCopy(const ColLabeledTable<char> &board);
int main()
{
// Allow user to enter size of board.
// Although range checking would be useful, not required.
int rows, cols;
cout << "Enter # rows on board: ";
cin >> rows;
cout << "Enter # columns on board: ";
cin >> cols;
// Start "numbering" columns with letter below.
const char COL_START = 'a';
// Seed random number generator to get different
// random sequence based on time.
srand((unsigned int)time(NULL));
// Create board representing game with starting
// letter used to label columns and width of a
// column label in # characters.
ColLabeledTable<char> gameBoard(COL_START, 1, rows, cols);
// Track score for game.
int score = 0;
cout << "\nLet's play Plincode!" << endl;
do // Play (potentially) multiple games.
{
// Generate new board with pegs and point values.
generateBoard(gameBoard);
// Display current score and initial board.
cout << "\nScore: " << score << endl;
gameBoard.display();
// Test copying of game board.
testCopy(gameBoard);
// Store current position of chip.
// Set to start at top.
int chipRow = 0;
int chipCol;
char colLetter;
cout << "\nEnter letter of starting column for chip (x=exit): ";
cin >> colLetter;
cin.ignore(); // eat newline
// User wants to exit game?
if (colLetter == 'x')
break;
// Translate from letter to 1-based column index.
// Although validating character entered would be useful,
// not required.
chipCol = colLetter - COL_START + 1;
// Let chip fall from top, being diverted if peg
// is below it.
advanceChip(gameBoard, chipRow, chipCol);
do
{
// Place chip at its current position on board.
gameBoard.setPos(chipRow, chipCol, CHIP_CHAR);
// Display board configuration with chip.
gameBoard.display();
// Allow user to advance chip to next row.
cout << "\nPress <Enter> for chip to fall to next row: ";
string option;
getline(cin, option);
// Erase chip from its current position.
gameBoard.setPos(chipRow, chipCol, EMPTY_CHAR);
// Let chip fall one row, being diverted if peg
// is below it.
int points = advanceChip(gameBoard, chipRow, chipCol);
// Increase score and start new game if reached bottom row.
if (points != 0)
{
score += points;
cout << "You earned " << points << " point(s)!" << endl;
break; // exit inner loop
}
} while (true);
} while (true);
cout << "\nWe hope you enjoyed Plincode!!" << endl;
return 0;
}
// Definitions for functions that help set up/advance game.
void generateBoard(ColLabeledTable<char> &board)
{
// FILL IN FUNCTION
//use constants to set pegs and spaces
//pegs are even, spaces are odd
for (int i = 1; i < board.getNumRows(); i++) {
for (int j = 1; j <= board.getNumCols(); j++) {
if ((i + j) % 2 == 0)
{
board.setPos(i, j, PEG_CHAR);
}
else {
board.setPos(i, j, EMPTY_CHAR);
}
}
}
//set up last row in seperate for loop for the rand number generator
for (int i = 0; i < board.getNumCols(); i++)
{
board.setPos(board.getNumCols(), i + 1, ('a' + i) - 49);
//for()
}
//
//for (int j = 1; j <= board.getNumCols(); j++)
//{
// char randChar = 48 + rand() % board.getNumCols();
// board.setPos(board.getNumRows(), j, randChar);//(char)rand() % board.getNumCols() + 1);
//}
}
// Advance chip's position to next row. How it falls depends
// on whether a peg is present.
int advanceChip(const ColLabeledTable<char> &board, int &row, int &col)
{
//get the current position value
//need to add 1 to row to get it on the first row
char currPosition = board.getPos(row + 1, col);
//test if it has empty char
//kept separate for clarity
if (currPosition == EMPTY_CHAR)
{
//advance to next row
row++;
}
else {
//returns score
return currPosition;// +48;
}
//kept separate since if it is a peg there is no score to return
//test if it has peg char
if (currPosition == PEG_CHAR)
{
//keeps it from falling off the left side
if (currPosition == 1)
{
col++;
}//keeps it from falling off the right side
else if (currPosition == board.getNumCols())
{
col--;
}
else
{
//will make the move random
if (rand() % 2 == 0)
{
col++;
}else
{
col--;
}
}
//advance row
row++;
}
return 0; // no points earned
}
|