Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdbool.h>
- #include <SDL2/SDL.h>
- #include <SDL2/SDL2_gfxPrimitives.h>
- #define N 3
- #define WIN_WIDTH 640
- #define WIN_HEIGHT 480
- #define CELL_WIDTH (WIN_WIDTH / N)
- #define CELL_HEIGHT (WIN_HEIGHT / N)
- typedef enum { ST_RUNNING, ST_X_WON, ST_O_WON, ST_DRAW, ST_QUIT } state_T;
- typedef struct {
- char board[N * N];
- char player;
- state_T state;
- } Game;
- static const SDL_Color X_COLOR = { .r = 255, .g = 0, .b = 255 },
- O_COLOR = { .r = 50, .g = 100, .b = 255 },
- DRAW_COLOR = { .r = 100, .g = 100, .b = 100 },
- GRID_COLOR = { .r = 255, .g = 255, .b = 255 };
- void render_grid(SDL_Renderer *ren, const SDL_Color color) {
- SDL_SetRenderDrawColor(ren, color.r, color.g, color.b, 255);
- for (int i = 1; i < N; ++i) {
- SDL_RenderDrawLine(ren, i * CELL_WIDTH, 0, i * CELL_WIDTH, WIN_HEIGHT);
- SDL_RenderDrawLine(ren, 0, i * CELL_HEIGHT, WIN_WIDTH, i * CELL_HEIGHT);
- }
- }
- void render_player(SDL_Renderer *ren, const char player, int row, int col, const SDL_Color color) {
- const float HALF_BOX_SIDE = fmin(CELL_WIDTH, CELL_HEIGHT) * .25,
- CENTER_X = CELL_WIDTH * .5 + col * CELL_WIDTH,
- CENTER_Y = CELL_HEIGHT * .5 + row * CELL_HEIGHT;
- if (player == 'X') {
- thickLineRGBA(ren,
- CENTER_X - HALF_BOX_SIDE,
- CENTER_Y - HALF_BOX_SIDE,
- CENTER_X + HALF_BOX_SIDE,
- CENTER_Y + HALF_BOX_SIDE, 10, color.r, color.g, color.b, 255);
- thickLineRGBA(ren,
- CENTER_X + HALF_BOX_SIDE,
- CENTER_Y - HALF_BOX_SIDE,
- CENTER_X - HALF_BOX_SIDE,
- CENTER_Y + HALF_BOX_SIDE, 10, color.r, color.g, color.b, 255);
- } else if (player == 'O') {
- filledCircleRGBA(ren, CENTER_X, CENTER_Y, HALF_BOX_SIDE + 5, color.r, color.g, color.b, 255);
- filledCircleRGBA(ren, CENTER_X, CENTER_Y, HALF_BOX_SIDE - 5, 0, 0, 0, 255);
- }
- }
- void render_board(SDL_Renderer *ren, const char *board, const SDL_Color x_col, const SDL_Color o_col) {
- for (int y = 0; y < N; ++y) {
- for (int x = 0; x < N; ++x) {
- render_player(ren, board[x * N + y], y, x, board[x * N + y] == 'X' ? x_col : o_col);
- }
- }
- }
- void render_game_over(SDL_Renderer *ren, const Game *game, const SDL_Color color) {
- render_grid(ren, color);
- render_board(ren, game->board, color, color);
- }
- void render_running(SDL_Renderer *ren, const Game *game) {
- render_grid(ren, GRID_COLOR);
- render_board(ren, game->board, X_COLOR, O_COLOR);
- }
- void render_game(SDL_Renderer *ren, const Game *game) {
- switch (game->state) {
- case ST_RUNNING:
- render_running(ren, game);
- break;
- case ST_X_WON:
- render_game_over(ren, game, X_COLOR);
- break;
- case ST_O_WON:
- render_game_over(ren, game, O_COLOR);
- break;
- case ST_DRAW:
- render_game_over(ren, game, DRAW_COLOR);
- break;
- default:
- break;
- }
- }
- int cell_count(const char *board, char cell) {
- int n = 0;
- for (int i = 0; i < N * N; ++i) {
- if (board[i] == cell) {
- ++n;
- }
- }
- return n;
- }
- bool won(Game *game, char player) {
- int nrow = 0, ncol = 0, ndiag1 = 0, ndiag2 = 0;
- for (int y = 0; y < N; ++y) {
- for (int x = 0; x < N; ++x) {
- if (game->board[y * N + x] == player) {
- ++nrow;
- }
- if (game->board[x * N + y] == player) {
- ++ncol;
- }
- }
- if (nrow == N || ncol == N) {
- return true;
- }
- nrow = ncol = 0;
- if (game->board[y * N + y] == player) {
- ++ndiag1;
- }
- if (game->board[y * N + N - y - 1] == player) {
- ++ndiag2;
- }
- }
- return ndiag1 == N || ndiag2 == N;
- }
- void test_game_over(Game *game) {
- if (won(game, 'X')) {
- game->state = ST_X_WON;
- } else if (won(game, 'O')) {
- game->state = ST_O_WON;
- } else if (cell_count(game->board, 0) == 0) {
- game->state = ST_DRAW;
- }
- }
- void reset_game(Game *game) {
- game->player = 'X';
- game->state = ST_RUNNING;
- memset(game->board, 0, sizeof(game->board));
- }
- void player_turn(Game *game, int row, int col) {
- if (!game->board[row * N + col]) {
- game->board[row * N + col] = game->player;
- game->player = game->player == 'X' ? 'O' : 'X'; // switch players
- test_game_over(game);
- }
- }
- void cell_put(Game *game, int row, int col) {
- if (game->state == ST_RUNNING) {
- player_turn(game, row, col);
- } else {
- reset_game(game);
- }
- }
- int main(void) {
- if (SDL_Init(SDL_INIT_VIDEO)) {
- fprintf(stderr, "couldn't initialize SDL: %s\n", SDL_GetError());
- return 1;
- }
- SDL_Window *win = SDL_CreateWindow("Tic Tac Toe",
- SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- WIN_WIDTH, WIN_HEIGHT,
- SDL_WINDOW_SHOWN);
- if (!win) {
- fprintf(stderr, "couldn't create window: %s\n", SDL_GetError());
- return 1;
- }
- SDL_Renderer *renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- if (!renderer) {
- fprintf(stderr, "couldn't create renderer for window: %s\n", SDL_GetError());
- return 1;
- }
- Game game = { .board = { 0 }, .player = 'X', .state = ST_RUNNING };
- SDL_Event e;
- while (game.state != ST_QUIT) {
- while (SDL_PollEvent(&e)) {
- switch (e.type) {
- case SDL_QUIT:
- game.state = ST_QUIT;
- break;
- case SDL_MOUSEBUTTONDOWN:
- cell_put(&game, e.button.x / CELL_WIDTH, e.button.y / CELL_HEIGHT);
- break;
- default:
- break;
- }
- }
- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
- SDL_RenderClear(renderer);
- render_game(renderer, &game);
- SDL_RenderPresent(renderer);
- }
- SDL_DestroyWindow(win);
- SDL_Quit();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement