diff --git a/snake.h b/snake.h index ebe1192..b2700c9 100644 --- a/snake.h +++ b/snake.h @@ -4,98 +4,183 @@ #include #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'; +char direction = 'r'; +bool paused = false; +multiset> topscores; -void input_handler(){ - // change terminal settings + +void loadScores() { + ifstream infile("scores.txt"); + int score; + while (infile >> score) { + topscores.insert(score); + } + infile.close(); +} + +void saveScores() { + ofstream outfile("scores.txt"); + int count = 0; + for (int score : topscores) { + if (count++ == 10) break; + outfile << score << "\n"; + } + outfile.close(); +} + +void showTopScores() { + cout << "\n=== Top Scores ===\n"; + int count = 0; + for (int s : topscores) { + cout << ++count << ". " << s << endl; + if (count == 10) break; + } + cout << "==================\n"; +} + +void input_handler() { 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'}}; + + 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'){ + } else if (input == 'x') { + paused = !paused; + } else if (input == 'q') { + saveScores(); exit(0); } - // 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> &snake, pair food, pair poisonfood) { + 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 (find(snake.begin(), snake.end(), make_pair(int(i), int(j))) != snake.end()) { + } else if (find(snake.begin(), snake.end(), make_pair(int(i), int(j))) != snake.end()) { cout << "🐍"; - }else{ + } else if (i == poisonfood.first && j == poisonfood.second) { + 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') - { - 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 gameOver(int score, const string &reason) { + system("clear"); + cout << "Game Over! " << reason << endl; + cout << "Final Score: " << score << " points\n"; + topscores.insert(score); + saveScores(); -void game_play(){ + showTopScores(); + exit(0); +} + +void game_play() { system("clear"); + + loadScores(); + showTopScores(); + deque> snake; - snake.push_back(make_pair(0,0)); + snake.push_back(make_pair(0, 0)); + + pair food; + do { + food = make_pair(rand() % 10, rand() % 10); + } while (find(snake.begin(), snake.end(), food) != snake.end()); + + pair poisonfood = make_pair(-1, -1); + pair head = make_pair(0, 1); - 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 + while (true) { cout << "\033[H"; - // check self collision + int score = snake.size() * 10; + + if (paused) { + render_game(10, snake, food, poisonfood); + cout << "Game paused. Press x to continue" << endl; + cout << "Score: " << score << " points" << endl; + sleep_for(std::chrono::milliseconds(200)); + continue; + } + + 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) { - // grow snake - food = make_pair(rand() % 10, rand() % 10); - snake.push_back(head); - }else{ - // move snake + gameOver(score, "You hit yourself!"); + } + + else if (head.first == food.first && head.second == food.second) { + do { + food = make_pair(rand() % 10, rand() % 10); + } while (find(snake.begin(), snake.end(), food) != snake.end()); + + if (rand() % 3 == 0) { + do { + poisonfood = make_pair(rand() % 10, rand() % 10); + } while (find(snake.begin(), snake.end(), poisonfood) != snake.end() && food == poisonfood); + } else { + poisonfood = make_pair(-1, -1); + } + snake.push_back(head); + } + + else if (head == poisonfood) { + gameOver(score, "You ate poisonous food!"); + } + + else { snake.push_back(head); snake.pop_front(); } - render_game(10, snake, food); + + render_game(10, snake, food, poisonfood); cout << "length of snake: " << snake.size() << endl; - - sleep_for(500ms); + cout << "Score: " << score << " points" << endl; + + int base_delay = 500; + int min_delay = 100; + int reduction = (snake.size() / 10) * 50; + int current_delay = max(min_delay, base_delay - reduction); + + sleep_for(std::chrono::milliseconds(current_delay)); } }