Created
October 13, 2018 17:09
-
-
Save woodrowbarlow/44b9375443e8312c4becb771bbb3b6f6 to your computer and use it in GitHub Desktop.
gcc tak.c -o tak; ./tak
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
/* each line along which a player can win */ | |
enum axes { | |
HORIZ_TOP, | |
HORIZ_MID, | |
HORIZ_BOT, | |
VERT_LEFT, | |
VERT_MID, | |
VERT_RIGHT, | |
DIAG_TOP_LEFT, /* from top left to bottom right */ | |
DIAG_BOT_LEFT, /* from bottom left to top right */ | |
AXES_MAX | |
}; | |
/* if any rank hits (plus or minus) three, the game is over */ | |
static int ranks[AXES_MAX] = { 0 }; | |
static char board[3][3] = { | |
{ ' ', ' ', ' ' }, | |
{ ' ', ' ', ' ' }, | |
{ ' ', ' ', ' ' }, | |
}; | |
static int check_game_state(void) | |
{ | |
int i; | |
/* if any rank hits (plus or minus) three, the game is over. | |
* - positive indicates 'x' wins | |
* - negative indicates 'o' wins | |
*/ | |
for (i = 0; i < AXES_MAX; i++) | |
{ | |
switch (ranks[i]) | |
{ | |
case 3: | |
return 1; | |
case -3: | |
return -1; | |
} | |
} | |
return 0; | |
} | |
static void draw_board(void) | |
{ | |
int i; | |
printf("\n [1] [2] [3]\n\n"); | |
printf("[A] %c | %c | %c \n", | |
board[0][0], board[0][1], board[0][2]); | |
for (i = 1; i < 3; i++) | |
{ | |
printf(" ---|---|---\n"); | |
printf("[%c] %c | %c | %c \n", 'A' + i, | |
board[i][0], board[i][1], board[i][2]); | |
} | |
} | |
static int get_input(int *row, int *col) | |
{ | |
char tmp = 0; | |
char r = 0; | |
unsigned int c = 0; | |
int matches = 0; | |
matches = scanf("%c%u", &r, &c); | |
while (tmp != '\n' && tmp != EOF) | |
{ | |
/* scanf doesn't remove extra leftovers from the buffer */ | |
tmp = getchar(); | |
} | |
if (matches != 2 || c < 1 || c > 3) | |
{ | |
return -1; | |
} | |
switch (r) | |
{ | |
case 'a': | |
case 'b': | |
case 'c': | |
*row = r - 'a'; | |
break; | |
case 'A': | |
case 'B': | |
case 'C': | |
*row = r - 'A'; | |
break; | |
default: | |
return -1; | |
} | |
*col = (int) c - 1; | |
return 0; | |
} | |
static void make_move(int row, int col, char player) | |
{ | |
int rank_factor = (player == 'x') ? 1 : -1; | |
/* the game ends if any rank hits (plus or minus) three. | |
* there is a rank for each "axis" on which you can win: | |
* - the three horizontal rows (top, middle, and bottom) | |
* - the three vertical columns (left, middle, and right) | |
* - the two diagonal axes (from top left, from bottom left) | |
*/ | |
/* update rank for each axis this move affected */ | |
ranks[HORIZ_TOP + row] += rank_factor; | |
ranks[VERT_LEFT + col] += rank_factor; | |
ranks[DIAG_TOP_LEFT] += ((row == 0 && col == 0) || | |
(row == 1 && col == 1) || | |
(row == 2 && col == 2)) ? rank_factor : 0; | |
ranks[DIAG_BOT_LEFT] += ((row == 2 && col == 0) || | |
(row == 1 && col == 1) || | |
(row == 0 && col == 2)) ? rank_factor : 0; | |
/* then update the board itself */ | |
board[row][col] = player; | |
} | |
int main(void) | |
{ | |
int spaces_available = 9; | |
char player = 'o'; | |
while (spaces_available > 0 && check_game_state() == 0) | |
{ | |
player = (player == 'x') ? 'o' : 'x'; | |
draw_board(); | |
int row; | |
int col; | |
while (get_input(&row, &col) != 0 || board[row][col] != ' ') | |
{ | |
/* do nothing */ | |
} | |
make_move(row, col, player); | |
spaces_available--; | |
} | |
draw_board(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment