Skip to content

Instantly share code, notes, and snippets.

@object71
Created March 19, 2023 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save object71/b77cffffff75d80132288616a9b8c61b to your computer and use it in GitHub Desktop.
Save object71/b77cffffff75d80132288616a9b8c61b to your computer and use it in GitHub Desktop.
TicTacToe example implementation in Plain C
#include <raylib.h>
#include <stdint.h>
const uint8_t kEmptyPlayer = 0;
typedef struct Board {
uint8_t positions[3][3];
} Board;
Board ConstructBoard() {
Board board;
for (uint8_t x = 0; x < 3; x += 1) {
for (uint8_t y = 0; y < 3; y += 1) {
board.positions[x][y] = kEmptyPlayer;
}
}
return board;
}
/**
* Checks whether a given player has won.
* @param board The current game board
* @param player The player we want to check for
* @return True if that player wins on this board
*/
bool CheckPlayerWins(Board board, uint8_t player) {
for (uint8_t i = 0; i < 3; i += 1) {
// horizontals
if (board.positions[i][0] == player
&& board.positions[i][1] == player
&& board.positions[i][2] == player) {
return true;
}
// verticals
if (board.positions[0][i] == player
&& board.positions[1][i] == player
&& board.positions[2][i] == player) {
return true;
}
}
// diagonal
if (board.positions[0][0] == player
&& board.positions[1][1] == player
&& board.positions[2][2] == player) {
return true;
}
// diagonal
if (board.positions[2][0] == player
&& board.positions[1][1] == player
&& board.positions[0][2] == player) {
return true;
}
return false;
}
/**
* @param board The current game board
* @return True if the board is full (meaning no 0 values on it)
*/
bool BoardIsFull(Board board) {
for (uint8_t x = 0; x < 3; x += 1) {
for (uint8_t y = 0; y < 3; y += 1) {
if (board.positions[x][y] == kEmptyPlayer) {
return false;
}
}
}
return true;
}
void InitializeWindow() {
const uint16_t kWindowWidth = 800;
const uint16_t kWindowHeight = 600;
InitWindow(kWindowWidth, kWindowHeight, "Tic-Tac-Toe");
SetTargetFPS(60);
}
uint8_t NextPlayer(uint8_t current_player) {
return current_player == 2 ? 1 : 2;
}
/**
* Draws the square on the screen as well as its current value.
* Will also check if the square has been clicked
*
* @return True if the square has been clicked and is active
*/
bool UpdateSquare(uint8_t x, uint8_t y, uint8_t current_value) {
const uint16_t square_size = 60;
const uint16_t offset_x = (GetScreenWidth() - square_size * 3) / 2;
const uint16_t offset_y = (GetScreenHeight() - square_size * 3) / 2;
uint16_t position_x = offset_x + x * square_size;
uint16_t position_y = offset_y + y * square_size;
DrawRectangleLines(position_x, position_y, square_size, square_size, BLACK);
if (current_value == 1) {
DrawText("x", position_x + 20, position_y + 10, square_size - 20, BLACK);
} else if (current_value == 2) {
DrawText("o", position_x + 20, position_y + 10, square_size - 20, BLACK);
} else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
Vector2 mouse_position = GetMousePosition();
if (mouse_position.x > position_x
&& mouse_position.x < position_x + square_size
&& mouse_position.y > position_y
&& mouse_position.y < position_y + square_size) {
return true;
}
}
return false;
}
/**
* Draws the board and if a square has been clicked
* the value will be updated for that square and the players will be switched.
*/
void UpdateBoard(Board *board, uint8_t *current_player) {
for (uint8_t x = 0; x < 3; x += 1) {
for (uint8_t y = 0; y < 3; y += 1) {
if (UpdateSquare(x, y, board->positions[x][y])) {
board->positions[x][y] = *current_player;
*current_player = NextPlayer(*current_player);
}
}
}
}
void Run() {
uint8_t current_player = NextPlayer(0);
Board board = ConstructBoard();
char *won_message = "";
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(RAYWHITE);
UpdateBoard(&board, &current_player);
if (CheckPlayerWins(board, 1)) {
board = ConstructBoard();
won_message = "Player 'x' won!";
}
if (CheckPlayerWins(board, 2)) {
board = ConstructBoard();
won_message = "Player 'o' won!";
}
if (BoardIsFull(board)) {
board = ConstructBoard();
won_message = "Game was a draw!";
}
DrawText(TextFormat("Current Player %c", current_player == 1 ? 'x' : 'o'), 25, 10, 40, BLACK);
DrawText(won_message, 25, 60, 40, BLACK);
EndDrawing();
}
}
int main() {
InitializeWindow();
Run();
CloseWindow();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment