diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 7d8d2c7..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/GEMINI.md b/GEMINI.md deleted file mode 100644 index 6e04356..0000000 --- a/GEMINI.md +++ /dev/null @@ -1,39 +0,0 @@ -# Gemini Code Assistant Context - -This document provides context for the Gemini code assistant to understand and assist with the development of this project. - -## Project Overview - -This is a simple, terminal-based Tic-Tac-Toe game written in C++. It uses the `ncurses` library to create the game interface in the terminal. The game is played on a 5x5 grid. - -The project is structured into three main components: - -* **`Engine`**: The main game engine that manages the game loop, player turns, and input processing. -* **`Window`**: Handles the display of the game board in the terminal. -* **`Player`**: Represents a player in the game. - -## Building and Running - -The project uses CMake for building. - -**To build the project:** - -```bash -mkdir build -cd build -cmake .. -make -``` - -**To run the game:** - -```bash -./tic_tac_toe -``` - -## Development Conventions - -* **Language**: C++23 -* **Build System**: CMake -* **Code Style**: The code follows a consistent style with the use of header guards, and clear naming conventions. -* **Testing**: There are no tests in the project. diff --git a/include/elements.hpp b/include/elements.hpp index 61c1ef2..af0301d 100644 --- a/include/elements.hpp +++ b/include/elements.hpp @@ -6,10 +6,14 @@ class Window; struct Player { - Player(char symbol, int id) : m_symbol(symbol), m_id(id) {}; - char m_symbol; - int m_id; - bool on_line(); + Player(char id) : id(id) {}; + char id; +}; + +struct vec2 { + vec2(int x, int y) : x(x), y(y) {} + int x; + int y; }; class Engine { @@ -24,11 +28,12 @@ private: Player player1; Player player2; Player *temp; - GameState() : player1('x', 1), player2('o', 2), temp { &player1 } {}; + GameState() : player1('x'), player2('o'), temp { &player1 } {}; } state; void get_current_player(); bool process_input(); bool exit_code(); + bool check_line(char id); }; #endif diff --git a/src/elements.cpp b/src/elements.cpp index 2838ce3..1f597be 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -22,20 +22,20 @@ Engine::~Engine() { void Engine::run() { while (exit_code() && process_input()) { win->draw_display(); - std::cout << "Current Player: " << state.temp->m_symbol << "\n"; + std::cout << "Current Player: " << state.temp->id << "\n"; std::this_thread::sleep_for(std::chrono::milliseconds((int) (150))); // 1000 / fps; 200ms = 5fps } } bool Engine::exit_code() { int index = 0; - // if(state.player1.on_line()) { - // std::cout << "Game Over! Player 1 wins!" << std::endl; - // return false; - // } else if(state.player2.on_line()) { - // std::cout << "Game Over! Player 2 wins!" << std::endl; - // return false; - // } + if(check_line(state.player1.id)) { + std::cout << "Game Over! Player 1 wins!" << std::endl; + return false; + } else if(check_line(state.player2.id)) { + std::cout << "Game Over! Player 2 wins!" << std::endl; + return false; + } for(auto &row : win->view) { for(auto val : row) { if(val != ' ') index++; @@ -53,31 +53,31 @@ bool Engine::process_input() { while((ch = getch()) != ERR) { if(ch == 113) { return false; } if(ch == 49) { - win->view[0][0] = state.temp->m_symbol; + win->view[0][0] = state.temp->id; get_current_player(); } if(ch == 50) { - win->view[0][2] = state.temp->m_symbol; + win->view[0][2] = state.temp->id; get_current_player(); } if(ch == 51) { - win->view[0][4] = state.temp->m_symbol; + win->view[0][4] = state.temp->id; get_current_player(); } if(ch == 52) { - win->view[2][0] = state.temp->m_symbol; + win->view[2][0] = state.temp->id; get_current_player(); } if(ch == 53) { - win->view[2][2] = state.temp->m_symbol; + win->view[2][2] = state.temp->id; get_current_player(); } if(ch == 54) { - win->view[2][4] = state.temp->m_symbol; + win->view[2][4] = state.temp->id; get_current_player(); } if(ch == 55) { - win->view[4][0] = state.temp->m_symbol; + win->view[4][0] = state.temp->id; get_current_player(); } if(ch == 56) { - win->view[4][2] = state.temp->m_symbol; + win->view[4][2] = state.temp->id; get_current_player(); } if(ch == 57) { - win->view[4][4] = state.temp->m_symbol; + win->view[4][4] = state.temp->id; get_current_player(); } } @@ -85,34 +85,25 @@ bool Engine::process_input() { } void Engine::get_current_player() { - if(state.temp->m_symbol == 'x') { state.temp = &state.player2; } - else if(state.temp->m_symbol == 'o') { state.temp = &state.player1; } + if(state.temp->id == 'x') { state.temp = &state.player2; } + else if(state.temp->id == 'o') { state.temp = &state.player1; } } -// bool Player::on_line(vec2** buffer) { -// for(int i = 0; i <= 6; i += 3) { -// if(buffer[i]->m_symbol == buffer[i+1]->m_symbol && buffer[i+1]->m_symbol == buffer[i+2]->m_symbol) { -// if(buffer[i]->m_symbol == m_symbol) { -// return true; -// } -// } -// } -// for(int i = 0; i < 3; i++) { -// if(buffer[i]->m_symbol == buffer[i+3]->m_symbol && buffer[i+3]->m_symbol == buffer[i+6]->m_symbol) { -// if(buffer[i]->m_symbol == m_symbol) { -// return true; -// } -// } -// } -// if(buffer[0]->m_symbol == buffer[4]->m_symbol && buffer[4]->m_symbol == buffer[8]->m_symbol) { -// if(buffer[0]->m_symbol == m_symbol) { -// return true; -// } -// } -// if(buffer[2]->m_symbol == buffer[4]->m_symbol && buffer[4]->m_symbol == buffer[6]->m_symbol) { -// if(buffer[2]->m_symbol == m_symbol) { -// return true; -// } -// } -// return false; -// } +bool Engine::check_line(char id) { + for(int i : std::ranges::views::iota(0, COL)) { + if(win->view[0][i] == id && win->view[2][i] == id && win->view[4][i] == id) { + return true; + } + } + for(int i : std::ranges::views::iota(0, ROW)) { + if(win->view[i][0] == id && win->view[i][2] == id && win->view[i][4] == id) { + return true; + } + } + auto same_symbol = [&](vec2 a, vec2 b) { + return win->view[a.y][a.x] == id && + win->view[2][2] == id && + win->view[b.y][b.x] == id; + }; + return same_symbol({ 0, 0 }, { 4, 4 }) || same_symbol({ 4, 0 }, { 0, 4 }); +}