diff --git a/snake.h b/snake.h index ebe1192..eacf289 100644 --- a/snake.h +++ b/snake.h @@ -11,8 +11,10 @@ using namespace std; using std::chrono::system_clock; using namespace std::this_thread; -char direction='r'; +char direction = 'r'; +bool paused = false; // track pause state +vector high_scores; // NEW: top 10 scores void input_handler(){ // change terminal settings @@ -22,80 +24,139 @@ void input_handler(){ // 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'}}; + + map keymap = {{'d', 'r'}, {'a', 'l'}, {'w', 'u'}, {'s', 'd'}}; + 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'){ + if (!paused) direction = keymap[input]; // movement only when not paused + } else if (input == 'q') { exit(0); + } else if (input == 'p') { + paused = !paused; // toggle pause/resume } - // 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){ +void render_game(int size, deque> &snake, pair food, pair poison){ 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') - { + }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); - } + 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; - } +// helper: generate new item not inside snake +pair generate_item(const deque> &snake, pair other, int size=10){ + pair pos; + do { + pos = make_pair(rand() % size, rand() % size); + } while(find(snake.begin(), snake.end(), pos) != snake.end() || pos == other); + return pos; +} +// NEW: update and print top 10 scores +void update_high_scores(int score) { + high_scores.push_back(score); + sort(high_scores.begin(), high_scores.end(), greater()); // sort descending + if (high_scores.size() > 10) high_scores.pop_back(); // keep only top 10 + + cout << "\n=== High Scores ===" << endl; + for (size_t i = 0; i < high_scores.size(); i++) { + cout << i+1 << ". " << high_scores[i] << endl; + } +} 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_item(snake, {-1,-1}); // ensures no overlap + pair poison = generate_item(snake, food); // separate from snake & food + + int score = 0; // track score + int moves = 0; // track moves for poison relocation + + int speed = 500; // initial speed in ms + const int min_speed = 100; // max difficulty + const int decrement = 20; // speed decrease per growth + 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 + cout << "\033[H"; // send cursor to top-left + + if (paused) { + render_game(10, snake, food, poison); + cout << "length of snake: " << snake.size() << endl; + cout << "score: " << score << endl; + cout << "[PAUSED] Press 'p' to resume" << endl; + sleep_for(chrono::milliseconds(200)); + continue; + } + if (find(snake.begin(), snake.end(), head) != snake.end()) { system("clear"); - cout << "Game Over" << endl; + cout << "Game Over! Final Score: " << score << endl; + update_high_scores(score); + exit(0); + } else if (head == food) { + snake.push_back(head); + + // spawn new food + food = generate_item(snake, poison); + + // increase difficulty + speed -= decrement; + if(speed < min_speed) speed = min_speed; + + // update score + score += 10; + } else if (head == poison) { + system("clear"); + cout << "You ate poison! Game Over. Final Score: " << score << endl; + update_high_scores(score); 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 + } else { snake.push_back(head); snake.pop_front(); } - render_game(10, snake, food); + + // relocate poison every 5 moves + moves++; + if (moves % 5 == 0) { + poison = generate_item(snake, food); + } + + render_game(10, snake, food, poison); cout << "length of snake: " << snake.size() << endl; - - sleep_for(500ms); + cout << "score: " << score << endl; + + sleep_for(chrono::milliseconds(speed)); } }