I wrote a basic tic-tac-toe game based on multidimensional arrays. g[3][3]. In my program I have about 9 conditions like the one I am about to show you:
if((g[0][0] == X && g[0][1] == X && g[0][2] == X) || (g[0][0] == O && g[0][1] == O && g[0][2] == O))
This is quite insane. I am probably doing something wrong but this is why I am addressing this question. Is there an easier way of representing long and complicated conditions like this? For example couldn't I somehow do:
if(grid.hasXes)
You're probably going about it the wrong way. There are only 3^9, or
19683 possible combinations, so you can convert your grid to an int
,
even on a 16 bit machine:
int
asInt( char const (&grid)[3][3] )
{
int results = 0;
for ( int i = 0; i != 3; ++ i ) {
for ( int j = 0; j != 3; ++ j ) {
results *= 3;
switch ( grid[i][j] ) {
case 'X':
results += 1;
break;
case 'Y':
results += 2;
break;
case ' ':
break;
default:
assert(0);
}
}
}
return results;
}
Afterwards, you can use the int to index into a table indicating who won (if anyone). Alternatively, you can convert just one or the other player's position into a 9 bit int:
int
asInt( char const (&grid)[3][3], char who )
{
int results = 0;
for ( int i = 0; i != 3; ++ i ) {
for ( int j = 0; j != 3; ++ j ) {
results *= 2;
if ( grid[i][j] == who ) {
++ results;
}
}
}
return results;
}
You can then use a simple linear search into a table, verifying that the necessary bits are set:
static int const wins[] =
{
0007, 0070, 0700, // rows
0111, 0222, 0444, // columns
0124, 0421 // diagonals
};
class Wins
{
int myToMatch;
public:
Wins( char const (&grid)[3][3], char who )
: myToMatch( asInt( grid, who ) )
{
}
bool operator()( int entry ) const
{
return (entry & myToMatch) == entry;
}
};
Then:
if ( std::find_if( begin( wins ), end( wins ), Wins( grid, 'X' ) )
!= end( wins ) {
// X wins
else if ( std::find_if( begin( wins ), end( wins ), Wins( grid, 'O' ) )
!= end( wins ) {
// O wins
else
// play another turn.
You could even consider keeping the grid as two int
s, one per player.
The bit number for a position would be 3 * i + j
, and to test if a
move is legal:
bool
isLegal( int gridX, int gridY, int i, int j )
{
return ((gridX | gridY) & (1 << (3 * i + j))) == 0;
}