Ok, I fixed it. I'm undoing moves instead of copying the grid and the weighting system seems to work right for any of the test data I have tried. Still have to add alpha-beta pruning tho.
Code:
#include <stdio.h>
#define DEBUG 0 /* prints gridstates. Not recommended for deep searches */
void show(char* grid)
{
printf(" A B C\n");
for(int r=0; r<9; r+=3)
printf("%d %c %c %c\n", (r/3)+1, grid[r], grid[r+1], grid[r+2]);
putchar('\n');
}
bool is_win(char* grid, char player)
{
char p = (player)?'X':'O';
for(int r=0; r<9; r+=3)
if(grid[r]==p&&grid[r+1]==p&&grid[r+2]==p)
return true;
for(int c=0; c<3; c++)
if(grid[c]==p&&grid[3+c]==p&&grid[6+c]==p)
return true;
if(grid[0]==p&&grid[4]==p&&grid[8]==p)
return true;
if(grid[2]==p&&grid[4]==p&&grid[6]==p)
return true;
return false;
}
int minimax(char* grid, int player, int pos, int depth)
{
int weight = -999999;
int opponent = player^=1;
grid[pos]=(player)?'X':'O'; // Make Move
if(DEBUG) show(grid);
if(is_win(grid, player))
{
grid[pos]=' ';
if(DEBUG)printf((player)?"WIN!\n":"LOSE!\n");
return (depth*10);
}
for(int i=0; i<9; i++) // For each cell
{
if(grid[i] == ' ') // If cell is free
{
//negative value switches to opponent and back depth value (multiplier) reduced each ply only
int temp = 0-minimax(grid, opponent, i, (player)?depth:depth-1);
if(weight== -999999)
weight=temp;
else
weight+=temp;
}
}
grid[pos]=' '; // Undo Move Made
if(weight == -999999)// board is full
{
if(DEBUG)printf("DRAW!\n");
return 0;
}
return weight; // return the highest weight?
}
void choose_move(char* grid, int player, int depth)
{
show(grid);
int weights[9]; // Set by mimimax function
for(int i=0; i<9; i++)
weights[i]=-9999999;
for(int i=0; i<9; i++) // For each cell
{
if(grid[i] == ' ') // If cell is free
{
weights[i] = minimax(grid, player, i, depth);
}
}
for(int i=0; i<9; i++)
printf("%c%d: %d\n", 'A'+(i%3), (i/3)+1, weights[i]);
}
int get_depth(char* grid) /* Gets the number of turns until the end of the game by assessing the board state */
{
int depth = 0;
for(int i=0; i<9; i++)
if(grid[i]==' ')depth++;
return depth;
}
int main()
{
//Players: 1 = X ; 0 = Y
char grid[9]=
{
' ', ' ', ' ',
' ', ' ', ' ',
' ', ' ', ' '
};
int depth = get_depth(grid);
choose_move(grid, 1, depth);
getchar();
}