diff --git a/snake.h b/snake.h index ebe1192..fecbf01 100644 --- a/snake.h +++ b/snake.h @@ -2,100 +2,158 @@ #include #include #include -#include +#include #include -#include // for system clear +#include #include #include #include +#include + using namespace std; -using std::chrono::system_clock; +using namespace std::chrono; using namespace std::this_thread; -char direction='r'; + +char direction = 'r'; +bool paused = false; -void input_handler(){ - // change terminal settings +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); 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'}, {'q', 'q'} + }; + while (true) { char input = getchar(); - if (keymap.find(input) != keymap.end()) { - // This now correctly modifies the single, shared 'direction' variable + if (keymap.count(input)) { direction = keymap[input]; - }else if (input == 'q'){ + } else if (input == 'p') { + paused = !paused; + } else if (input == 'q') { exit(0); } - // You could add an exit condition here, e.g., if (input == 'q') break; } - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } -void render_game(int size, deque> &snake, pair food){ - for(size_t i=0;i>& snake, + const pair& food, const pair& poison) { + 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; } + + +pair get_next_head(const pair& current, char dir) { + int x = current.first; + int y = current.second; + + if (dir == 'r') return {x, (y + 1) % 10}; + if (dir == 'l') return {x, y == 0 ? 9 : y - 1}; + if (dir == 'd') return {(x + 1) % 10, y}; + if (dir == 'u') return {x == 0 ? 9 : x - 1, y}; + + return current; } -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(const deque>& snake, + const pair& avoid) { + pair pos; + do { + pos = {rand() % 10, rand() % 10}; + } while (find(snake.begin(), snake.end(), pos) != snake.end() || pos == avoid); + return pos; } +void update_highscores(int score) { + vector scores; + ifstream infile("highscores.txt"); + int s; + while (infile >> s) scores.push_back(s); + infile.close(); -void game_play(){ + scores.push_back(score); + sort(scores.begin(), scores.end(), greater()); + if (scores.size() > 10) scores.resize(10); + + ofstream outfile("highscores.txt"); + for (int sc : scores) outfile << sc << "\n"; + outfile.close(); + + cout << "\nšŸ† Top 10 High Scores šŸ†\n"; + for (size_t i = 0; i < scores.size(); i++) { + cout << i + 1 << ". " << scores[i] << "\n"; + } +} + + +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 + deque> snake = {{0, 0}}; + pair food = generate_food(snake, {-1, -1}); + pair poison = generate_food(snake, food); + + int score = 0, foodEaten = 0, speed = 500; + + for (pair head = {0, 1};; head = get_next_head(head, direction)) { + cout << "\033[H"; + if (paused) { + cout << "Game Paused - Press 'p' to Resume\n"; + sleep_for(200ms); + continue; + } + + // Collisions if (find(snake.begin(), snake.end(), head) != snake.end()) { system("clear"); - cout << "Game Over" << endl; + cout << "Game Over! You ate yourself šŸ\n"; + cout << "Final Score: " << score << "\n"; + update_highscores(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 + } + if (head == food) { + food = generate_food(snake, poison); + poison = generate_food(snake, food); + snake.push_back(head); + foodEaten++; + score += 10; + if (foodEaten % 10 == 0 && speed > 100) speed -= 50; + } else if (head == poison) { + system("clear"); + cout << "Game Over! You ate poison ā˜ ļø\n"; + cout << "Final Score: " << score << "\n"; + update_highscores(score); + exit(0); + } else { snake.push_back(head); snake.pop_front(); } - render_game(10, snake, food); - cout << "length of snake: " << snake.size() << endl; - - sleep_for(500ms); + + render_game(10, snake, food, poison); + cout << "Score: " << score << "\n"; + cout << "Length of snake: " << snake.size() << "\n"; + cout << "Speed: " << speed << "ms\n"; + + sleep_for(milliseconds(speed)); } }