Skip to content

Instantly share code, notes, and snippets.

@AnnaOpss
Last active December 22, 2015 06:29
Show Gist options
  • Save AnnaOpss/6431552 to your computer and use it in GitHub Desktop.
Save AnnaOpss/6431552 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
/* This function looks for winning moves of a player */
void findThreat (int, int [][2], int [][3]);
int main (int argc, char* argv[])
{
int grid[3][3], nextgrid[3][3], i, j, col, row, positionO, Threats[2][2];
int Forks[2][2], forknum, win, shouldgoon;
puts("=========================");
puts("| OOO | OOO | X X | HELLO, AND WELCOME STRANGER");
puts("| O O | O O | X |");
puts("| OOO | OOO | X X | GET READY NOT TO WIN AT");
puts("|=======|=======|=======|");
puts("| | X X | | TIC-TAC-TOE!!");
puts("| | X | |");
puts("| | X X | |");
puts("|=======|=======|=======| For input, think of a grid like:");
puts("| X X | | |");
puts("| X | | | 1 2 3");
puts("| X X | | | 4 5 6");
puts("|=======|=======|=======| 7 8 9");
puts("");
puts("");
win = 0;
for (i=0; i<3; i++)
for (j=0; j<3; j++) {
grid[i][j] = 0;
nextgrid[i][j] = 0;
}
do {
puts("Place your O:");
scanf("%d", &positionO);
puts("");
if (positionO > 9 || positionO < 1)
continue;
positionO = positionO - 1;
col = positionO % 3;
row = positionO / 3;
if (grid[row][col] != 0)
continue;
grid[row][col] = 1;
// WINNING STRATEGY COURTESY OF
// https://en.wikipedia.org/wiki/Tic-tac-toe#Strategy
// 1. Win
findThreat (2, Threats, grid);
if (Threats[0][0] != -1) {
grid[Threats[0][0]][Threats[0][1]] = 2;
win = 1;
goto print; // I know, http://xkcd.com/292/
}
// 2. Block
findThreat (1, Threats, grid);
if (Threats[0][0] != -1) {
grid[Threats[0][0]][Threats[0][1]] = 2;
goto print;
}
// 3. Fork
for (i=0; i<3; i++)
for (j=0; j<3; j++) {
memcpy(nextgrid, grid, 3*3*sizeof (int));
if (grid[i][j] != 0)
continue;
nextgrid[i][j] = 2;
findThreat (2, Threats, nextgrid);
if (Threats[0][0] != -1 && Threats[1][0] != -1) {
grid[i][j] = 2;
goto print;
}
}
// 4. Block an opponent's fork
for (i=0; i<2; i++)
for (j=0; j<2; j++)
Forks[i][j]=-1;
forknum = 0;
for (i=0; i<3; i++)
for (j=0; j<3; j++) {
memcpy(nextgrid, grid, 3*3*sizeof (int));
if (grid[i][j] != 0)
continue;
nextgrid[i][j] = 1;
findThreat (1, Threats, nextgrid);
if (Threats[0][0] != -1 && Threats[1][0] != -1) {
Forks[forknum][0] = i;
Forks[forknum][1] = j;
forknum++;
}
}
// Option 2 (means there's only one fork possible, block it)
if (forknum == 1) {
grid[Forks[0][0]][Forks[0][1]] = 2;
goto print;
}
// Option 1 (more than one fork possible, force into defending)
if (forknum == 2) {
for (i=0; i<3; i++)
for (j=0; j<3; j++) {
memcpy(nextgrid, grid, 3*3*sizeof (int));
if (grid[i][j] != 0)
continue;
nextgrid[i][j] = 2;
findThreat (2, Threats, nextgrid);
if ((Threats[0][0] == Forks[0][0] && Threats[0][1] == Forks[0][1]) ||
(Threats[0][0] == Forks[1][0] && Threats[0][1] == Forks[1][1]))
continue;
if (Threats[0][0] != -1) {
grid[i][j] = 2;
goto print;
}
}
}
// 5. Center
if (grid[1][1] == 0) {
grid[1][1] = 2;
goto print;
}
// 6. Opposite corner
if (grid[0][0] == 1){ grid[2][2] = 2; goto print;}
if (grid[0][2] == 1){ grid[2][0] = 2; goto print;}
if (grid[2][0] == 1){ grid[0][2] = 2; goto print;}
if (grid[2][2] == 1){ grid[0][0] = 2; goto print;}
// 7. Empty corner
if (grid[0][0] == 0){ grid[0][0] = 2; goto print;}
if (grid[0][2] == 0){ grid[0][2] = 2; goto print;}
if (grid[2][0] == 0){ grid[2][0] = 2; goto print;}
if (grid[2][2] == 0){ grid[2][2] = 2; goto print;}
// 8. Empty side
if (grid[0][1] == 0){ grid[0][1] = 2; goto print;}
if (grid[1][0] == 0){ grid[1][0] = 2; goto print;}
if (grid[2][1] == 0){ grid[2][1] = 2; goto print;}
if (grid[1][2] == 0){ grid[1][2] = 2; goto print;}
print:
for (i=0; i<3; i++) {
for (j=0; j<3; j++)
switch (grid[i][j]) {
case 0:
printf ("_ ");
break;
case 1:
printf ("O ");
break;
case 2:
printf ("X ");
break;
}
printf("\n");
}
printf("\n");
if (win) break;
shouldgoon = 0;
for (i=0; i<3; i++)
for (j=0; j<3; j++)
if (grid[i][j] == 0)
shouldgoon = 1;
} while (shouldgoon);
return 0;
}
void findThreat (int player, int Threats [][2], int grid[][3]) {
int k, threatnum, i, j, a;
for (i=0; i<2; i++)
for (j=0; j<2; j++)
Threats[i][j] = -1;
threatnum = 0;
// Threats on a row
for (i=0; i<3; i++) {
k = 0;
a = -1;
for (j=0; j<3; j++) {
if (grid[i][j] == player)
k++;
if (grid[i][j] == 0)
a = j;
}
if (k == 2 && a != -1) {
Threats[threatnum][0] = i;
Threats[threatnum][1] = a;
threatnum++;
}
}
// Threats on a column
for (j=0; j<3; j++) {
k = 0;
a = -1;
for (i=0; i<3; i++) {
if (grid[i][j] == player)
k++;
if (grid[i][j] == 0)
a = i;
}
if (k == 2 && a != -1) {
Threats[threatnum][0] = a;
Threats[threatnum][1] = j;
threatnum++;
}
}
// Threats on top-to-bottom diagonal
k = 0;
a = -1;
for (i=0; i<3; i++) {
if (grid[i][i] == player)
k++;
if (grid[i][i] == 0)
a=i;
}
if (k == 2 && a != -1) {
Threats[threatnum][0] = a;
Threats[threatnum][1] = a;
threatnum++;
}
// Threats on the other diagonal
k = 0;
a = -1;
for (i=0; i<3; i++) {
if (grid[i][2-i] == player)
k++;
if (grid[i][2-i] == 0)
a = i;
}
if (k == 2 && a != -1) {
Threats[threatnum][0] = a;
Threats[threatnum][1] = 2 - a;
threatnum++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment