From 402fc0061f7ba3d3789c159681d30e45d7d79749 Mon Sep 17 00:00:00 2001 From: Parth Date: Wed, 17 Sep 2025 23:51:02 +0530 Subject: [PATCH 1/2] All Issues solved --- main.cpp | 15 ++- scores.txt | 3 + snake | Bin 0 -> 126024 bytes snake.h | 299 +++++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 260 insertions(+), 57 deletions(-) create mode 100644 scores.txt create mode 100644 snake diff --git a/main.cpp b/main.cpp index ef65093..8fc1ca1 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,18 @@ #include "snake.h" +#include + int main(int argc, char *argv[]) { + srand((unsigned)time(nullptr));// seed RNG for food placement + thread input_thread(input_handler); - thread game_thread(game_play); + thread game_thread(game_play); + input_thread.join(); game_thread.join(); -return 0; -} \ No newline at end of file + return 0; +} + + + +// https://github.com/gamekeepers/snake-cli/pull/28 \ No newline at end of file diff --git a/scores.txt b/scores.txt new file mode 100644 index 0000000..4ddd383 --- /dev/null +++ b/scores.txt @@ -0,0 +1,3 @@ +2 +2 +7 diff --git a/snake b/snake new file mode 100644 index 0000000000000000000000000000000000000000..93d3f9c343454b85ca83743082072ecd7bdd2069 GIT binary patch literal 126024 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 #include #include -#include // for system clear +#include #include #include #include +#include +#include using namespace std; using std::chrono::system_clock; -using namespace std::this_thread; -char direction='r'; +constexpr int BOARD_SIZE = 10; // Board size -void input_handler(){ - // change terminal settings +char direction = 'r'; + +// Input handler (runs in a separate thread) +void input_handler() +{ struct termios oldt, newt; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; - // turn off canonical mode and echo - newt.c_lflag &= ~(ICANON | ECHO); + newt.c_lflag &= ~(ICANON | ECHO); // turn off canonical mode and echo tcsetattr(STDIN_FILENO, TCSANOW, &newt); + map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}, {'q', 'q'}}; - while (true) { + while (true) + { char input = getchar(); - if (keymap.find(input) != keymap.end()) { - // This now correctly modifies the single, shared 'direction' variable + if (keymap.find(input) != keymap.end()) + { direction = keymap[input]; - }else if (input == 'q'){ + } + else if (input == 'q') + { + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); exit(0); } - // You could add an exit condition here, e.g., if (input == 'q') break; + else if (input == 'p') + { + if (direction != 'P') + direction = 'P'; // pause + else + direction = 'r'; // resume moving right or previous direction + } } tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } - -void render_game(int size, deque> &snake, pair food){ - for(size_t i=0;i> &snake, pair food, pair poison, int score) +{ + for (int i = 0; i < size; ++i) + { + for (int j = 0; j < size; ++j) + { + if (i == food.first && j == food.second) + { cout << "🍎"; - }else if (find(snake.begin(), snake.end(), make_pair(int(i), int(j))) != snake.end()) { + } + else if (i == poison.first && j == poison.second) + { + cout << "☠️"; + } + else if (find(snake.begin(), snake.end(), make_pair(i, j)) != snake.end()) + { cout << "🐍"; - }else{ + } + else + { cout << "⬜"; } + } + cout << '\n'; } - cout << endl; + cout << "Length: " << snake.size() << " Score: " << score << "\n"; } + +// Compute next head (wraps around) +pair get_next_head(pair current, char direction) +{ + pair next; + if (direction == 'r') + { + next = make_pair(current.first, (current.second + 1) % BOARD_SIZE); + } + else if (direction == 'l') + { + next = make_pair(current.first, current.second == 0 ? BOARD_SIZE - 1 : current.second - 1); + } + else if (direction == 'd') + { + next = make_pair((current.first + 1) % BOARD_SIZE, current.second); + } + else + { // 'u' + next = make_pair(current.first == 0 ? BOARD_SIZE - 1 : current.first - 1, current.second); + } + return next; } -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') +// Spawn food at a location not occupied by the snake +pair spawn_food(const deque> &snake) +{ + vector> freeCells; + for (int i = 0; i < BOARD_SIZE; ++i) { - 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); + for (int j = 0; j < BOARD_SIZE; ++j) + { + pair pos = make_pair(i, j); + if (find(snake.begin(), snake.end(), pos) == snake.end()) + { + freeCells.push_back(pos); + } } - return next; - + } + + if (freeCells.empty()) + return make_pair(-1, -1); // board full + + int idx = rand() % freeCells.size(); + return freeCells[idx]; +} +// ✅ Save score to file +void save_score(int score) +{ + ofstream file("scores.txt", ios::app); // append mode + if (file.is_open()) + { + file << score << "\n"; + file.close(); + } } +// ✅ Load scores and return top 10 +vector load_top_scores() +{ + ifstream file("scores.txt"); + vector scores; + int s; + while (file >> s) + { + scores.push_back(s); + } + file.close(); + + // Sort descending + sort(scores.begin(), scores.end(), greater()); + + // Keep only top 10 + if (scores.size() > 10) + { + scores.resize(10); + } -void game_play(){ + return scores; +} + +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()) { + snake.push_back(make_pair(0, 0)); // starting segment + + pair food = spawn_food(snake); + pair poison = spawn_food(snake); // spawn initial poison + + int score = 0; + int level = 1; // starting level + int baseDelay = 500; // initial delay in ms + + while (true) + { + pair currentHead = snake.back(); + pair nextHead = get_next_head(currentHead, direction); + + cout << "\033[H"; // move cursor to top-left + + bool willGrow = (nextHead == food); + bool collision = false; + + // ✅ Pause logic + if (direction == 'P') + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + continue; // skip movement, freeze game + } + + if (willGrow) + { + if (find(snake.begin(), snake.end(), nextHead) != snake.end()) + collision = true; + } + else + { + auto itStart = snake.begin(); + if (!snake.empty()) + ++itStart; // skip tail + if (find(itStart, snake.end(), nextHead) != snake.end()) + collision = true; + } + + // Snake collides with itself + if (collision) + { system("clear"); - cout << "Game Over" << endl; + cout << "Game Over\n"; + cout << "Final Length: " << snake.size() << " Final Score: " << score << "\n"; + + save_score(score); + + cout << "\n=== Top 10 Scores ===\n"; + vector topScores = load_top_scores(); + for (int i = 0; i < topScores.size(); i++) + { + cout << (i + 1) << ". " << topScores[i] << "\n"; + } + + exit(0); + } + + // Snake eats poison + if (nextHead == poison) + { + system("clear"); + cout << "Snake ate poison ☠️ Game Over!\n"; + cout << "Final Length: " << snake.size() << " Final Score: " << score << "\n"; + + save_score(score); + + cout << "\n=== Top 10 Scores ===\n"; + vector topScores = load_top_scores(); + for (int i = 0; i < topScores.size(); i++) + { + cout << (i + 1) << ". " << topScores[i] << "\n"; + } + 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.push_back(nextHead); + + if (willGrow) + { + score += 1; + food = spawn_food(snake); + + // 🔹 Respawn poison every 3 points + if (score % 3 == 0) + { + poison = spawn_food(snake); + } + + if (food.first == -1) + { + system("clear"); + cout << "You Win! Final Length: " << snake.size() << " Final Score: " << score << "\n"; + + save_score(score); + + cout << "\n=== Top 10 Scores ===\n"; + vector topScores = load_top_scores(); + for (int i = 0; i < topScores.size(); i++) + { + cout << (i + 1) << ". " << topScores[i] << "\n"; + } + + exit(0); + } + } + else + { snake.pop_front(); } - render_game(10, snake, food); - cout << "length of snake: " << snake.size() << endl; - - sleep_for(500ms); + + // Level calculation: increase level every 5 points + level = (score / 5) + 1; + + // Render game (with poison + score) + render_game(BOARD_SIZE, snake, food, poison, score); + + cout << "Level: " << level << "\n"; + + // Dynamic speed: faster as level increases (min 50ms) + int delay_ms = max(50, baseDelay - (level - 1) * 50 - (int)snake.size() * 5); + std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms)); } -} +} \ No newline at end of file From 74c1947f8edce1c3cbc544db3f9e15605cebe47f Mon Sep 17 00:00:00 2001 From: Rajvi Date: Fri, 26 Sep 2025 18:14:00 +0530 Subject: [PATCH 2/2] Refactored Code --- main.cpp | 19 ++-- snake.h | 235 +++++++++++++++++++++++-------------------------- snake_test.cpp | 100 +++++++++++++++++---- 3 files changed, 202 insertions(+), 152 deletions(-) diff --git a/main.cpp b/main.cpp index 8fc1ca1..2eb9e28 100644 --- a/main.cpp +++ b/main.cpp @@ -1,18 +1,15 @@ -#include "snake.h" + +#include "snake.h" #include +#include -int main(int argc, char *argv[]) { - srand((unsigned)time(nullptr));// seed RNG for food placement +char direction = 'r'; +int main(int argc, char *argv[]) +{ thread input_thread(input_handler); - thread game_thread(game_play); - + game_play(); input_thread.join(); - game_thread.join(); return 0; -} - - - -// https://github.com/gamekeepers/snake-cli/pull/28 \ No newline at end of file +} \ No newline at end of file diff --git a/snake.h b/snake.h index cc511d3..61813ba 100644 --- a/snake.h +++ b/snake.h @@ -1,3 +1,8 @@ + + +#ifndef SNAKE_H +#define SNAKE_H + #include #include #include @@ -11,19 +16,56 @@ #include #include using namespace std; -using std::chrono::system_clock; -constexpr int BOARD_SIZE = 10; // Board size +constexpr int BOARD_SIZE = 10; +extern char direction; + +// ------------------ Snake Class ------------------ +class Snake +{ +private: + deque> body; + +public: + Snake() + { + body.push_back({0, 0}); // start at (0,0) + } -char direction = 'r'; + void grow(pair newHead) + { + body.push_back(newHead); + } + + void move(pair newHead) + { + body.push_back(newHead); + body.pop_front(); + } + + pair getHead() const + { + return body.back(); + } + + int getSize() const + { + return body.size(); + } -// Input handler (runs in a separate thread) -void input_handler() + const deque> &getBody() const + { + return body; + } +}; + +// ------------------ Input Handling ------------------ +inline void input_handler() { struct termios oldt, newt; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); // 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'}}; @@ -42,92 +84,72 @@ void input_handler() else if (input == 'p') { if (direction != 'P') - direction = 'P'; // pause + direction = 'P'; else - direction = 'r'; // resume moving right or previous direction + direction = 'r'; } } tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } -// Render the board -void render_game(int size, deque> &snake, pair food, pair poison, int score) +// ------------------ Rendering ------------------ +inline void render_game(int size, const Snake &snake, pair food, + pair poison, int score) { + const auto &body = snake.getBody(); for (int i = 0; i < size; ++i) { for (int j = 0; j < size; ++j) { if (i == food.first && j == food.second) - { cout << "🍎"; - } else if (i == poison.first && j == poison.second) - { cout << "☠️"; - } - else if (find(snake.begin(), snake.end(), make_pair(i, j)) != snake.end()) - { + else if (find(body.begin(), body.end(), make_pair(i, j)) != body.end()) cout << "🐍"; - } else - { cout << "⬜"; - } } cout << '\n'; } - cout << "Length: " << snake.size() << " Score: " << score << "\n"; + cout << "Length: " << snake.getSize() << " Score: " << score << "\n"; } -// Compute next head (wraps around) -pair get_next_head(pair current, char direction) +// ------------------ Game Helpers ------------------ +inline pair get_next_head(pair current, char direction) { - pair next; if (direction == 'r') - { - next = make_pair(current.first, (current.second + 1) % BOARD_SIZE); - } + return {current.first, (current.second + 1) % BOARD_SIZE}; else if (direction == 'l') - { - next = make_pair(current.first, current.second == 0 ? BOARD_SIZE - 1 : current.second - 1); - } + return {current.first, current.second == 0 ? BOARD_SIZE - 1 : current.second - 1}; else if (direction == 'd') - { - next = make_pair((current.first + 1) % BOARD_SIZE, current.second); - } + return {(current.first + 1) % BOARD_SIZE, current.second}; + else if (direction == 'u') + return {current.first == 0 ? BOARD_SIZE - 1 : current.first - 1, current.second}; + else if (direction == 'P') // <-- pause means no movement + return current; else - { // 'u' - next = make_pair(current.first == 0 ? BOARD_SIZE - 1 : current.first - 1, current.second); - } - return next; + return current; // safe fallback } -// Spawn food at a location not occupied by the snake -pair spawn_food(const deque> &snake) +inline pair spawn_food(const deque> &body) { vector> freeCells; for (int i = 0; i < BOARD_SIZE; ++i) - { for (int j = 0; j < BOARD_SIZE; ++j) - { - pair pos = make_pair(i, j); - if (find(snake.begin(), snake.end(), pos) == snake.end()) - { - freeCells.push_back(pos); - } - } - } + if (find(body.begin(), body.end(), make_pair(i, j)) == body.end()) + freeCells.push_back({i, j}); if (freeCells.empty()) - return make_pair(-1, -1); // board full + return {-1, -1}; - int idx = rand() % freeCells.size(); - return freeCells[idx]; + return freeCells[rand() % freeCells.size()]; } -// ✅ Save score to file -void save_score(int score) + +// ------------------ Score Management ------------------ +inline void save_score(int score) { - ofstream file("scores.txt", ios::app); // append mode + ofstream file("scores.txt", ios::app); if (file.is_open()) { file << score << "\n"; @@ -135,158 +157,125 @@ void save_score(int score) } } -// ✅ Load scores and return top 10 -vector load_top_scores() +inline vector load_top_scores() { ifstream file("scores.txt"); vector scores; int s; - while (file >> s) - { scores.push_back(s); - } file.close(); - // Sort descending sort(scores.begin(), scores.end(), greater()); - - // Keep only top 10 if (scores.size() > 10) - { scores.resize(10); - } return scores; } -void game_play() +// ------------------ Game Loop ------------------ +inline void game_play() { system("clear"); - deque> snake; - snake.push_back(make_pair(0, 0)); // starting segment + Snake snake; + pair food = spawn_food(snake.getBody()); + pair poison = spawn_food(snake.getBody()); - pair food = spawn_food(snake); - pair poison = spawn_food(snake); // spawn initial poison - - int score = 0; - int level = 1; // starting level - int baseDelay = 500; // initial delay in ms + int score = 0, level = 1, baseDelay = 500; while (true) { - pair currentHead = snake.back(); - pair nextHead = get_next_head(currentHead, direction); + auto currentHead = snake.getHead(); + auto nextHead = get_next_head(currentHead, direction); - cout << "\033[H"; // move cursor to top-left + cout << "\033[H"; - bool willGrow = (nextHead == food); - bool collision = false; - - // ✅ Pause logic if (direction == 'P') { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - continue; // skip movement, freeze game + this_thread::sleep_for(chrono::milliseconds(100)); + continue; } + bool willGrow = (nextHead == food); + bool collision = false; + const auto &body = snake.getBody(); + if (willGrow) { - if (find(snake.begin(), snake.end(), nextHead) != snake.end()) + if (find(body.begin(), body.end(), nextHead) != body.end()) collision = true; } else { - auto itStart = snake.begin(); - if (!snake.empty()) - ++itStart; // skip tail - if (find(itStart, snake.end(), nextHead) != snake.end()) + auto itStart = body.begin(); + if (!body.empty()) + ++itStart; + if (find(itStart, body.end(), nextHead) != body.end()) collision = true; } - // Snake collides with itself if (collision) { system("clear"); cout << "Game Over\n"; - cout << "Final Length: " << snake.size() << " Final Score: " << score << "\n"; - + cout << "Final Length: " << snake.getSize() << " Final Score: " << score << "\n"; save_score(score); cout << "\n=== Top 10 Scores ===\n"; - vector topScores = load_top_scores(); + auto topScores = load_top_scores(); for (int i = 0; i < topScores.size(); i++) - { cout << (i + 1) << ". " << topScores[i] << "\n"; - } - exit(0); } - // Snake eats poison if (nextHead == poison) { system("clear"); cout << "Snake ate poison ☠️ Game Over!\n"; - cout << "Final Length: " << snake.size() << " Final Score: " << score << "\n"; - + cout << "Final Length: " << snake.getSize() << " Final Score: " << score << "\n"; save_score(score); cout << "\n=== Top 10 Scores ===\n"; - vector topScores = load_top_scores(); + auto topScores = load_top_scores(); for (int i = 0; i < topScores.size(); i++) - { cout << (i + 1) << ". " << topScores[i] << "\n"; - } - exit(0); } - snake.push_back(nextHead); - if (willGrow) { - score += 1; - food = spawn_food(snake); + snake.grow(nextHead); + score++; + food = spawn_food(snake.getBody()); - // 🔹 Respawn poison every 3 points if (score % 3 == 0) - { - poison = spawn_food(snake); - } + poison = spawn_food(snake.getBody()); if (food.first == -1) { system("clear"); - cout << "You Win! Final Length: " << snake.size() << " Final Score: " << score << "\n"; - + cout << "You Win! Final Length: " << snake.getSize() << " Final Score: " << score << "\n"; save_score(score); cout << "\n=== Top 10 Scores ===\n"; - vector topScores = load_top_scores(); + auto topScores = load_top_scores(); for (int i = 0; i < topScores.size(); i++) - { cout << (i + 1) << ". " << topScores[i] << "\n"; - } - exit(0); } } else { - snake.pop_front(); + snake.move(nextHead); } - // Level calculation: increase level every 5 points level = (score / 5) + 1; - - // Render game (with poison + score) render_game(BOARD_SIZE, snake, food, poison, score); - cout << "Level: " << level << "\n"; - // Dynamic speed: faster as level increases (min 50ms) - int delay_ms = max(50, baseDelay - (level - 1) * 50 - (int)snake.size() * 5); - std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms)); + int delay_ms = max(50, baseDelay - (level - 1) * 50 - snake.getSize() * 5); + this_thread::sleep_for(chrono::milliseconds(delay_ms)); } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/snake_test.cpp b/snake_test.cpp index 42f8561..a260a9e 100644 --- a/snake_test.cpp +++ b/snake_test.cpp @@ -1,33 +1,97 @@ -#include + + #include "snake.h" +#include +char direction = 'r'; -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)); - +// ---------------- Movement Tests ---------------- +TEST(SnakeTest, NextHeadRight) +{ + pair pos = {0, 0}; + auto next = get_next_head(pos, 'r'); + EXPECT_EQ(next, make_pair(0, 1)); } +TEST(SnakeTest, NextHeadWrapLeft) +{ + pair pos = {0, 0}; + auto next = get_next_head(pos, 'l'); + EXPECT_EQ(next, make_pair(0, BOARD_SIZE - 1)); +} -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(SnakeTest, NextHeadDown) +{ + pair pos = {0, 0}; + auto next = get_next_head(pos, 'd'); + EXPECT_EQ(next, make_pair(1, 0)); } -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(SnakeTest, NextHeadUpWrap) +{ + pair pos = {0, 0}; + auto next = get_next_head(pos, 'u'); + EXPECT_EQ(next, make_pair(BOARD_SIZE - 1, 0)); } -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(SnakeTest, FoodNotInSnake) +{ + deque> snake = {{0, 0}, {0, 1}, {0, 2}}; + auto food = spawn_food(snake); + EXPECT_TRUE(find(snake.begin(), snake.end(), food) == snake.end()); } +// Poison food spawn & collision +TEST(SnakeTest, PoisonNotInSnake) +{ + deque> snake = {{0, 0}, {0, 1}}; + auto poison = spawn_food(snake); + EXPECT_TRUE(find(snake.begin(), snake.end(), poison) == snake.end()); +} +// play/pause functionality test +TEST(SnakeTest, PauseStopsMovement) +{ + deque> snake = {{0, 0}}; + char pauseDir = 'P'; + auto next = get_next_head(snake.back(), pauseDir); + EXPECT_EQ(next, snake.back()); +} +TEST(SnakeTest, SaveAndLoadScores) +{ + save_score(100); + save_score(50); + auto scores = load_top_scores(); + EXPECT_TRUE(find(scores.begin(), scores.end(), 100) != scores.end()); + EXPECT_TRUE(find(scores.begin(), scores.end(), 50) != scores.end()); +} +// ---------------- Difficulty Level Tests ---------------- +TEST(SnakeTest, DelayDecreasesWithLevel) +{ + int baseDelay = 500; + int level1 = max(50, baseDelay - (1 - 1) * 50 - 1 * 5); + int level5 = max(50, baseDelay - (5 - 1) * 50 - 10 * 5); + + EXPECT_LT(level5, level1); // delay should reduce at higher levels +} -/** +// ---------------- Snake Class Tests ---------------- +TEST(SnakeTest, SnakeGrowsOnFood) +{ + Snake s; + int oldSize = s.getSize(); + s.grow({0, 1}); // add a new head + EXPECT_EQ(s.getSize(), oldSize + 1); +} + +TEST(SnakeTest, SnakeMovesCorrectly) +{ + Snake s; + int oldSize = s.getSize(); + s.move({0, 1}); // head moves forward + EXPECT_EQ(s.getSize(), oldSize); // size remains same after move + EXPECT_EQ(s.getHead(), make_pair(0, 1)); +} +/** * g++ -o my_tests snake_test.cpp -lgtest -lgtest_main -pthread; * This command is a two-part shell command. Let's break it down. @@ -45,5 +109,5 @@ TEST(SnakeBehaviour, NextHeadDown) { Test, which saves you from writing your own main() to run the tests. * -pthread: This links the POSIX threads library, which is required by Google Test for its operation. - * + * */ \ No newline at end of file