13
« on: November 06, 2008 »
I've just finished this Tic Tac Toe console app in C++. It works, but I'd like some ideas/advice on best practices.
The idea being that I swap out FreeBASIC as my default tool, and replace it with VS c++ in the long run.
// TicTacToe.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
#define TTT_X 1
#define TTT_O 2
class classTicTacToe
{
public:
int board[9];
classTicTacToe()
{
for (int a=0;a<9;a++)
board[a]=0;
}
~classTicTacToe() {}
void PutX(int x, int y)
{
if (x>=0 && x<3 && y>=0 && y<3) board[y*3+x] = TTT_X;
}
void PutO(int x, int y)
{
if (x>=0 && x<3 && y>=0 && y<3) board[y*3+x] = TTT_O;
}
void Clear(int x, int y)
{
if (x>=0 && x<3 && y>=0 && y<3) board[y*3+x] = 0;
}
int Check(int x, int y)
{
if (x>=0 && x<3 && y>=0 && y<3)
return board[y*3+x];
else
return 0;
}
int GameWon(void)
{
// Check for horizontal wins
for (int y=0;y<3;y++)
{
if (Check(0,y)==TTT_X && Check(1,y)==TTT_X && Check(2,y)==TTT_X) return TTT_X;
if (Check(0,y)==TTT_O && Check(1,y)==TTT_O && Check(2,y)==TTT_O) return TTT_O;
}
// Check for Vertical wins
for (int x=0;x<3;x++)
{
if (Check(x,0)==TTT_X && Check(x,1)==TTT_X && Check(x,2)==TTT_X) return TTT_X;
if (Check(x,0)==TTT_O && Check(x,1)==TTT_O && Check(x,2)==TTT_O) return TTT_O;
}
// Check for Diagonal wins
if (Check(0,0)==TTT_X && Check(1,1)==TTT_X && Check(2,2)==TTT_X) return TTT_X;
if (Check(0,0)==TTT_O && Check(1,1)==TTT_O && Check(2,2)==TTT_O) return TTT_O;
if (Check(2,0)==TTT_X && Check(1,1)==TTT_X && Check(0,2)==TTT_X) return TTT_X;
if (Check(2,0)==TTT_O && Check(1,1)==TTT_O && Check(0,2)==TTT_O) return TTT_O;
// else return 0
return 0;
}
int GameDrawn(void)
{
for (int y=0;y<3;y++)
for (int x=0;x<3;x++)
if (Check(x,y)==0) return 0;
// else return true
return -1;
}
char GetChar(int x, int y)
{
if (Check(x,y)==TTT_X) return 'X';
if (Check(x,y)==TTT_O) return 'O';
return ' ';
}
void DrawBoard()
{
cout << " a b c" << endl;
cout << "1 " << GetChar(0,0) << "|" << GetChar(1,0) << "|" << GetChar(2,0) << endl;
cout << " -+-+-" << endl;
cout << "2 " << GetChar(0,1) << "|" << GetChar(1,1) << "|" << GetChar(2,1) << endl;
cout << " -+-+-" << endl;
cout << "3 " << GetChar(0,2) << "|" << GetChar(1,2) << "|" << GetChar(2,2) << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
classTicTacToe myTTT;
string inputBuffer;
int whosTurn = 0;
int exitPressed = 0;
while (!exitPressed)
{
myTTT.DrawBoard();
if (whosTurn==0)
cout << "X's turn" << endl;
else
cout << "O's turn" << endl;
cout << endl << "Enter a move or x to exit. Ex a1<enter>" << endl;
std::getline(std::cin, inputBuffer);
cout << endl << endl;
if (inputBuffer=="x")
exitPressed=1;
else
{
// Check for a valid move
if (inputBuffer.length()!=2)
cout << "Please enter a 2 character board location and press enter. Ex b3<enter>" << endl;
else
{
char iB1=inputBuffer[0];
char iB2=inputBuffer[1];
int x=-1;
int y=-1;
if (iB1=='a') x=0;
if (iB1=='b') x=1;
if (iB1=='c') x=2;
if (iB2=='1') y=0;
if (iB2=='2') y=1;
if (iB2=='3') y=2;
if (x<0 || y<0)
cout << "Invalid move. Bad coordinates." << endl;
else
{
// Check if the square is free
if (myTTT.Check(x,y)!=0)
cout << "Invalid move. Square already occupied." << endl;
else
{
if (whosTurn==0)
{
whosTurn=1;
myTTT.PutX(x,y);
}
else
{
whosTurn=0;
myTTT.PutO(x,y);
}
}
}
}
}
// Check for a draw
if (myTTT.GameDrawn())
{
myTTT.DrawBoard();
cout << "Game drawn! Press <enter> to finish." << endl;
std::getline(std::cin, inputBuffer);
exitPressed=1;
}
// Check for a win
if (int winner=myTTT.GameWon())
{
myTTT.DrawBoard();
if (winner==TTT_X)
cout << "X Wins the game! Press <enter> to finish." << endl;
else
cout << "O Wins the game! Press <enter> to finish." << endl;
std::getline(std::cin, inputBuffer);
exitPressed=1;
}
}
return 0;
}