From 434590ced6aa4b2012b9dd2d6e296dd1473c0d3e Mon Sep 17 00:00:00 2001 From: Kashish Sorathiya <140380370+KashishSorathiya@users.noreply.github.com> Date: Wed, 17 Sep 2025 20:25:06 +0530 Subject: [PATCH 1/7] Update snake.h --- snake.h | 115 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/snake.h b/snake.h index ebe1192..4d4d262 100644 --- a/snake.h +++ b/snake.h @@ -3,99 +3,98 @@ #include #include #include -#include -#include // for system clear +#include // Windows input +#include // Windows clear screen #include #include #include using namespace std; using std::chrono::system_clock; using namespace std::this_thread; -char direction='r'; +char direction = 'r'; +// Windows: clear screen +void clear_screen() { + HANDLE hOut; + COORD Position; + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + Position.X = 0; + Position.Y = 0; + SetConsoleCursorPosition(hOut, Position); +} -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'}}; +// Windows input handler +void input_handler() { + 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); + if (_kbhit()) { // agar koi key press hui + char input = _getch(); + if (keymap.find(input) != keymap.end()) { + direction = keymap[input]; + } else if (input == 'q') { + exit(0); + } } - // You could add an exit condition here, e.g., if (input == 'q') break; + sleep_for(50ms); } - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } - -void render_game(int size, deque> &snake, pair food){ - for(size_t i=0;i> &snake, pair food) { + for (size_t i = 0; i < size; i++) { + for (size_t j = 0; j < size; j++) { + if (i == food.first && j == food.second) { + cout << "O"; // Food + } else if (find(snake.begin(), snake.end(), make_pair(int(i), int(j))) != snake.end()) { + cout << "X"; // Snake + } else { + cout << "."; } + } + cout << endl; } - cout << endl; -} } -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); - } +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); + } return next; - } - - -void game_play(){ - system("clear"); +void game_play() { + system("cls"); // Windows clear deque> snake; - snake.push_back(make_pair(0,0)); + 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"; + for (pair head = make_pair(0, 1);; head = get_next_head(head, direction)) { + clear_screen(); // check self collision if (find(snake.begin(), snake.end(), head) != snake.end()) { - system("clear"); + system("cls"); cout << "Game Over" << endl; exit(0); - }else if (head.first == food.first && head.second == food.second) { + } else if (head.first == food.first && head.second == food.second) { // grow snake food = make_pair(rand() % 10, rand() % 10); - snake.push_back(head); - }else{ + snake.push_back(head); + } else { // move snake snake.push_back(head); snake.pop_front(); } render_game(10, snake, food); cout << "length of snake: " << snake.size() << endl; - + sleep_for(500ms); } } From 75bc0509d4e9da0f347b8a478cc2d90699f43861 Mon Sep 17 00:00:00 2001 From: KashishSorathiya Date: Thu, 18 Sep 2025 00:29:37 +0530 Subject: [PATCH 2/7] Updated snake.h --- snake.h | 117 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/snake.h b/snake.h index 4d4d262..f423e2a 100644 --- a/snake.h +++ b/snake.h @@ -3,98 +3,111 @@ #include #include #include -#include // Windows input -#include // Windows clear screen +#include +#include // for system clear #include #include #include using namespace std; using std::chrono::system_clock; using namespace std::this_thread; -char direction = 'r'; +char direction='r'; -// Windows: clear screen -void clear_screen() { - HANDLE hOut; - COORD Position; - hOut = GetStdHandle(STD_OUTPUT_HANDLE); - Position.X = 0; - Position.Y = 0; - SetConsoleCursorPosition(hOut, Position); -} -// Windows input handler -void input_handler() { - map keymap = { - {'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}, {'q', 'q'} - }; +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) { - if (_kbhit()) { // agar koi key press hui - char input = _getch(); - if (keymap.find(input) != keymap.end()) { - direction = keymap[input]; - } else if (input == 'q') { - exit(0); - } + 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); } - sleep_for(50ms); + // You could add an exit condition here, e.g., if (input == 'q') break; } + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } -void render_game(int size, deque> &snake, pair food) { - for (size_t i = 0; i < size; i++) { - for (size_t j = 0; j < size; j++) { - if (i == food.first && j == food.second) { - cout << "O"; // Food - } else if (find(snake.begin(), snake.end(), make_pair(int(i), int(j))) != snake.end()) { - cout << "X"; // Snake - } else { - cout << "."; + +void render_game(int size, deque> &snake, pair food){ + for(size_t i=0;i 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); - } +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); + } return next; + } void game_play() { - system("cls"); // Windows clear + system("clear"); deque> snake; snake.push_back(make_pair(0, 0)); pair food = make_pair(rand() % 10, rand() % 10); + + int food_eaten = 0; // count how many food items eaten + int speed = 500; // start speed in milliseconds + for (pair head = make_pair(0, 1);; head = get_next_head(head, direction)) { - clear_screen(); + // send the cursor to the top + cout << "\033[H"; + // check self collision if (find(snake.begin(), snake.end(), head) != snake.end()) { - system("cls"); + 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); + + food_eaten++; + + + if (food_eaten % 10 == 0 && speed > 100) { + speed += 50; + } } else { // move snake snake.push_back(head); snake.pop_front(); } + render_game(10, snake, food); cout << "length of snake: " << snake.size() << endl; + cout << "food eaten: " << food_eaten << " | current speed: " << speed << "ms" << endl; - sleep_for(500ms); + sleep_for(std::chrono::milliseconds(speed)); } -} +} \ No newline at end of file From 757fa3b887fe9127cb759d53233536c1557772d4 Mon Sep 17 00:00:00 2001 From: KashishSorathiya Date: Thu, 18 Sep 2025 15:52:43 +0530 Subject: [PATCH 3/7] Updated snake.h as per assignment --- snake.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/snake.h b/snake.h index f423e2a..4cacd0f 100644 --- a/snake.h +++ b/snake.h @@ -52,6 +52,9 @@ void render_game(int size, deque> &snake, pair food){ } } + + + pair get_next_head(pair current, char direction){ pair next; if(direction =='r'){ @@ -68,12 +71,20 @@ pair get_next_head(pair current, char direction){ } +pair generate_food(int size, const deque> &snake) { + pair food; + do { + food = make_pair(rand() % size, rand() % size); + } while (find(snake.begin(), snake.end(), food) != snake.end()); + return food; +} void game_play() { system("clear"); deque> snake; snake.push_back(make_pair(0, 0)); - pair food = make_pair(rand() % 10, rand() % 10); + pair food = generate_food(10, snake); + int food_eaten = 0; // count how many food items eaten int speed = 500; // start speed in milliseconds @@ -89,7 +100,8 @@ void game_play() { exit(0); } else if (head.first == food.first && head.second == food.second) { // grow snake - food = make_pair(rand() % 10, rand() % 10); + food = generate_food(10, snake); + snake.push_back(head); food_eaten++; From 78e50d5aa797aea3cccfdeaae1b716489205cd89 Mon Sep 17 00:00:00 2001 From: KashishSorathiya Date: Thu, 18 Sep 2025 16:04:42 +0530 Subject: [PATCH 4/7] Updated snake.h as per assignment --- snake.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/snake.h b/snake.h index 4cacd0f..32b01c6 100644 --- a/snake.h +++ b/snake.h @@ -4,7 +4,7 @@ #include #include #include -#include // for system clear +#include #include #include #include @@ -15,23 +15,19 @@ 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); } - // You could add an exit condition here, e.g., if (input == 'q') break; } tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } @@ -86,38 +82,37 @@ void game_play() { pair food = generate_food(10, snake); - int food_eaten = 0; // count how many food items eaten - int speed = 500; // start speed in milliseconds + int food_eaten = 0; + int speed = 500; + int score = 0; 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 = generate_food(10, snake); snake.push_back(head); food_eaten++; + score+=10; - if (food_eaten % 10 == 0 && speed > 100) { - speed += 50; + speed += 50; } } else { - // move snake snake.push_back(head); snake.pop_front(); } render_game(10, snake, food); cout << "length of snake: " << snake.size() << endl; + cout << "Score: " << score << endl; + cout << "food eaten: " << food_eaten << " | current speed: " << speed << "ms" << endl; sleep_for(std::chrono::milliseconds(speed)); From 2ee4c59ef914483ee8b28d6b9915e1226e9dfda6 Mon Sep 17 00:00:00 2001 From: KashishSorathiya Date: Thu, 18 Sep 2025 16:12:28 +0530 Subject: [PATCH 5/7] Updated snake.h and .gitignore for assignment --- .gitignore | 5 +- snake.h | 172 +++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 125 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index d4fb281..544f547 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# VS Code settings +.vscode/ + # Prerequisites *.d @@ -38,4 +41,4 @@ *.app # debug information files -*.dwo +*.dwo \ No newline at end of file diff --git a/snake.h b/snake.h index 32b01c6..aa0b5a1 100644 --- a/snake.h +++ b/snake.h @@ -11,108 +11,178 @@ using namespace std; using std::chrono::system_clock; using namespace std::this_thread; -char direction='r'; +char direction = 'r'; - -void input_handler(){ +bool paused = false; // global flag +void input_handler() +{ 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) { + map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}}; + + while (true) + { char input = getchar(); - if (keymap.find(input) != keymap.end()) { + if (keymap.find(input) != keymap.end()) + { direction = keymap[input]; - }else if (input == 'q'){ + } + else if (input == 'p') + { + paused = !paused; // toggle pause/resume + } + else if (input == 'q') + { exit(0); } } 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) +{ + for (size_t i = 0; i < size; i++) + { + for (size_t 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(int(i), int(j))) != snake.end()) + { cout << "🐍"; - }else{ - cout << "⬜"; } + else + { + cout << "⬜"; + } + } + cout << endl; } - cout << endl; -} } - - - -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') +pair get_next_head(pair current, char direction) +{ + pair next; + if (direction == 'r') { - 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); - } + 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); + } return next; - } -pair generate_food(int size, const deque> &snake) { - pair food; - do { +pair generate_food(int size, const deque> &snake) +{ + pair food; + do + { food = make_pair(rand() % size, rand() % size); } while (find(snake.begin(), snake.end(), food) != snake.end()); return food; } -void game_play() { + +pair generate_poison(int size, const deque> &snake, pair food) +{ + pair poison; + do + { + poison = make_pair(rand() % size, rand() % size); + } while ( + find(snake.begin(), snake.end(), poison) != snake.end() || poison == food); + return poison; +} + +void game_play() +{ system("clear"); deque> snake; snake.push_back(make_pair(0, 0)); pair food = generate_food(10, snake); + pair poison = generate_poison(10, snake, food); + int food_eaten = 0; + int speed = 500; + int score = 0; + int poison_timer = 0; - int food_eaten = 0; - int speed = 500; - int score = 0; - - for (pair head = make_pair(0, 1);; head = get_next_head(head, direction)) { + pair head = make_pair(0, 1); + while (true) + { cout << "\033[H"; - if (find(snake.begin(), snake.end(), head) != snake.end()) { + while (paused) + { + system("clear"); + render_game(10, snake, food, poison); + cout << "=== PAUSED ===" << endl; + cout << "Press 'p' to resume..." << endl; + sleep_for(std::chrono::milliseconds(200)); + system("clear"); + } + + head = get_next_head(head, direction); + + 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) { + } + else if (head == poison) + { + system("clear"); + cout << "Game Over ( Snake ate poison ☠️ )" << endl; + exit(0); + } + else if (head.first == food.first && head.second == food.second) + { food = generate_food(10, snake); - snake.push_back(head); - food_eaten++; - score+=10; + score += 10; - if (food_eaten % 10 == 0 && speed > 100) { + if (food_eaten % 10 == 0 && speed > 100) + { speed += 50; } - } else { + } + else + { snake.push_back(head); snake.pop_front(); } - render_game(10, snake, food); + poison_timer += speed; // add time passed in this loop + if (poison_timer >= 5000) + { + poison = generate_poison(10, snake, food); + poison_timer = 0; + } + + render_game(10, snake, food, poison); cout << "length of snake: " << snake.size() << endl; cout << "Score: " << score << endl; - cout << "food eaten: " << food_eaten << " | current speed: " << speed << "ms" << endl; sleep_for(std::chrono::milliseconds(speed)); From f29c094d851a808a3f10ed1b98993da59c07e5e3 Mon Sep 17 00:00:00 2001 From: KashishSorathiya Date: Thu, 18 Sep 2025 17:00:21 +0530 Subject: [PATCH 6/7] Updated snake.h top_scores.txt and .gitignore for assignment --- snake.h | 268 ++++++++++++++++++++++++++----------------------- top_scores.txt | 3 + 2 files changed, 145 insertions(+), 126 deletions(-) create mode 100644 top_scores.txt diff --git a/snake.h b/snake.h index aa0b5a1..df6f923 100644 --- a/snake.h +++ b/snake.h @@ -4,18 +4,39 @@ #include #include #include -#include +#include #include #include #include +#include + using namespace std; using std::chrono::system_clock; using namespace std::this_thread; -char direction = 'r'; +char direction='r'; +vector top_scores; +bool paused = false; +void load_top_scores() { + ifstream infile("top_scores.txt"); + int s; + top_scores.clear(); + while (infile >> s) { + top_scores.push_back(s); + } + infile.close(); + sort(top_scores.rbegin(), top_scores.rend()); + if (top_scores.size() > 10) top_scores.resize(10); +} + +void save_top_scores() { + ofstream outfile("top_scores.txt"); + for (int s : top_scores) { + outfile << s << endl; + } + outfile.close(); +} -bool paused = false; // global flag -void input_handler() -{ +void input_handler(){ struct termios oldt, newt; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; @@ -23,97 +44,79 @@ void input_handler() tcsetattr(STDIN_FILENO, TCSANOW, &newt); map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}}; - while (true) - { + + while (true) { char input = getchar(); - if (keymap.find(input) != keymap.end()) - { + if (keymap.find(input) != keymap.end()) { direction = keymap[input]; - } - else if (input == 'p') - { - paused = !paused; // toggle pause/resume - } - else if (input == 'q') - { + }else if(input == 'p') { + paused = !paused; + } + else if (input == 'q'){ exit(0); } } tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } -void render_game(int size, deque> &snake, pair food, pair poison) -{ - for (size_t i = 0; i < size; i++) - { - for (size_t 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(int(i), int(j))) != snake.end()) - { + +void render_game(int size, deque> &snake, pair food, pair poison) { + for (size_t i = 0; i < size; i++) { + for (size_t 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(int(i), int(j))) != snake.end()) { cout << "🐍"; - } - else - { - cout << "⬜"; + } else { + cout << "⬜"; } } cout << endl; } } -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') + + + +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 == 0 ? 9 : current.first - 1, current.second); - } + 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); + } return next; + } -pair generate_food(int size, const deque> &snake) -{ - pair food; - do - { +pair generate_food(int size, const deque> &snake) { + pair food; + do { food = make_pair(rand() % size, rand() % size); } while (find(snake.begin(), snake.end(), food) != snake.end()); return food; } -pair generate_poison(int size, const deque> &snake, pair food) -{ - pair poison; - do - { +pair generate_poison(int size, const deque> &snake, pair food) { + pair poison; + do { poison = make_pair(rand() % size, rand() % size); } while ( - find(snake.begin(), snake.end(), poison) != snake.end() || poison == food); + find(snake.begin(), snake.end(), poison) != snake.end() || poison == food + ); return poison; } -void game_play() -{ +void game_play() { + load_top_scores(); + system("clear"); deque> snake; snake.push_back(make_pair(0, 0)); @@ -121,70 +124,83 @@ void game_play() pair food = generate_food(10, snake); pair poison = generate_poison(10, snake, food); - int food_eaten = 0; - int speed = 500; - int score = 0; - int poison_timer = 0; - pair head = make_pair(0, 1); - while (true) - { - cout << "\033[H"; - - while (paused) - { - system("clear"); - render_game(10, snake, food, poison); - cout << "=== PAUSED ===" << endl; - cout << "Press 'p' to resume..." << endl; - sleep_for(std::chrono::milliseconds(200)); - system("clear"); - } + int food_eaten = 0; + int speed = 500; + int score = 0; + int poison_timer = 0; - head = get_next_head(head, direction); +pair head = make_pair(0, 1); +while (true) { + cout << "\033[H"; - if (find(snake.begin(), snake.end(), head) != snake.end()) - { - system("clear"); - cout << "Game Over" << endl; - exit(0); - } - else if (head == poison) - { - system("clear"); - cout << "Game Over ( Snake ate poison ☠️ )" << endl; - exit(0); - } - else if (head.first == food.first && head.second == food.second) - { - food = generate_food(10, snake); - snake.push_back(head); - food_eaten++; - score += 10; - - if (food_eaten % 10 == 0 && speed > 100) - { - speed += 50; - } - } - else - { - snake.push_back(head); - snake.pop_front(); - } + while (paused) { + system("clear"); + render_game(10, snake, food, poison); + cout << "=== PAUSED ===" << endl; + cout << "Press 'p' to resume..." << endl; + sleep_for(std::chrono::milliseconds(200)); + system("clear"); + } - poison_timer += speed; // add time passed in this loop - if (poison_timer >= 5000) - { - poison = generate_poison(10, snake, food); - poison_timer = 0; - } + head = get_next_head(head, direction); - render_game(10, snake, food, poison); - cout << "length of snake: " << snake.size() << endl; - cout << "Score: " << score << endl; - cout << "food eaten: " << food_eaten << " | current speed: " << speed << "ms" << endl; + if (find(snake.begin(), snake.end(), head) != snake.end()) { + system("clear"); + + top_scores.push_back(score); + sort(top_scores.rbegin(), top_scores.rend()); + if (top_scores.size() > 10) top_scores.resize(10); + save_top_scores(); + + cout << "Game Over! Snake hit itself." << endl; + cout << "Top 10 Scores:" << endl; + for (int s : top_scores) cout << s << endl; - sleep_for(std::chrono::milliseconds(speed)); + exit(0); +} +else if (head == poison) { + system("clear"); + + // Update top scores and save + top_scores.push_back(score); + sort(top_scores.rbegin(), top_scores.rend()); + if (top_scores.size() > 10) top_scores.resize(10); + save_top_scores(); + + cout << "Game Over! Snake ate poison ☠️." << endl; + cout << "Top 10 Scores:" << endl; + for (int s : top_scores) cout << s << endl; + + exit(0); +} + + + else if (head.first == food.first && head.second == food.second) { + food = generate_food(10, snake); + snake.push_back(head); + food_eaten++; + score += 10; + + if (food_eaten % 10 == 0 && speed > 100) { + speed += 50; + } + } else { + snake.push_back(head); + snake.pop_front(); + } + + poison_timer += speed; // add time passed in this loop + if (poison_timer >= 5000) { + poison = generate_poison(10, snake, food); + poison_timer = 0; } + + render_game(10, snake, food, poison); + cout << "length of snake: " << snake.size() << endl; + cout << "Score: " << score << endl; + cout << "food eaten: " << food_eaten << " | current speed: " << speed << "ms" << endl; + + sleep_for(std::chrono::milliseconds(speed)); +} } \ No newline at end of file diff --git a/top_scores.txt b/top_scores.txt new file mode 100644 index 0000000..cf8ba84 --- /dev/null +++ b/top_scores.txt @@ -0,0 +1,3 @@ +20 +20 +0 \ No newline at end of file From d59458ba7270df4a6345f95c05847a3ebe092d38 Mon Sep 17 00:00:00 2001 From: Rajvi Dhameliya Date: Sun, 28 Sep 2025 20:19:02 +0530 Subject: [PATCH 7/7] Refactored snake game code --- main.cpp | 14 ++- snake.h | 307 ++++++++++++++++++++++++------------------------------- 2 files changed, 144 insertions(+), 177 deletions(-) diff --git a/main.cpp b/main.cpp index ef65093..a5ee391 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,13 @@ #include "snake.h" +#include + +int main() { + Game game; + thread input_thread(&Game::handle_input, &game); + thread game_thread(&Game::play, &game); -int main(int argc, char *argv[]) { - thread input_thread(input_handler); - thread game_thread(game_play); input_thread.join(); game_thread.join(); -return 0; -} \ No newline at end of file + + return 0; +} diff --git a/snake.h b/snake.h index df6f923..ac25d62 100644 --- a/snake.h +++ b/snake.h @@ -1,206 +1,169 @@ +#pragma once #include #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include +#include using namespace std; -using std::chrono::system_clock; using namespace std::this_thread; -char direction='r'; -vector top_scores; -bool paused = false; -void load_top_scores() { - ifstream infile("top_scores.txt"); - int s; - top_scores.clear(); - while (infile >> s) { - top_scores.push_back(s); - } - infile.close(); - sort(top_scores.rbegin(), top_scores.rend()); - if (top_scores.size() > 10) top_scores.resize(10); -} - -void save_top_scores() { - ofstream outfile("top_scores.txt"); - for (int s : top_scores) { - outfile << s << endl; - } - outfile.close(); -} - -void input_handler(){ - 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'}}; - - - while (true) { - char input = getchar(); - if (keymap.find(input) != keymap.end()) { - direction = keymap[input]; - }else if(input == 'p') { - paused = !paused; - } - else if (input == 'q'){ - exit(0); - } - } - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); -} - - -void render_game(int size, deque> &snake, pair food, pair poison) { - for (size_t i = 0; i < size; i++) { - for (size_t 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(int(i), int(j))) != snake.end()) { - cout << "🐍"; - } else { - cout << "⬜"; - } - } - cout << endl; - } -} - - - - -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); - } - return next; - -} - -pair generate_food(int size, const deque> &snake) { +using namespace std::chrono; + +constexpr int GRID_SIZE = 10; +constexpr int INITIAL_SPEED = 500; // milliseconds +constexpr int POISON_INTERVAL = 5000; // milliseconds +constexpr int MAX_TOP_SCORES = 10; + +class Game { +private: + char direction = 'r'; + bool paused = false; + vector top_scores; + deque> snake; pair food; - do { - food = make_pair(rand() % size, rand() % size); - } while (find(snake.begin(), snake.end(), food) != snake.end()); - return food; -} - -pair generate_poison(int size, const deque> &snake, pair food) { pair poison; - do { - poison = make_pair(rand() % size, rand() % size); - } while ( - find(snake.begin(), snake.end(), poison) != snake.end() || poison == food - ); - return poison; -} + int speed = INITIAL_SPEED; + int score = 0; + int food_eaten = 0; + int poison_timer = 0; -void game_play() { - load_top_scores(); +public: + Game() { + snake.push_back({0,0}); + food = generate_food(); + poison = generate_poison(); + load_top_scores(); + } - system("clear"); - deque> snake; - snake.push_back(make_pair(0, 0)); + void load_top_scores() { + ifstream infile("top_scores.txt"); + int s; + top_scores.clear(); + while (infile >> s) top_scores.push_back(s); + infile.close(); + sort(top_scores.rbegin(), top_scores.rend()); + if (top_scores.size() > MAX_TOP_SCORES) top_scores.resize(MAX_TOP_SCORES); + } - pair food = generate_food(10, snake); - pair poison = generate_poison(10, snake, food); + void save_top_scores() { + ofstream outfile("top_scores.txt"); + for (int s : top_scores) outfile << s << endl; + outfile.close(); + } + pair get_next_head(pair current, char dir) { + if(dir == 'r') return {current.first, (current.second + 1) % GRID_SIZE}; + if(dir == 'l') return {current.first, current.second == 0 ? GRID_SIZE - 1 : current.second - 1}; + if(dir == 'd') return {(current.first + 1) % GRID_SIZE, current.second}; + if(dir == 'u') return {current.first == 0 ? GRID_SIZE - 1 : current.first - 1, current.second}; + return current; + } - int food_eaten = 0; - int speed = 500; - int score = 0; - int poison_timer = 0; + pair generate_food() { + pair f; + do { f = {rand() % GRID_SIZE, rand() % GRID_SIZE}; } + while (find(snake.begin(), snake.end(), f) != snake.end()); + return f; + } -pair head = make_pair(0, 1); -while (true) { - cout << "\033[H"; + pair generate_poison() { + pair p; + do { p = {rand() % GRID_SIZE, rand() % GRID_SIZE}; } + while (find(snake.begin(), snake.end(), p) != snake.end() || p == food); + return p; + } - while (paused) { - system("clear"); - render_game(10, snake, food, poison); - cout << "=== PAUSED ===" << endl; - cout << "Press 'p' to resume..." << endl; - sleep_for(std::chrono::milliseconds(200)); - system("clear"); + void render() { + for(int i = 0; i < GRID_SIZE; ++i) { + for(int j = 0; j < GRID_SIZE; ++j) { + pair cell = {i,j}; + if(cell == food) cout << "🍎"; + else if(cell == poison) cout << "☠️"; + else if(find(snake.begin(), snake.end(), cell) != snake.end()) cout << "🐍"; + else cout << "⬜"; + } + cout << endl; + } + cout << "Length: " << snake.size() << " | Score: " << score << " | Food eaten: " << food_eaten + << " | Speed: " << speed << "ms" << endl; } - head = get_next_head(head, direction); + void handle_input() { + 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'}}; - if (find(snake.begin(), snake.end(), head) != snake.end()) { - system("clear"); + while(true) { + char input = getchar(); + if(keymap.find(input) != keymap.end()) direction = keymap[input]; + else if(input == 'p') paused = !paused; + else if(input == 'q') exit(0); + } - top_scores.push_back(score); - sort(top_scores.rbegin(), top_scores.rend()); - if (top_scores.size() > 10) top_scores.resize(10); - save_top_scores(); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + } - cout << "Game Over! Snake hit itself." << endl; - cout << "Top 10 Scores:" << endl; - for (int s : top_scores) cout << s << endl; + void play() { + pair head = {0,1}; - exit(0); -} -else if (head == poison) { - system("clear"); + while(true) { + cout << "\033[H"; // move cursor to top - // Update top scores and save - top_scores.push_back(score); - sort(top_scores.rbegin(), top_scores.rend()); - if (top_scores.size() > 10) top_scores.resize(10); - save_top_scores(); + while(paused) { + system("clear"); + render(); + cout << "=== PAUSED ===\nPress 'p' to resume...\n"; + sleep_for(milliseconds(200)); + } - cout << "Game Over! Snake ate poison ☠️." << endl; - cout << "Top 10 Scores:" << endl; - for (int s : top_scores) cout << s << endl; + head = get_next_head(head, direction); - exit(0); -} + if(find(snake.begin(), snake.end(), head) != snake.end() || head == poison) { + end_game(head == poison ? "Snake ate poison ☠️." : "Snake hit itself."); + } + if(head == food) { + snake.push_back(head); + food = generate_food(); + food_eaten++; + score += 10; + if(food_eaten % 10 == 0 && speed > 100) speed += 50; + } else { + snake.push_back(head); + snake.pop_front(); + } - else if (head.first == food.first && head.second == food.second) { - food = generate_food(10, snake); - snake.push_back(head); - food_eaten++; - score += 10; + poison_timer += speed; + if(poison_timer >= POISON_INTERVAL) { + poison = generate_poison(); + poison_timer = 0; + } - if (food_eaten % 10 == 0 && speed > 100) { - speed += 50; + render(); + sleep_for(milliseconds(speed)); } - } else { - snake.push_back(head); - snake.pop_front(); } - poison_timer += speed; // add time passed in this loop - if (poison_timer >= 5000) { - poison = generate_poison(10, snake, food); - poison_timer = 0; +private: + void end_game(const string& message) { + system("clear"); + top_scores.push_back(score); + sort(top_scores.rbegin(), top_scores.rend()); + if(top_scores.size() > MAX_TOP_SCORES) top_scores.resize(MAX_TOP_SCORES); + save_top_scores(); + + cout << "Game Over! " << message << "\nTop 10 Scores:\n"; + for(int s : top_scores) cout << s << endl; + exit(0); } - - render_game(10, snake, food, poison); - cout << "length of snake: " << snake.size() << endl; - cout << "Score: " << score << endl; - cout << "food eaten: " << food_eaten << " | current speed: " << speed << "ms" << endl; - - sleep_for(std::chrono::milliseconds(speed)); -} -} \ No newline at end of file +};