Quote:
|
Originally Posted by UnKnown X
You should try making an expanded tic-tac-toe where the user decides how many rows and columns on which to play. Then you can't make the AI so specific. Makes for a nice challenge.
|
thanks, I'll keep that in mind for a challenge
Here is the second rough version.
The computer will now block you from winning.
Next I'd like to add a offensive function with a 50% chance of running (so the computer is still beatable)
anyway, here it is:
tic.h
//tic.h -- TicTacToe declarations
#ifndef TICTACTOE_H_
#define TICTACTOE_H_
class Board
{
private:
char *checkBoard(int);
protected:
static char board[3][3];
char player;
char otherPlayer;
public:
Board(char,char);
void reset();
virtual bool makeMove(int);
bool checkWin();
void show() const;
virtual ~Board();
bool checkCats() const;
};
class CBoard : public Board
{
public:
CBoard(char, char);
virtual bool makeMove();
private:
int *checkDefence();
void makeRandomMove();
// int checkOffence();
};
#endif
tic.cpp
//tic.cpp -- implementation of class
#include <iostream>
#include "tic.h"
char Board::board[3][3];
Board::Board(char icon, char otherIcon)
{
//std::cout << "constructor called" << std::endl;
player = icon;
otherPlayer = otherIcon;
}
void Board::reset()
{
for(int x = 0; x < 3; x++)
for(int y = 0; y < 3; y++)
Board::board[x][y] = ' ';
}
bool Board::makeMove(int space)
{
//board setup is like that of numpad
if(space < 1 || space > 9)
{
std::cout << "invalid range!" << std::endl;
return false;
}
int x, y; //x-axis, y-axis
x = y = 0;
switch(space) {
case 7:
x = 0;
y = 0;
break;
case 8:
x = 1;
y = 0;
break;
case 9:
x = 2;
y = 0;
break;
case 4:
x = 0;
y = 1;
break;
case 5:
x = 1;
y = 1;
break;
case 6:
x = 2;
y = 1;
break;
case 1:
x = 0;
y = 2;
break;
case 2:
x = 1;
y = 2;
break;
case 3:
x = 2;
y = 2;
break;
}
if((Board::board[x][y] == otherPlayer) || (Board::board[x][y] == player)) //if space is taken...
return false; //move failed. return false.
else
{
Board::board[x][y] = player; //otherwise, make move
return true; //return success
}
}
char *Board::checkBoard(int part)
{
//0, 1, 2 ==> cols
//3, 4, 5 ==> rows
//6, 7 ==> diagonals
char *temp = new char[3];
int space;
switch(part)
{
//columns
case 0:
case 1:
case 2:
for(int a = 0; a < 3; a++)
temp[a] = Board::board[part][a];
break;
//rows
case 3:
space = 0;
for(int a = 0; a < 3; a++)
temp[a] = Board::board[a][space];
break;
case 4:
space = 1;
for(int a = 0; a < 3; a++)
temp[a] = Board::board[a][space];
break;
case 5:
space = 2;
for(int a = 0; a < 3; a++)
temp[a] = Board::board[a][space];
break;
//diagonals
case 6:
temp[0] = Board::board[0][2];
temp[1] = Board::board[1][1];
temp[2] = Board::board[2][0];
break;
case 7:
temp[0] = Board::board[0][0];
//std::cout << "from checkBoard -- diagonal 2 " << Board::board[0][0] << std::endl;
temp[1] = Board::board[1][1];
//std::cout << "from checkBoard -- diagonal 2 " << Board::board[1][1] << std::endl;
temp[2] = Board::board[2][2];
//std::cout << "from checkBoard -- diagonal 2" << Board::board[2][2] << std::endl;
break;
}
return temp;
}
bool Board::checkWin()
{
int count = 0;
bool winner = false;
//checking columns
for(int x = 0; x < 3; x++)
{ //for each colums
char *col = checkBoard(x);//get the column
count = 0;
for(int a = 0; a < 3; a++) //check each space in column
if(*(col + a) == player) //if space is taken
count++; //increase count
if(count == 3)
{ //if all three taken on column...
winner = true; //set winner to true;
//std::cout << "column winner" << std::endl;
}
delete [] col;
}
//checking rows
for(int x = 3; x < 6; x++)
{ //for each rows
char *row = checkBoard(x);
count = 0; //starting count again
for(int a = 0; a < 3; a++)
if(*(row + a) == player) //if space is taken
count++; //increase count
if(count == 3)
{
winner = true;
//std::cout << "row winner" << std::endl;
}
delete [] row;
}
//checking diagonals
count = 0;
char *dia1 = checkBoard(6);
//for(int a = 0; a < 3; a++)
// std::cout << "diagonal[" << a << "] = " << dia1[a] << std::endl;
for(int x = 0; x < 3; x++)
{
if(*(dia1 + x) == player)
count++;
}
if(count == 3)
{
//std::cout << "diagonal 1 winner" << std::endl << std::endl;
winner = true;
}
delete [] dia1;
//second diagonal
count = 0;
char *dia2 = checkBoard(7);
//for(int a = 0; a < 3; a++)
// std::cout << "diagonal[" << a << "] = " << dia2[a] << std::endl;
for(int x = 0; x < 3; x++)
if(*(dia2 + x) == player)
count++;
if(count == 3)
{
//std::cout << "diagonal 2 winner" << std::endl;
winner = true;
}
delete [] dia2;
return winner; //returns false if no win, true if winner
}
void Board::show() const
{
std::cout << "---------";
for(int a = 0; a < 3; a++)
{
std::cout << std::endl;
std::cout << "|";
for(int c = 0; c < 3; c++)
std::cout << " " << Board::board[c][a];
std::cout.put(' ');
std::cout << "|";
}
std::cout << "\n---------" << std::endl;
}
bool Board::checkCats() const
{
int taken = 0;
for(int x = 0; x < 3; x++)
for(int y = 0; y < 3; y++)
if(Board::board[x][y] != ' ')
taken++;
/*if(taken == 9)
std::cout << "return true" << std::endl;
else
std::cout << "return false" << std::endl;
return (taken == 9);*/
return taken == 9;
}
Board::~Board()
{
}
//CBoard method definitions
CBoard::CBoard(char icon, char otherIcon)
: Board(icon, otherIcon)
{
player = icon;
otherPlayer = otherIcon;
}
int *CBoard::checkDefence()
{
//look for any spots where the human player will win
//first look for rows
int *spot = new int[3];
bool found = false;
int count = 0;
for(int x = 0; x < 3; x++)
{
count = 0;
for(int y = 0; y < 3; y++)
{
if(Board::board[x][y] == otherPlayer && Board::board[x][y] != player)
count++;
if(count == 2)
{
for(int c = 0; c < 3; c++)
{
if(Board::board[x][c] != otherPlayer && Board::board[x][c] != player)
{
spot[0] = x;
spot[1] = c;
found = true;
}
}
}
}
}
if(found)
return spot;
//then check for columns
count = 0;
for(int x = 0; x < 3; x++)
{
count = 0;
for(int y = 0; y < 3; y++)
{
if(Board::board[y][x] == otherPlayer && Board::board[y][x] != player)
count++;
if(count == 2)
{
for(int c = 0; c < 3; c++)
{
if(Board::board[c][x] != otherPlayer && Board::board[c][x] != player)
{
spot[0] = c;
spot[1] = x;
found = true;
}
}
}
}
}
if(found)
return spot;
//check diagonals
count = 0;
//first diagonal: lower left to upper right
if(Board::board[0][2] == otherPlayer && Board::board[1][1] == otherPlayer
&& Board::board[2][0] != player)
{
spot[0] = 2; //2
spot[1] = 0; //0
found = true;
//std::cout << "diagonal should be blocked" << std::endl;
}
else if(Board::board[1][1] == otherPlayer && Board::board[2][0] == otherPlayer
&& Board::board[0][2] != player)
{
spot[0] = 0; //0
spot[1] = 2; //2
found = true;
//std::cout << "diagonal should be blocked" << std::endl;
}
else if(Board::board[0][2] == otherPlayer && Board::board[2][0] == otherPlayer
&& Board::board[1][1] != player)
{
spot[0] = 1; //1
spot[1] = 1; //1
found = true;
//std::cout << "diagonal should be blocked" << std::endl;
}
if(found)
return spot;
//second diagonal
if(Board::board[0][0] == otherPlayer && Board::board[1][1] == otherPlayer
&& Board::board[2][2] != player)
{
spot[0] = 2; //2
spot[1] = 2; //2
found = true;
//std::cout << "diagonal should be blocked" << std::endl;
}
else if(Board::board[1][1] == otherPlayer && Board::board[2][2] == otherPlayer
&& Board::board[0][0] != player)
{
spot[0] = 0; //0
spot[1] = 0; //0
found = true;
//std::cout << "diagonal should be blocked" << std::endl;
}
else if(Board::board[0][0] == otherPlayer && Board::board[2][2] == otherPlayer
&& Board::board[1][1] != player)
{
spot[0] = 1; //1
spot[1] = 1; //1
found = true;
//std::cout << "diagonal should be blocked" << std::endl;
}
if(found)
return spot;
return NULL;
}
void CBoard::makeRandomMove()
{
srand(time(0));
while(1)
{
int move = rand() % 9 + 1;
if(Board::makeMove(move)) //if move is good
break;
else
continue; //otherwise, make another move
}
}
bool CBoard::makeMove()
{
int *spot = checkDefence();
if(spot != NULL)
{
//std::cout << "spot[0] = " << spot[0] << std::endl;
//std::cout << "spot[1] = " << spot[1] << std::endl;
Board::board[spot[0]][spot[1]] = player;
}
else
{
srand(time(0));
makeRandomMove();
}
delete [] spot;
return true;
}
main.cpp
#include "tic.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(0));
Board b1('x', 'o');
CBoard b2('o', 'x');
bool done = false;
b2.reset();
while(!done)
{
int move;
while(1)
{
cout << "Enter move: ";
cin >> move;
if(!b1.makeMove(move)) //bad move
cout << "bad move" << endl;
else
break;
}
//cout << "out of first whiel loop" << endl;
b1.show();
if(b1.checkWin())
{
cout << "x wins!" << endl;
done = true;
continue;
}
if(b1.checkCats())
{
cout << "cat's game" << endl;
done = true;
continue;
}
//cout << "b2.makeMove()" << endl;
b2.makeMove();
b2.show();
if(b2.checkWin())
{
cout << "o wins!" << endl;
done = true;
continue;
}
if(b2.checkCats())
{
cout << "cat's game" << endl;
done = true;
continue;
}
}
return 0;
}