Advertisement
Advertisement
| 11.04.2008 at 10:18AM PST, ID: 23875283 |
|
[x]
Attachment Details
|
||
|
[x]
The Solution Rating System
|
||
With so many solutions, how can you tell which solutions are most likely to help you and which ones are not? To provide you with a tool to use, we rate our solutions based on various elements that most accurately determine if a solution is a quality solution. To explain what factors affect the solution rating, here are the elements we take into consideration when formulating our solution rating.
Your Input Matters If you have any suggestions that you would like to make for our rating system, please ask a question in the Suggestions Zone of Community Support. Thank you! |
||
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: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: |
#include <iostream>
#include "pyramid.h"
// INCLUDE PLAYER CLASSES
#include "humanplayer.h"
#include "randomplayer.h"
#include "randomtableplayer.h"
using std::cout;
using std::endl;
using std::cin;
int main () {
Pyramid game;
const int opponentCount = 3;
PlayerBase* opponents[2];
// MODIFICATION NOTE:
// This is where the opponents in the game are assigned.
// This is the only place in this function where modifications
// are needed in this function when new player classes are added.
opponents[0] = new HumanPlayer();
opponents[1] = new RandomPlayer();
cout << "Pyramid. Players in this game: " << endl;
cout << "1. ";
opponents[0]->outputName(&cout);
cout << endl << "2. ";
opponents[1]->outputName(&cout);
cout << endl << endl;
bool keepPlaying = true;
while (keepPlaying) {
cout << "Initializing game board." << endl;
game.newGame();
cout << "Initializing players." << endl;
cout << "Initializing player 1." << endl;
opponents[0]->initialize();
cout << "Initializing player 2." << endl;
opponents[1]->initialize();
cout << endl;
bool gameOver = false;
int currentPlayer = 0;
game.display();
while (!gameOver) {
cout << endl << "Player " << currentPlayer + 1 << " turn. ";
opponents[currentPlayer]->outputName(&cout);
cout << "." << endl;
game.performMove(opponents[currentPlayer]->makeMove(game));
cout << "Resulting Board:" << endl;
game.display();
gameOver = game.gameOver();
// if currentPlayer was 0 it becomes 1 and vice versa
currentPlayer = 1 - currentPlayer;
}
cout << "Game Over." << endl;
cout << "Player " << currentPlayer+1 << ", a ";
opponents[currentPlayer]->outputName(&cout);
cout << ", has won." << endl << endl;
cout << "Enter 'y' to play again: ";
char response;
cin >> response;
keepPlaying = ((response == 'y') || (response == 'Y'));
}
return 0;
}
/////////////////////////////////////////////
#ifndef RANDOMTABLEPLAYER
#define RANDOMTABLEPLAYER
#include "playerBase.h"
// RandomTablePlayer
// This player makes a random move each turn, but the moves are
// preselected at the start of the game for each board configuration.
class RandomTablePlayer : public PlayerBase {
public:
virtual void initialize();
virtual void outputName(std::ostream*);
virtual Move makeMove(Pyramid p);
private:
Move movematrix[8][6][4]; // move table
};
#endif
//////////////////////////////
#include "RandomTablePlayer.h"
#include <stdlib.h>
#include <time.h>
void RandomTablePlayer::initialize() {
srand(time(0));
Move m;
int s[3]; // for the three subscripts in our loop
for (s[0] = 0; s[0] <= 7; s[0]++) {
for (s[1] = 0; s[1] <= 5; s[1]++) {
for (s[2] = 0; s[2] <= 3; s[2]++) {
// this "if" is needed because the 0,0,0 configuration
// has to be skipped, as there are no legal moves
if (!s[0] && !s[1] && !s[2]) continue;
// determine a random move. Loop is needed in case a row
// with 0 stones is selected
bool needMove = true;
while (needMove) {
m.level = rand() % 3;
if (s[m.level] != 0) {
m.count = rand() % s[m.level] + 1;
needMove = false;
}
}
movematrix[s[0]][s[1]][s[2]] = m;
}
}
}
}
void RandomTablePlayer::outputName(std::ostream* o) {
*o << "Random player using a table";
}
Move RandomTablePlayer::makeMove(Pyramid p) {
return movematrix[p.getCount(0)][p.getCount(1)][p.getCount(2)];
}
////////////////////////////////////////////////////////////////////
#ifndef RANDOMPLAYER
#define RANDOMPLAYER
#include "playerBase.h"
// RandomPlayer
// This player makes a random move each turn.
class RandomPlayer : public PlayerBase {
public:
virtual void initialize();
virtual void outputName(std::ostream*);
virtual Move makeMove(Pyramid p);
};
#endif
/////////////////////////////////////////////////////////////
#include "RandomPlayer.h"
#include <stdlib.h>
#include <time.h>
void RandomPlayer::initialize() {
srand(time(0));
}
void RandomPlayer::outputName(std::ostream* o) {
*o << "Random player";
}
Move RandomPlayer::makeMove(Pyramid p) {
Move m;
p.resetLegalMoves();
int numMoves = p.getLegalMoveCount();
// generate a number from 1 to the number of legal moves
int randomMoveNumber = rand() % numMoves + 1;
// iterate through moves to that number
for (int i = 1; i <= randomMoveNumber; i++) {
m = p.getNextLegalMove();
}
return m;
}
/////////////////////////////////////////////////////////////
#ifndef PYRAMID
#define PYRAMID
#include "Move.h"
class Pyramid {
public:
Pyramid();
// newGame
// Set initial stone counts.
void newGame();
// performMove
// Makes the given move and returns true, except if the move is illegal,
// the pyramid will be unchanged and the function returns false.
bool performMove(Move m);
// goodMove
// Returns true for a legal move for the current pyramid state, false
// otherwise.
bool goodMove(Move m);
// getCount
// Returns the number of stones on a certain level.
int getCount(int level);
// gameOver
// Returns true if the game is over (all stones are gone), and false
// otherwise.
bool gameOver();
// display
// Displays the board to cout.
void display();
// resetLegalMoves
// Must be called before using getNextLegalMove.
void resetLegalMoves();
// getNextLegalMove
// Calling this repeatedly allows all the legal moves to be
// enumerated. This will return -1, -1 for the move if there
// are no more legal moves. This method assumes the game state for this
// Pyramid hasn't changed since the last call to this function. If it has,
// you have to call reset and start over.
Move getNextLegalMove();
// getLegalMoveCount
// Returns the count of legal moves for this state.
int getLegalMoveCount();
private:
int stoneCount[3];
// used by the legal move methods
int lastLegalRow;
int lastLegalCount;
};
#endif
///////////////////////////////////////////////////////////////
#include "pyramid.h"
#include <iostream>
Pyramid::Pyramid() {
newGame();
}
void Pyramid::newGame() {
stoneCount[0] = 7;
stoneCount[1] = 5;
stoneCount[2] = 3;
}
bool Pyramid::goodMove(Move m) {
if ((m.level < 0) || (m.level > 2)) return false;
if (m.count < 1) return false;
return (stoneCount[m.level] >= m.count);
}
bool Pyramid::performMove(Move m) {
if (!goodMove(m)) return false;
stoneCount[m.level] -= m.count;
return true;
}
bool Pyramid::gameOver() {
return (getLegalMoveCount() == 0);
}
int Pyramid::getCount(int level) {
if ((level < 0) || (level > 2)) return 0;
return stoneCount[level];
}
void Pyramid::display() {
// cheap attempt to make it look like a pyramid
for (int row = 2; row >= 0; row--) {
std::cout << "Level " << row+1 << ": ";
for (int j = (7 - stoneCount[row]) / 2; j > 0; j--) std::cout << " ";
for (j = 1; j <= stoneCount[row]; j++) std::cout << "*";
std::cout << std::endl;
}
}
void Pyramid::resetLegalMoves() {
lastLegalRow = 0;
lastLegalCount = 0;
}
Move Pyramid::getNextLegalMove() {
Move nextMove;
bool foundMove = false;
// set up default values, this is what the function
// will return if we can't find a move.
nextMove.count = -1;
nextMove.level = -1;
while ((!foundMove) && (lastLegalRow < 3)) {
lastLegalCount++;
if (stoneCount[lastLegalRow] >= lastLegalCount) {
nextMove.count = lastLegalCount;
nextMove.level = lastLegalRow;
foundMove = true;
} else {
lastLegalCount = 0;
lastLegalRow++;
}
}
return nextMove;
}
int Pyramid::getLegalMoveCount() {
int sum = 0;
for (int i = 0; i <= 2; i++) sum += stoneCount[i];
return sum;
}
/////////////////////////////////////////////////////////////////
#ifndef PLAYERBASE
#define PLAYERBASE
#include <iostream>
#include "move.h"
#include "pyramid.h"
// PlayerBase
// Abstract class from which all player classes should descend
class PlayerBase {
public:
// initialize
// This function takes no parameters and will be called
// at the start of every game for any initialization the
// player needs to do (not all players will do anything
// in this function).
virtual void initialize() = 0;
// outputName
// Inserts the name of the player into the specified stream
virtual void outputName(std::ostream*) = 0;
// makeMove
// Given the board state specified by the Pyramid parameter,
// returns the Move to make.
virtual Move makeMove(Pyramid p) = 0;
};
#endif
/////////////////////////////////////////////////////////////
#ifndef MOVE
#define MOVE
struct Move {
int level; // level of pyramid 1 - 3
int count; // number of stones to remove
};
#endif
//////////////////////////////////////////////////////////
#ifndef HUMANPLAYER
#define HUMANPLAYER
#include "playerBase.h"
class HumanPlayer : public PlayerBase {
public:
virtual void initialize();
virtual void outputName(std::ostream*);
virtual Move makeMove(Pyramid p);
};
#endif
/////////////////////////////////////////////////////////////////
#include "HumanPlayer.h"
void HumanPlayer::initialize() {
// no initialization needed
}
void HumanPlayer::outputName(std::ostream* o) {
*o << "Human player";
}
Move HumanPlayer::makeMove(Pyramid p) {
Move m;
bool needInput = true;
while (needInput) {
std::cout << "Choose a level (1 - 3): ";
std::cin >> m.level;
// actual level is 0 - 2, we subtract one
// so user can enter level more naturally
m.level--;
std::cout << "Choose a count: ";
std::cin >> m.count;
needInput = !p.goodMove(m);
if (needInput) {
std::cout << "Bad input. " << std::endl;
}
}
return m;
}
Sorry for the long snippet!!
|
| Answered By: | ozo |
| Expert Since: | 08/20/1997 |
| Accepted Solutions: | 9624 |