Skip to content

Instantly share code, notes, and snippets.

@Lain62
Last active August 9, 2024 07:32
Show Gist options
  • Save Lain62/bd932f13dc7ac6f5acf605e064322eca to your computer and use it in GitHub Desktop.
Save Lain62/bd932f13dc7ac6f5acf605e064322eca to your computer and use it in GitHub Desktop.
This is actually overengineered as hell istg and its AWFUL DONT USE AS REFERENCE PLEASE
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
int WinningCondition[8][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 4, 7}, {2, 5, 8}, {3, 6, 9}, {1, 5, 9}, {7, 5, 3}};
typedef enum
{
Xmarker,
Omarker
} Marker;
typedef enum
{
BlankBoardTile = 0,
HoriBoardTile = 1,
VertiBoardTile = 2,
PlayerBoardTile = 3,
InputBoardTile = 4
} MainboardRender;
// 7 x 7 board that looks like this
// - - -
// | | | |
// 1 2 3
// | | | |
// 4 5 6
// | | | |
// 7 8 9
MainboardRender MainBoard[49] = {
0, 1, 0, 1, 0, 1, 0, 2, 3, 2, 3, 2, 3, 2, 0, 4, 0, 4, 0, 4, 0, 2, 3, 2, 3,
2, 3, 2, 0, 4, 0, 4, 0, 4, 0, 2, 3, 2, 3, 2, 3, 2, 0, 4, 0, 4, 0, 4, 0};
typedef enum
{
BlankTile,
UserTile,
ComputerTile
} TileState;
typedef enum
{
UserTurn,
ComputerTurn
} CurrentTurn;
typedef struct Player
{
Marker marker;
int tileBank[9];
} Player;
char parseMarker(Marker marker);
Marker getUserMarker();
Marker getComputerMarker(Marker userMarker);
void renderMainBoard(TileState gameBoard[9], Marker userMarker,
Marker computerMarker);
// im not sure if this is efficient but im bruteforcing it
// 0 == no win
// 1 == win found
int checkIfTileBankWin(int tileBank[]);
void placeMarker(TileState gameBoard[], int pos, CurrentTurn turn);
void playRound(TileState gameBoard[], Player *user, Player *computer, CurrentTurn firstTurn, int *turnNumber);
int getComputerInput(TileState gameBoard[]);
int getUserInput(TileState gameBoard[]);
int main()
{
srand(time(NULL));
printf("Welcome to tictactoe!\n");
TileState gameBoard[9] = {BlankTile};
Player userPlayer = {getUserMarker(), {0}};
Player computerPlayer = {getComputerMarker(userPlayer.marker), {0}};
CurrentTurn firstTurn = UserTurn;
int turnNumber = 0;
// renderMainBoard(gameBoard, userPlayer.marker, computerPlayer.marker);
if (userPlayer.marker == Xmarker)
firstTurn = UserTurn;
else
firstTurn = ComputerTurn;
renderMainBoard(gameBoard, userPlayer.marker, computerPlayer.marker);
while (turnNumber < 9)
{
printf("turn %d\n", turnNumber);
playRound(gameBoard, &userPlayer, &computerPlayer, firstTurn, &turnNumber);
renderMainBoard(gameBoard, userPlayer.marker, computerPlayer.marker);
}
if (turnNumber == 9)
{
printf("Its a draw!");
return 0;
}
}
int getComputerInput(TileState gameBoard[])
{
int i = (rand() % 9) + 1;
while (gameBoard[i - 1] != BlankTile)
{
i = (rand() % 9) + 1;
}
return i;
}
int getUserInput(TileState gameBoard[])
{
int i = 0;
printf("Your turn!\n");
while (i <= 0 || i > 9 || gameBoard[i - 1] != BlankTile)
{
printf("Please choose a number between 1-9: ");
scanf(" %d", &i);
}
return i;
}
void playRound(TileState gameBoard[], Player *user, Player *computer, CurrentTurn firstTurn, int *turnNumber)
{
if (firstTurn == UserTurn)
{
int i = getUserInput(gameBoard);
int j = 0;
while (user->tileBank[j] != 0)
{
j++;
}
user->tileBank[j] = i;
placeMarker(gameBoard, i - 1, UserTurn);
int k = checkIfTileBankWin(user->tileBank);
if (k == 1)
{
renderMainBoard(gameBoard, user->marker, computer->marker);
printf("You win!\n");
exit(EXIT_SUCCESS);
}
*turnNumber = *turnNumber + 1;
if (*turnNumber == 9)
{
return;
}
int a = getComputerInput(gameBoard);
int b = 0;
while (computer->tileBank[b] != 0)
{
b++;
}
computer->tileBank[b] = a;
placeMarker(gameBoard, a - 1, ComputerTurn);
int c = checkIfTileBankWin(user->tileBank);
if (c == 1)
{
renderMainBoard(gameBoard, user->marker, computer->marker);
printf("You Lost!\n");
exit(EXIT_SUCCESS);
}
*turnNumber = *turnNumber + 1;
if (*turnNumber == 9)
{
return;
}
}
else if (firstTurn == ComputerTurn)
{
int a = getComputerInput(gameBoard);
int b = 0;
while (computer->tileBank[b] != 0)
{
b++;
}
computer->tileBank[b] = a;
placeMarker(gameBoard, a - 1, ComputerTurn);
int c = checkIfTileBankWin(computer->tileBank);
if (c == 1)
{
renderMainBoard(gameBoard, user->marker, computer->marker);
printf("You Lost!\n");
exit(EXIT_SUCCESS);
}
renderMainBoard(gameBoard, user->marker, computer->marker);
*turnNumber = *turnNumber + 1;
if (*turnNumber == 9)
{
return;
}
int i = getUserInput(gameBoard);
int j = 0;
while (user->tileBank[j] != 0)
{
j++;
}
user->tileBank[j] = i;
placeMarker(gameBoard, i - 1, UserTurn);
int k = checkIfTileBankWin(user->tileBank);
if (k == 1)
{
renderMainBoard(gameBoard, user->marker, computer->marker);
printf("You win!\n");
exit(EXIT_SUCCESS);
}
*turnNumber = *turnNumber + 1;
if (*turnNumber == 9)
{
return;
}
}
}
void placeMarker(TileState gameBoard[], int pos, CurrentTurn turn)
{
if (turn == UserTurn)
{
gameBoard[pos] = UserTile;
}
else if (turn == ComputerTurn)
{
gameBoard[pos] = ComputerTile;
}
else
{
fprintf(stderr, "Error placing marker");
exit(EXIT_FAILURE);
}
}
char parseMarker(Marker marker)
{
switch (marker)
{
case Xmarker:
return 'X';
case Omarker:
return 'O';
default:
fprintf(stderr, "Error getting marker");
exit(EXIT_FAILURE);
}
}
Marker getUserMarker()
{
int i = 0;
while (i <= 0 || i > 2)
{
printf("Would you like to go first or second?\n");
printf("answer 1 / 2\n");
scanf(" %d", &i);
};
if (i == 1)
{
return Xmarker;
}
else if (i == 2)
{
return Omarker;
}
else
{
fprintf(stderr, "Error getting user turn marker");
exit(EXIT_FAILURE);
}
};
Marker getComputerMarker(Marker userMarker)
{
if (userMarker == Xmarker)
{
return Omarker;
}
else if (userMarker == Omarker)
{
return Xmarker;
}
else
{
fprintf(stderr, "Error getting computer turn marker");
exit(EXIT_FAILURE);
}
}
void renderMainBoard(TileState gameBoard[9], Marker userMarker,
Marker computerMarker)
{
int currentInput = 1;
int currentMainBoardIndex = 0;
int currentGameBoardIndex = 0;
printf("================\n");
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 7; j++)
{
switch (MainBoard[currentMainBoardIndex])
{
case BlankBoardTile:
printf(" ");
break;
case HoriBoardTile:
printf("-");
break;
case VertiBoardTile:
printf("|");
break;
case PlayerBoardTile:
switch (gameBoard[currentGameBoardIndex])
{
case BlankTile:
printf(" ");
break;
case UserTile:
printf("%c", parseMarker(userMarker));
break;
case ComputerTile:
printf("%c", parseMarker(computerMarker));
break;
default:
fprintf(stderr, "Error Rendering main board has gone wrong");
exit(EXIT_FAILURE);
break;
}
currentGameBoardIndex++;
break;
case InputBoardTile:
printf("%d", currentInput);
currentInput++;
break;
default:
fprintf(stderr, "Error Rendering main board has gone wrong");
exit(EXIT_FAILURE);
break;
}
currentMainBoardIndex++;
}
printf("\n");
}
printf("================\n");
}
int checkIfTileBankWin(int tileBank[])
{
if (tileBank[0] == 0)
{
return 0;
}
if (tileBank[1] == 0)
{
return 0;
}
if (tileBank[2] == 0)
{
return 0;
}
for (int i = 0; i < 8; i++)
{
int wins = 0;
for (int j = 0; j < 3; j++)
{
int l = 0;
while (tileBank[l] != 0)
{
if (tileBank[l] == WinningCondition[i][j])
{
wins++;
break;
}
l++;
}
}
if (wins == 3)
{
return 1;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment