diff --git a/README.md b/README.md index e69de29..c90a389 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,14 @@ +# TicTacToe in C + +A simple TicTacToe game written in C in under 2 hours! + +## Usage +```bash +./build +``` +then +```bash +./ttt +``` + +Enjoy! diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..707c08b --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ + #!/bin/bash + +set -xe +CFLAGS="-Wall -Werror -std=c11 -ggdb" + +gcc $CFLAGS -o ttt main.c \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..5e4fa99 --- /dev/null +++ b/main.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include + +#define ROWS 3 +#define COLUMNS 3 +#define RED "\033[31m" /* Red */ +#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ +#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ +#define BOLDRED "\033[1m\033[31m" /* Bold Yellow */ +#define BOLDWHITE "\033[1m\033[37m" /* Bold White */ +#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ +#define RESET "\033[0m" + +char board[ROWS][COLUMNS]; +char ESC = 27; + +void print_board(); +void clear_board(); +void player_choice(char player); +void cpu_choice(char cpu); +char check_win(); +int free_spaces(); + +int main(int argc, char *argv[]){ + char flag = ' '; + clear_board(); + + do{ + flag = check_win(); + if(free_spaces() == 0){ + break; + } + + print_board(); + + player_choice('X'); + flag = check_win(); + print_board(); + + player_choice('O'); + flag = check_win(); + print_board(); + + } while(flag == ' '); + + if(flag == ' ') + printf(BOLDMAGENTA "\nNo-one won!" RESET); + else + printf(BOLDMAGENTA "\n%c won!" RESET, flag ); + + printf(BOLDWHITE "\nGame Over!\n" RESET); + return 0; +} + +void print_board(){ + system("clear"); + printf(BOLDWHITE " 1 2 3 \n" RESET); + + printf(BOLDWHITE "1 " RESET); + printf("%c | %c | %c ", board[0][0], board[0][1], board[0][2]); + printf("\n ---|---|---\n"); + + printf(BOLDWHITE "2 " RESET); + printf("%c | %c | %c ", board[1][0], board[1][1], board[1][2]); + printf("\n ---|---|---\n"); + + printf(BOLDWHITE "3 " RESET); + printf("%c | %c | %c ", board[2][0], board[2][1], board[2][2]); + + printf("\n"); +} + +void clear_board(){ + int r, c; + for(r = 0; r < ROWS; ++r){ + for(c = 0; c < COLUMNS; ++c){ + board[r][c] = ' '; + } + } +} + +int free_spaces(){ + int r, c, s; + s = 0; + for(r = 0; r < ROWS; ++r){ + for(c = 0; c < COLUMNS; ++c){ + if(board[r][c] == ' ') ++s; + } + } + return s; +} + +void player_choice(char player){ + + int pr, pc; + printf(BOLDGREEN "\n[%c] Enter row (1, 2 or 3) <---->\n> " RESET, player); + scanf("%d", &pr); + --pr; + + printf(BOLDYELLOW "\n[%c] Enter column (1, 2 or 3) ^ v\n> " RESET, player); + scanf("%d", &pc); + --pc; + + if(board[pr][pc] != ' ' ){ + printf(BOLDRED "\n[%c] Cannot play here, skipping...\n" RESET, player); + } else { + board[pr][pc] = player; + } +} + +void cpu_choice(char cpu){ + time_t t; + srand((unsigned)time(&t)); + + int cr, cc; + cr = cc = 0; + while(board[cr][cc] != ' '){ + cr = rand() % 3; + cc = rand() % 3; + } + board[cr][cc] = cpu; +} + +char check_win(){ + char flag = ' '; + /* + 00 |01 |02 + ---|---|--- + 10 |11 |12 + ---|---|--- + 20 |21 |22 + */ + //horizontal checks l to r + if(board[0][0] == board[0][1] && board[0][1] == board[0][2]){ + flag = board[0][0]; + } + if(board[1][0] == board[1][1] && board[1][1] == board[1][2]){ + flag = board[1][0]; + } + if(board[2][0] == board[2][1] && board[2][1] == board[2][2]){ + flag = board[2][0]; + } + + //horizontal check up n down + if(board[0][0] == board[1][0] && board[1][0] == board[2][0]){ + flag = board[0][0]; + } + if(board[0][1] == board[1][1] && board[1][1] == board[2][1]){ + flag = board[0][1]; + } + if(board[0][2] == board[1][2] && board[1][2] == board[2][2]){ + flag = board[0][2]; + } + + //diagonal checks + if(board[0][0] == board[1][1] && board[1][1] == board[2][2]){ + flag = board[0][0]; + } + if(board[0][2] == board[1][1] && board[1][1] == board[2][0]){ + flag = board[0][2]; + } + + return flag; +} diff --git a/ttt b/ttt new file mode 100755 index 0000000..83d584f Binary files /dev/null and b/ttt differ