Sorry for the double post, but here's V1.4 if anyone's interested:
Main.cpp:
Code:
#include <iostream>
#include "grid.hpp"
using namespace std;
//AUTHOR: Plasticcaz;
#define VERSION 1.4
//ORIGINAL CREATION: 23/10/2012
//LAST MODIFIED: 31/10/2012
// KNOWN ISSUES:
/* #1 -- RESOLVED (1.4)
If a number and then a letter is inputed as a move (EXAMPLE 7a), it
will make the move, and then tell the next user that his input
failed, and needs to try again. Must be a problem with the "Solution" to
infinite loops when there is invalid input.
*/
// CHANGE LOG:
// Version 1.4 (31/10/2012)
// Fixed known issue #1. Thanks to whiteflags from the C forums:
// http://cboard.cprogramming.com/cplusplus-programming/151802-critique-my-tictactoe-game-terminal-based.html#post1130786
// Changed the delete statements in Grid's destructor to delete[] statements, as they should be.
// Made a number of Grid functions const, to ensure const correctness. (The above two were suggested by laserlight, at the
// afore mentioned forums.)
// Version 1.3 (30/10/2012):
// Fixed an issue where I had only allotted 8 chars to the
// boxes array in grid.cpp.
// Version 1.2 (30/10/2012):
// Got rid of unused variable bool running. No purpose for it.
void switchPlayers( int *playerNum)
{
if (*playerNum == PLAYER_ONE)
{
*playerNum = PLAYER_TWO;
} else
{
*playerNum = PLAYER_ONE;
}
}
int main()
{
int playerNum;
int playerWon;
Grid* grid;
grid = new Grid();
playerNum = PLAYER_ONE;
playerWon = NO_ONE;
cout << "\n~-~-~TIC TAC TOE v" << VERSION << "~-~-~\n\n";
cout << "by Plasticcaz\n\n~-~-~-~-~-~-~-~-~-~-~-~-~-\n\n\n";
grid->printGrid();
try
{
while( grid->isMoreMoves() && ( grid->gameWon() == NO_ONE)) //ie. no Player has won.
{
grid->makeMove( playerNum);
cout << "\n\n";
grid->printGrid();
switchPlayers( &playerNum);
}
} catch ( int e)
{
cout << "ERROR ID: " << e << endl;
}
playerWon = grid->gameWon();
if ( playerWon != NO_ONE)
{
cout << "Player " << playerWon << " has won! Congratulations!" << endl;
} else
{
cout << "The game was a draw. Better luck next time!" << endl;
}
cout << "See you next time!" << endl << endl;
delete grid;
cout << "\n\n...Press ENTER to Exit System...";
cin.get();
cin.get();
return 0;
}
Grid.hpp:
Code:
#ifndef GRID_HPP_INCLUDED
#define GRID_HPP_INCLUDED
//ERRORS
#define INVALID_PLAYER 1
//PLAYER WON CONSTANTS
#define NO_ONE 0
#define PLAYER_ONE 1
#define PLAYER_TWO 2
class Grid
{
private:
char *boxes;
char *marks;
int playerWon;
public:
Grid();
~Grid();
void makeMove(const int);
bool isMoreMoves() const;
int gameWon();
void printGrid() const;
};
#endif // GRID_HPP_INCLUDED
grid.cpp:
Code:
#include <iostream>
#include "grid.hpp"
using namespace std;
Grid::Grid()
{
boxes = new char[9];
marks = new char[2];
boxes[0] = '1';
boxes[1] = '2';
boxes[2] = '3';
boxes[3] = '4';
boxes[4] = '5';
boxes[5] = '6';
boxes[6] = '7';
boxes[7] = '8';
boxes[8] = '9';
marks[0] = 'X';
marks[1] = 'O';
playerWon = 0;
}
Grid::~Grid()
{
delete[] boxes;
delete[] marks;
}
void Grid::makeMove( const int playerNo)
{
int block;
bool validBlock = false;
if ( playerNo > 2 || playerNo < 1)
{
cout << "\nERROR: Invalid player being asked to move.\n";
throw INVALID_PLAYER;
}
do
{
cout << "\nPlayer " << playerNo <<" , make your move: ";
//INPUT THE DESIRED BLOCK WHILE CHECKING IF IT WORKED
//Found this solution to my problem at: http://www.daniweb.com/software-development/cpp/threads/314840/infinite-loop-due-to-char-input
while(!(cin >> block))
{
cout << "Input failed...try again\n\n\n";
printGrid();
cout << "\nPlayer " << playerNo <<" , make your move: ";
cin.clear();
while(cin.get() != '\n');
}
if ( cin.peek() != '\n')
{
//Not a block number by itself (eg. 7a)
block = 10; //Make it invalid, so the user must redo input.
}
if ( block >= 1 && block <= 9)
{
if ( boxes[block - 1] != marks[0] &&
boxes[block - 1] != marks[1] )
{
validBlock = true;
}
}
if( !validBlock)
{
cout << "Invalid choice." << endl;
}
} while (! validBlock);
boxes[block - 1] = marks[playerNo - 1];
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
}
bool Grid::isMoreMoves() const
{
bool moreMoves = false;
for ( int i = 0; i < 9; i++)
{
if ( (boxes[i] != marks[0]) && (boxes[i] != marks[1]) )
{
moreMoves = true;
}
}
return moreMoves;
}
int Grid::gameWon()
{
for ( int m = 0; m < 2; m++)
{
//Each possible way to win.
if ( ((boxes[0] == marks[m]) && (boxes[1] == marks[m]) && (boxes[2] == marks[m])) ||
((boxes[3] == marks[m]) && (boxes[4] == marks[m]) && (boxes[5] == marks[m])) ||
((boxes[6] == marks[m]) && (boxes[7] == marks[m]) && (boxes[8] == marks[m])) ||
((boxes[6] == marks[m]) && (boxes[3] == marks[m]) && (boxes[0] == marks[m])) ||
((boxes[7] == marks[m]) && (boxes[4] == marks[m]) && (boxes[1] == marks[m])) ||
((boxes[8] == marks[m]) && (boxes[5] == marks[m]) && (boxes[2] == marks[m])) ||
((boxes[6] == marks[m]) && (boxes[4] == marks[m]) && (boxes[2] == marks[m])) ||
((boxes[8] == marks[m]) && (boxes[4] == marks[m]) && (boxes[0] == marks[m])) )
{
playerWon = m + 1; //Set it equal to the player that won.
}
}
return playerWon;
}
void Grid::printGrid() const
{
cout << boxes[6] << "|" << boxes[7] << "|" << boxes[8] << endl;
cout << "-----" << endl;
cout << boxes[3] << "|" << boxes[4] << "|" << boxes[5] << endl;
cout << "-----" << endl;
cout << boxes[0] << "|" << boxes[1] << "|" << boxes[2] << endl;
}