Skip to content

Instantly share code, notes, and snippets.

@qbatten
Created June 21, 2018 18:45
Show Gist options
  • Save qbatten/c9228a637ddba6ee3579a2922c12c49f to your computer and use it in GitHub Desktop.
Save qbatten/c9228a637ddba6ee3579a2922c12c49f to your computer and use it in GitHub Desktop.
Tic Tac Toe - Quinn Batten
/*------------Libraries------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*------------PRINT BOARD: prints the current board state------------*/
/*
Input: the current board state, represented by a char* of length 10 (9char+\0), where spaces that have been played
in have an "X" or "O" (whichever player played there), and unplyed spaces have a lowercase letter between a
and i, in increasing order from top left.
Output: Prints the board state, does not return any value.
*/
void printBoard(char *board)
{
printf("\033[2J"); //clear screen
printf("\n %c | %c | %c \n", board[0], board[1], board[2]);
printf("-----------\n");
printf(" %c | %c | %c \n", board[3], board[4], board[5]);
printf("-----------\n");
printf(" %c | %c | %c \n", board[6], board[7], board[8]);
}
/*------------GAME OVER: Prints congratulatory message------------*/
//Input: (int) If someone won, the int of the ASCII Char of the winner.
//Output: Prints the result of the game, then returns 1 (unless there's a problem).
int gameOver(int result)
{
if ((int) result == 88 || (int) result == 79) //if X or O won
{
printf("\nGAME OVER!\nPlayer %c is the winner!!\n", (char) result);
return 1;
}
else if (result == 1) //tie
{
printf("\nIt's a tie!!!\n");
return 1;
}
else //Should never happen
{
printf("\nError in Game Over. Wrong result passed to fn.\n");
return 0;
}
}
/*------------CHANGE PLAYER: Changes the player whose turn it is, then prompts for the current player's move.------------*/
//Input: (char *player) the char representing the current player. Must be "X" or "O", aka (char) 88 or (char) 79.
//Output: (char) a char representing the NEW current player. Must be "X" or "O", aka (char) 88 or (char) 79.
char changePlayer(char player)
{
if (player == 88) //X
{
player = 79;
}
else if (player == 79) //O
{
player = 88;
}
else //Should never happen
{
printf("ERROR IN MOVE: Wrong player passed");
}
return player;
}
/*------------PROMPT MOVE: Prompts for the current player's move.------------*/
/*
Input:
1. (char *board) the current board state as a pointer to allocated memory (must be writable).
2. (char *player) the char representing the current player. Must be "X" or "O", aka (char) 88 or (char) 79.
Output:
(int) an integer between 0 and 8 (inclusive) represnting the space on the board that the current player
wants to play in.
*/
int promptMove(char *board, char player)
{
printf("Player %c, which space would you like to play?: ", player);
int last = 41; //int value of ASCII character; used to check for double newlines & quits
//loop to check validity of submission
while (1 == 1)
{
int space; //int (0-8); the space on the board that the player has selected
int input; //int value of ASCII character; the immediate, most recent typed value
int answer = 0; //int value of ASCII character;where input goes if its not garbage.
while ((input = getchar()) != EOF && input != '\n') //Toss newlines and EOF
//NOTE: Need to make this while loop more robust. I want it to only accept one char at a time & to toss ANSI escape codes, but haven't figured it out yet. Something with fgets, it sounds like.
{
if (answer == 0 && input >= 97 && input <= 105) //Check if it's an ASCII char btwn 'a' and 'i'
{
answer = input;
space = answer - 97; //translate ASCII code to space in board array
if (board[space] >= 97 && board[space] <= 105) //check if that space has been played
{
return space;
}
else
{
printBoard(board);
printf("\nThat space is taken already! Please try again:");
}
}
else if (input == 113 || input == 81) //quit
{
last = input;
printf("\nAre you sure you would like to quit? (y/n)\n");
}
else //they entered something weird
{
if ((last == 81 || last == 113) && (input == 89 || input == 121)) //if last key was qQ and this is yY, quit
{
printf("\nQuitting game...\n");
exit(0);
}
printBoard(board);
printf("Type in the letter of the space you want to play in.\nIt must be a lowercase letter between 'a' and 'i'.\n------\nPlayer %c, please try again:",
player);
}
}
}
}
/*------------Checks whether a win has occurred------------*/
/*
Input: Current board state (see printBoard above, input is identical)
Output:
- If someone won, the int of the char representing that player. Must be 88 (X) or 79 (O).
- If the board is full but no win happened (aka a tie), return 1.
- If no win yet, return 0.
*/
int checkGame(char *board)
{
int tie = 0;
for (int i = 0; i <= strlen(board); i ++)
{
//case: horizontal win
if (i % 3 == 0 && board[i] == board[i + 1] && board[i] == board[i + 2])
{
return (int) board[i];
}
//case: vertical win
else if (i <= 2 && board[i] == board[i + 3] && board[i] == board[i + 6])
{
return (int) board[i];
}
//case: diagonal win
if (i == 0 || i == 2)
{
int add;
if (i == 0)
{
add = 4;
}
else if (i == 2)
{
add = 2;
}
else //should never happen
{
printf("\nERROR in Board Check Function!!!\n");
return 0;
}
if (board[i] == board[i + add] && board[i] == board[i + (2 * add)])
{
return (int) board[i];
}
}
//counting filled spaces; if all spaces are filled, game's over (tie)
if (board[i] == 88 || board[i] == 79)
{
tie = tie + 1;
}
if (tie > 8)
{
return 1;
}
}
return 0;
}
int main(void)
{
//Declare variables & allocate memory
char playerChar = (char) 88; //current player
char *boardState = "abcdefghi"; //initial board state
int currMove = 0; //the space played in most recently (Current)
int game = 0; //boolean for whether the game is still running
char *oldBoard = malloc(10 * sizeof(char)); //old board state, just storage
if (oldBoard == NULL)
{
return 1;
}
char *newBoard = malloc(10 * sizeof(char)); //new board state (Current)
if (newBoard == NULL)
{
return 1;
}
//Assign correct initial values to old & new board states
strncpy(oldBoard, boardState, 11);
strncpy(newBoard, boardState, 11);
//The big loop of play. Continues as play occurs, until game ends.
while (game == 0)
{
printBoard(newBoard);
playerChar = changePlayer(playerChar);
currMove = promptMove(newBoard, playerChar);
//Copy new board state into newBoard variable
for (int i = 0, n = strlen(boardState); i < n; i++)
{
if (i == currMove)
{
newBoard[i] = playerChar;
}
else
{
newBoard[i] = oldBoard[i];
}
}
strncpy(oldBoard, newBoard, 11);
game = checkGame(newBoard);
}
printBoard(newBoard);
return gameOver(game);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment