From ce3a27b5807170adbac105a21bfc2282200501cb Mon Sep 17 00:00:00 2001 From: harshwadhwani-10 Date: Tue, 23 Sep 2025 20:38:54 +0530 Subject: [PATCH] Refactor codebase into classes --- main.cpp | 15 ++- snake | Bin 0 -> 91992 bytes snake.h | 244 +++++++++++++++++++++++++++++++++---------------- snake_test.cpp | 41 +++++---- 4 files changed, 203 insertions(+), 97 deletions(-) create mode 100644 snake diff --git a/main.cpp b/main.cpp index ef65093..c67e527 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,18 @@ +#include #include "snake.h" int main(int argc, char *argv[]) { - thread input_thread(input_handler); - thread game_thread(game_play); + int size = 8; + if (argc > 1) { + int requested = atoi(argv[1]); + if (requested == 7 || requested == 8) { + size = requested; + } + } + Game game(size); + std::thread input_thread(&Game::runInput, &game); + std::thread game_thread(&Game::runLoop, &game); input_thread.join(); game_thread.join(); -return 0; + return 0; } \ No newline at end of file diff --git a/snake b/snake new file mode 100644 index 0000000000000000000000000000000000000000..f38cafc1b6f29b7b30de55bce90350f9c3c41f7d GIT binary patch literal 91992 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 literal 0 HcmV?d00001 diff --git a/snake.h b/snake.h index ebe1192..009fa7e 100644 --- a/snake.h +++ b/snake.h @@ -1,101 +1,189 @@ +#ifndef SNAKE_H +#define SNAKE_H + #include #include #include #include -#include -#include -#include // for system clear +#include #include #include #include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif + using namespace std; -using std::chrono::system_clock; +using namespace std::chrono_literals; using namespace std::this_thread; -char direction='r'; - - -void input_handler(){ - // change terminal settings - struct termios oldt, newt; - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - // turn off canonical mode and echo - newt.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}, {'q', 'q'}}; - while (true) { - char input = getchar(); - if (keymap.find(input) != keymap.end()) { - // This now correctly modifies the single, shared 'direction' variable - direction = keymap[input]; - }else if (input == 'q'){ - exit(0); + +class Snake { +public: + explicit Snake(int gridSize) + : gridSize_(gridSize) { + body_.push_back(make_pair(0, 0)); + } + + static pair computeNextHead(const pair& current, char direction, int gridSize) { + pair next = current; + if (direction == 'r') { + next = make_pair(current.first, (current.second + 1) % gridSize); + } else if (direction == 'l') { + next = make_pair(current.first, current.second == 0 ? gridSize - 1 : current.second - 1); + } else if (direction == 'd') { + next = make_pair((current.first + 1) % gridSize, current.second); + } else if (direction == 'u') { + next = make_pair(current.first == 0 ? gridSize - 1 : current.first - 1, current.second); } - // You could add an exit condition here, e.g., if (input == 'q') break; + return next; + } + + const deque>& body() const { return body_; } + pair head() const { return body_.back(); } + + bool contains(const pair& cell) const { + return find(body_.begin(), body_.end(), cell) != body_.end(); + } + + bool willCollideWithSelf(const pair& nextHead) const { + return contains(nextHead); + } + + void growTo(const pair& nextHead) { + body_.push_back(nextHead); + } + + void moveTo(const pair& nextHead) { + body_.push_back(nextHead); + body_.pop_front(); } - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); -} +private: + int gridSize_; + deque> body_; +}; -void render_game(int size, deque> &snake, pair food){ - for(size_t i=0;i>& snake, const pair& food) { + cout << "Snake Game" << endl; + for (size_t i = 0; i < static_cast(size); i++) { + for (size_t j = 0; j < static_cast(size); j++) { + if (static_cast(i) == food.first && static_cast(j) == food.second) { + cout << "🍎"; + } else if (find(snake.begin(), snake.end(), make_pair(int(i), int(j))) != snake.end()) { + cout << "🐍"; + } else { + cout << "⬜"; + } } + cout << endl; + } } - cout << endl; -} -} +}; + +class InputHandler { +public: + InputHandler() : direction_('r') {} + + char direction() const { return direction_.load(); } -pair get_next_head(pair current, char direction){ - pair next; - if(direction =='r'){ - next = make_pair(current.first,(current.second+1) % 10); - }else if (direction=='l') - { - next = make_pair(current.first, current.second==0?9:current.second-1); - }else if(direction =='d'){ - next = make_pair((current.first+1)%10,current.second); - }else if (direction=='u'){ - next = make_pair(current.first==0?9:current.first-1, current.second); + void run() { +#ifdef _WIN32 + map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}, {'q', 'q'}}; + for (;;) { + if (_kbhit()) { + char input = _getch(); + if (keymap.find(input) != keymap.end()) { + direction_.store(keymap[input]); + } else if (input == 'q') { + system("cls"); + exit(0); + } + } + sleep_for(10ms); } - return next; - -} +#else + struct termios oldt, newt; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}, {'q', 'q'}}; + while (true) { + char input = getchar(); + if (keymap.find(input) != keymap.end()) { + direction_.store(keymap[input]); + } else if (input == 'q') { + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + exit(0); + } + } + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +#endif + } + +private: + atomic direction_; +}; + +class Game { +public: + Game(int size = 8) + : size_(size), snake_(size_), input_(), renderer_(), food_(make_pair(rand() % size_, rand() % size_)) {} + void runInput() { input_.run(); } + void runLoop() { +#ifdef _WIN32 + system("cls"); +#else + system("clear"); +#endif + pair head = make_pair(0, 1); + for (;;) { + cout << "\033[H"; + char dir = input_.direction(); + head = Snake::computeNextHead(head, dir, size_); + + if (snake_.willCollideWithSelf(head)) { +#ifdef _WIN32 + system("cls"); +#else + system("clear"); +#endif + cout << "Game Over" << endl; + exit(0); + } else if (head.first == food_.first && head.second == food_.second) { + food_ = make_pair(rand() % size_, rand() % size_); + snake_.growTo(head); + } else { + snake_.moveTo(head); + } -void game_play(){ - system("clear"); - deque> snake; - snake.push_back(make_pair(0,0)); - - pair food = make_pair(rand() % 10, rand() % 10); - for(pair head=make_pair(0,1);; head = get_next_head(head, direction)){ - // send the cursor to the top - cout << "\033[H"; - // check self collision - if (find(snake.begin(), snake.end(), head) != snake.end()) { - system("clear"); - cout << "Game Over" << endl; - exit(0); - }else if (head.first == food.first && head.second == food.second) { - // grow snake - food = make_pair(rand() % 10, rand() % 10); - snake.push_back(head); - }else{ - // move snake - snake.push_back(head); - snake.pop_front(); + renderer_.render(size_, snake_.body(), food_); + cout << "length of snake: " << snake_.body().size() << endl; + sleep_for(500ms); } - render_game(10, snake, food); - cout << "length of snake: " << snake.size() << endl; - - sleep_for(500ms); } + +private: + int size_; + Snake snake_; + InputHandler input_; + Renderer renderer_; + pair food_; +}; + +inline pair get_next_head(pair current, char direction){ + return Snake::computeNextHead(current, direction, 10); } + +#endif // SNAKE_H + diff --git a/snake_test.cpp b/snake_test.cpp index 42f8561..15138a4 100644 --- a/snake_test.cpp +++ b/snake_test.cpp @@ -1,29 +1,38 @@ -#include + #include #include "snake.h" -TEST(SnakeBehaviour, NextHeadRight) { - pair current = make_pair(rand() % 10, rand() % 10); - EXPECT_EQ(get_next_head(current, 'r'),make_pair(current.first,current.second+1)); - +TEST(SnakeBehaviour, NextHeadRightWraps) { + pair current = make_pair(3, 9); + EXPECT_EQ(Snake::computeNextHead(current, 'r', 10), make_pair(3, 0)); } -TEST(SnakeBehaviour, NextHeadLeft) { - pair current = make_pair(rand() % 10, rand() % 10); - EXPECT_EQ(get_next_head(current, 'l'),make_pair(current.first,current.second-1)); - +TEST(SnakeBehaviour, NextHeadLeftWraps) { + pair current = make_pair(4, 0); + EXPECT_EQ(Snake::computeNextHead(current, 'l', 10), make_pair(4, 9)); } -TEST(SnakeBehaviour, NextHeadUp) { - pair current = make_pair(rand() % 10, rand() % 10); - EXPECT_EQ(get_next_head(current, 'u'),make_pair(current.first-1,current.second)); +TEST(SnakeBehaviour, NextHeadUpWraps) { + pair current = make_pair(0, 7); + EXPECT_EQ(Snake::computeNextHead(current, 'u', 10), make_pair(9, 7)); } -TEST(SnakeBehaviour, NextHeadDown) { - pair current = make_pair(rand() % 10, rand() % 10); - EXPECT_EQ(get_next_head(current, 'd'),make_pair(current.first+1,current.second)); - +TEST(SnakeBehaviour, NextHeadDownWraps) { + pair current = make_pair(9, 2); + EXPECT_EQ(Snake::computeNextHead(current, 'd', 10), make_pair(0, 2)); +} + +TEST(SnakeClass, GrowAndMoveBehaviour) { + Snake s(10); + // Start with one segment at (0,0); grow to (0,1), then move to (0,2) + pair next = Snake::computeNextHead(make_pair(0,0), 'r', 10); + s.growTo(next); + EXPECT_EQ(s.body().size(), 2u); + next = Snake::computeNextHead(s.head(), 'r', 10); + s.moveTo(next); + EXPECT_EQ(s.body().size(), 2u); + EXPECT_EQ(s.head(), make_pair(0,2)); }