# include "stdio.h"
# include "limits.h"
int MAX (int x, int y) {
if (x > y) {
return x;
}
else {
return y;
}
}
int MIN (int x, int y) {
if (x < y) {
return x;
}
else {
return y;
}
}
char gridChar(int i) {
switch(i) {
case -1:
return 'X';
case 0:
return ' ';
case 1:
return 'O';
}
}
void draw(int* b) {
printf(" %c | %c | %c\n",gridChar(b[0]),gridChar(b[1]),gridChar(b[2]));
printf("---+---+---\n");
printf(" %c | %c | %c\n",gridChar(b[3]),gridChar(b[4]),gridChar(b[5]));
printf("---+---+---\n");
printf(" %c | %c | %c\n",gridChar(b[6]),gridChar(b[7]),gridChar(b[8]));
}
int win(const int* board) {
//determines if a player has won, returns 0 otherwise.
unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
int i;
for(i = 0; i < 8; ++i) {
if(board[wins[i][0]] != 0 &&
board[wins[i][0]] == board[wins[i][1]] &&
board[wins[i][0]] == board[wins[i][2]])
return board[wins[i][2]];
}
return 0;
}
int alphabeta(int* board, int depth, int alpha, int beta, bool max_player) {
int score = 0;
max_player = true;
if(depth == 0){
return score;
}
if(max_player) {
alpha = INT_MIN;
while (depth != 0) {
score = alphabeta(board, depth - 1, alpha, beta, !max_player);
alpha = MAX(alpha, score );
if (beta <= alpha) break;
}
return alpha;
}
else {
beta = INT_MAX;
while (depth != 0) {
score = alphabeta(board, depth - 1, alpha, beta, !max_player);
beta = MIN(beta, score );
if (beta <= alpha) break;
}
return beta;
}
}
void computerMove(int* board) {
int move = -1;
int score = -2;
int i;
for(i = 0; i < 9; ++i) {
if(board[i] == 0) {
board[i] = 1;
int tempScore = -alphabeta(board,6, -10000, 10000, true);
board[i] = 0;
if(tempScore > score) {
score = tempScore;
move = i;
}
}
}
//returns a score based on minimax tree at a given node.
board[move] = 1;
}
void playerMove(int* board) {
int move = 0;
do {
printf("\nInput move ([0..8]): ");
scanf("%d", &move);
printf("\n");
} while (move >= 9 || move < 0 && board[move] == 0);
board[move] = -1;
}
int main() {
int board[9] = {0,0,0,0,0,0,0,0,0};
//computer squares are 1, player squares are -1.
printf("Computer: O, You: X\nPlay (1)st or (2)nd? ");
int player=0;
scanf("%d",&player);
printf("\n");
unsigned turn;
for(turn = 0; turn < 9 && win(board) == 0; ++turn) {
if((turn+player) % 2 == 0)
computerMove(board);
else {
draw(board);
playerMove(board);
}
}
switch(win(board)) {
case 0:
printf("A draw. How droll.\n");
break;
case 1:
draw(board);
printf("You lose.\n");
break;
case -1:
printf("You win. Inconceivable!\n");
break;
}
}
ICAgICMgaW5jbHVkZSAic3RkaW8uaCIKICAgICMgaW5jbHVkZSAibGltaXRzLmgiCgogICAgaW50IE1BWCAoaW50IHgsIGludCB5KSB7CiAgICAJaWYgKHggPiB5KSB7CiAgICAJCXJldHVybiB4OwogICAgCX0KICAgIAllbHNlIHsKICAgIAkJcmV0dXJuIHk7CiAgICAJfQogICAgfQoKICAgIGludCBNSU4gKGludCB4LCBpbnQgeSkgewogICAgCWlmICh4IDwgeSkgewogICAgCQlyZXR1cm4geDsKICAgIAl9CiAgICAJZWxzZSB7CiAgICAJCXJldHVybiB5OwogICAgCX0KICAgIH0KCgogICAgY2hhciBncmlkQ2hhcihpbnQgaSkgewogICAgICAgIHN3aXRjaChpKSB7CiAgICAgICAgICAgIGNhc2UgLTE6CiAgICAgICAgICAgICAgICByZXR1cm4gJ1gnOwogICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICByZXR1cm4gJyAnOwogICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICByZXR1cm4gJ08nOwogICAgICAgIH0KICAgIH0KCiAgICB2b2lkIGRyYXcoaW50KiBiKSB7CiAgICAgICAgcHJpbnRmKCIgJWMgfCAlYyB8ICVjXG4iLGdyaWRDaGFyKGJbMF0pLGdyaWRDaGFyKGJbMV0pLGdyaWRDaGFyKGJbMl0pKTsKICAgICAgICBwcmludGYoIi0tLSstLS0rLS0tXG4iKTsKICAgICAgICBwcmludGYoIiAlYyB8ICVjIHwgJWNcbiIsZ3JpZENoYXIoYlszXSksZ3JpZENoYXIoYls0XSksZ3JpZENoYXIoYls1XSkpOwogICAgICAgIHByaW50ZigiLS0tKy0tLSstLS1cbiIpOwogICAgICAgIHByaW50ZigiICVjIHwgJWMgfCAlY1xuIixncmlkQ2hhcihiWzZdKSxncmlkQ2hhcihiWzddKSxncmlkQ2hhcihiWzhdKSk7CiAgICB9CgogICAgaW50IHdpbihjb25zdCBpbnQqIGJvYXJkKSB7CiAgICAgICAgLy9kZXRlcm1pbmVzIGlmIGEgcGxheWVyIGhhcyB3b24sIHJldHVybnMgMCBvdGhlcndpc2UuCiAgICAgICAgdW5zaWduZWQgd2luc1s4XVszXSA9IHt7MCwxLDJ9LHszLDQsNX0sezYsNyw4fSx7MCwzLDZ9LHsxLDQsN30sezIsNSw4fSx7MCw0LDh9LHsyLDQsNn19OwogICAgICAgIGludCBpOwogICAgICAgIGZvcihpID0gMDsgaSA8IDg7ICsraSkgewogICAgICAgICAgICBpZihib2FyZFt3aW5zW2ldWzBdXSAhPSAwICYmCiAgICAgICAgICAgICAgIGJvYXJkW3dpbnNbaV1bMF1dID09IGJvYXJkW3dpbnNbaV1bMV1dICYmCiAgICAgICAgICAgICAgIGJvYXJkW3dpbnNbaV1bMF1dID09IGJvYXJkW3dpbnNbaV1bMl1dKQogICAgICAgICAgICAgICAgcmV0dXJuIGJvYXJkW3dpbnNbaV1bMl1dOwogICAgICAgIH0KICAgICAgICByZXR1cm4gMDsKICAgIH0KCiAgICBpbnQgYWxwaGFiZXRhKGludCogYm9hcmQsIGludCBkZXB0aCwgaW50IGFscGhhLCBpbnQgYmV0YSwgYm9vbCBtYXhfcGxheWVyKSB7CiAgICAJCiAgICAJaW50IHNjb3JlID0gMDsKICAgIAltYXhfcGxheWVyID0gdHJ1ZTsKICAgIAkKICAgIAlpZihkZXB0aCA9PSAwKXsKICAgIAkJcmV0dXJuIHNjb3JlOwogICAgCX0KICAgIAkKICAgIAlpZihtYXhfcGxheWVyKSB7CiAgICAJCWFscGhhID0gSU5UX01JTjsKICAgIAkJd2hpbGUgKGRlcHRoICE9IDApIHsKICAgIAkJc2NvcmUgPSBhbHBoYWJldGEoYm9hcmQsIGRlcHRoIC0gMSwgYWxwaGEsIGJldGEsICFtYXhfcGxheWVyKTsKICAgIAkJCWFscGhhID0gTUFYKGFscGhhLCBzY29yZSApOwogICAgCQkJaWYgKGJldGEgPD0gYWxwaGEpIGJyZWFrOwogICAgCQl9CiAgICAJCXJldHVybiBhbHBoYTsKICAgIAl9CiAgICAJZWxzZSB7CiAgICAJCWJldGEgPSBJTlRfTUFYOwogICAgCQl3aGlsZSAoZGVwdGggIT0gMCkgewogICAgCQkJc2NvcmUgPSBhbHBoYWJldGEoYm9hcmQsIGRlcHRoIC0gMSwgYWxwaGEsIGJldGEsICFtYXhfcGxheWVyKTsKICAgIAkJCWJldGEgPSBNSU4oYmV0YSwgc2NvcmUgKTsKICAgIAkJCWlmIChiZXRhIDw9IGFscGhhKSBicmVhazsKICAgIAkJfQogICAgCQlyZXR1cm4gYmV0YTsKICAgIAl9CiAgICB9CgoKICAgIHZvaWQgY29tcHV0ZXJNb3ZlKGludCogYm9hcmQpIHsKICAgICAgICBpbnQgbW92ZSA9IC0xOwogICAgICAgIGludCBzY29yZSA9IC0yOwogICAgICAgIGludCBpOwogICAgICAgIGZvcihpID0gMDsgaSA8IDk7ICsraSkgewogICAgICAgICAgICBpZihib2FyZFtpXSA9PSAwKSB7CiAgICAgICAgICAgICAgICBib2FyZFtpXSA9IDE7CiAgICAgICAgICAgICAgICBpbnQgdGVtcFNjb3JlID0gLWFscGhhYmV0YShib2FyZCw2LCAtMTAwMDAsIDEwMDAwLCB0cnVlKTsKICAgICAgICAgICAgICAgIGJvYXJkW2ldID0gMDsKICAgICAgICAgICAgICAgIGlmKHRlbXBTY29yZSA+IHNjb3JlKSB7CiAgICAgICAgICAgICAgICAgICAgc2NvcmUgPSB0ZW1wU2NvcmU7CiAgICAgICAgICAgICAgICAgICAgbW92ZSA9IGk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy9yZXR1cm5zIGEgc2NvcmUgYmFzZWQgb24gbWluaW1heCB0cmVlIGF0IGEgZ2l2ZW4gbm9kZS4KICAgICAgICBib2FyZFttb3ZlXSA9IDE7CiAgICB9CgoKICAgIHZvaWQgcGxheWVyTW92ZShpbnQqIGJvYXJkKSB7CiAgICAgICAgaW50IG1vdmUgPSAwOwogICAgICAgIGRvIHsKICAgICAgICAgICAgcHJpbnRmKCJcbklucHV0IG1vdmUgKFswLi44XSk6ICIpOwogICAgICAgICAgICBzY2FuZigiJWQiLCAmbW92ZSk7CiAgICAgICAgICAgIHByaW50ZigiXG4iKTsKICAgICAgICB9IHdoaWxlIChtb3ZlID49IDkgfHwgbW92ZSA8IDAgJiYgYm9hcmRbbW92ZV0gPT0gMCk7CiAgICAgICAgYm9hcmRbbW92ZV0gPSAtMTsKICAgIH0KCiAgICBpbnQgbWFpbigpIHsKICAgICAgICBpbnQgYm9hcmRbOV0gPSB7MCwwLDAsMCwwLDAsMCwwLDB9OwogICAgICAgIC8vY29tcHV0ZXIgc3F1YXJlcyBhcmUgMSwgcGxheWVyIHNxdWFyZXMgYXJlIC0xLgogICAgICAgIHByaW50ZigiQ29tcHV0ZXI6IE8sIFlvdTogWFxuUGxheSAoMSlzdCBvciAoMiluZD8gIik7CiAgICAgICAgaW50IHBsYXllcj0wOwogICAgICAgIHNjYW5mKCIlZCIsJnBsYXllcik7CiAgICAgICAgcHJpbnRmKCJcbiIpOwogICAgICAgIHVuc2lnbmVkIHR1cm47CiAgICAgICAgZm9yKHR1cm4gPSAwOyB0dXJuIDwgOSAmJiB3aW4oYm9hcmQpID09IDA7ICsrdHVybikgewogICAgICAgICAgICBpZigodHVybitwbGF5ZXIpICUgMiA9PSAwKQogICAgICAgICAgICAgICAgY29tcHV0ZXJNb3ZlKGJvYXJkKTsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBkcmF3KGJvYXJkKTsKICAgICAgICAgICAgICAgIHBsYXllck1vdmUoYm9hcmQpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHN3aXRjaCh3aW4oYm9hcmQpKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIHByaW50ZigiQSBkcmF3LiBIb3cgZHJvbGwuXG4iKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICBkcmF3KGJvYXJkKTsKICAgICAgICAgICAgICAgIHByaW50ZigiWW91IGxvc2UuXG4iKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIC0xOgogICAgICAgICAgICAgICAgcHJpbnRmKCJZb3Ugd2luLiBJbmNvbmNlaXZhYmxlIVxuIik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9Cgo=