#include #include #include #include using namespace std; const int WIDTH = 30; const int HEIGHT = 15; const int OBSTACLE_COUNT = 10; const int NORMAL_FRUIT_SCORE = 10; const int HIGH_SCORE_FRUIT_SCORE = 30; const int WIN_SCORE = 500; bool gameover, paused, highScoreFruit; int x, y, fruitX, fruitY, highScoreFruitX, highScoreFruitY, score; int tailX[100], tailY[100], nTail; int x2, y2, score2, tailX2[100], tailY2[100], nTail2; int obstacles[OBSTACLE_COUNT][2]; enum Direction { STOP = 0, LEFT, RIGHT, UP, DOWN }; Direction dir, dir2; bool twoSnakeMode = false; // 增加模式选择标志 void gotoxy(int x, int y) { COORD coord; coord.X = x; coord.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } void SetConsoleCursor(bool visible) { CONSOLE_CURSOR_INFO cci; cci.dwSize = 1; cci.bVisible = visible ? TRUE : FALSE; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci); } void InitializeObstacles() { for (int i = 0; i < OBSTACLE_COUNT; ++i) { do { obstacles[i][0] = rand() % WIDTH; obstacles[i][1] = rand() % HEIGHT; } while ((obstacles[i][0] == x && obstacles[i][1] == y) || (twoSnakeMode && obstacles[i][0] == x2 && obstacles[i][1] == y2)); } } void GenerateFruit(int& fruitX, int& fruitY) { int tt; do { tt = 0; fruitX = rand() % (WIDTH - 2) + 1; fruitY = rand() % (HEIGHT - 2) + 1; for (int i = 0; i < nTail; ++i) if (fruitX == tailX[i] && fruitY == tailY[i]) tt = 1; for (int i = 0; i < OBSTACLE_COUNT; ++i) if (fruitX == obstacles[i][0] && fruitY == obstacles[i][1]) tt = 1; if (fruitX == x && fruitY == y) tt = 1; if (twoSnakeMode && fruitX == x2 && fruitY == y2) tt = 1; } while (tt == 1); } void Setup() { gameover = paused = highScoreFruit = false; dir = dir2 = STOP; x = WIDTH / 2; y = HEIGHT / 2; if (twoSnakeMode) { x2 = WIDTH / 3; y2 = HEIGHT / 3; score2 = 0; nTail2 = 0; } fruitX = rand() % WIDTH; fruitY = rand() % HEIGHT; score = 0; nTail = 0; InitializeObstacles(); } void Draw() { gotoxy(0, 0); // 将光标移动到控制台的左上角 for (int i = 0; i < WIDTH + 2; i++) cout << "#"; cout << endl; for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { if (j == 0) cout << "#"; bool isObstacle = false; for (int k = 0; k < OBSTACLE_COUNT; ++k) { if (obstacles[k][0] == j && obstacles[k][1] == i) { cout << "*"; isObstacle = true; break; } } if (!isObstacle) { if (i == y && j == x) cout << "O"; else if (twoSnakeMode && i == y2 && j == x2) cout << "X"; else if (i == fruitY && j == fruitX) cout << "F"; else if (i == highScoreFruitY && j == highScoreFruitX && highScoreFruit) cout << "H"; else { bool printTail = false; for (int k = 0; k < nTail; k++) { if (tailX[k] == j && tailY[k] == i) { cout << "o"; printTail = true; break; } } if (twoSnakeMode) { for (int k = 0; k < nTail2; k++) { if (tailX2[k] == j && tailY2[k] == i) { cout << "x"; printTail = true; break; } } } if (!printTail) cout << " "; } } if (j == WIDTH - 1) cout << "#"; } cout << endl; } for (int i = 0; i < WIDTH + 2; i++) cout << "#"; cout << endl; cout << "Score1: " << score; if (twoSnakeMode) cout << " Score2: " << score2; cout << endl; if (paused) cout << "Paused. Press 'R' to resume." << endl; else cout << " " << endl; } void Input() { if (_kbhit()) { switch (_getch()) { case 'a': dir = LEFT; break; case 'd': dir = RIGHT; break; case 'w': dir = UP; break; case 's': dir = DOWN; break; case 'j': if (twoSnakeMode) dir2 = LEFT; break; case 'l': if (twoSnakeMode) dir2 = RIGHT; break; case 'i': if (twoSnakeMode) dir2 = UP; break; case 'k': if (twoSnakeMode) dir2 = DOWN; break; case 'p': paused = !paused; break; case 'q': gameover = true; break; } } } void MoveSnake(int& x, int& y, int tailX[], int tailY[], int& nTail, Direction dir) { int prevX = tailX[0]; int prevY = tailY[0]; int prev2X, prev2Y; tailX[0] = x; tailY[0] = y; for (int i = 1; i < nTail; i++) { prev2X = tailX[i]; prev2Y = tailY[i]; tailX[i] = prevX; tailY[i] = prevY; prevX = prev2X; prevY = prev2Y; } switch (dir) { case LEFT: x--; break; case RIGHT: x++; break; case UP: y--; break; case DOWN: y++; break; default: break; } if (x >= WIDTH) x = 0; else if (x < 0) x = WIDTH - 1; if (y >= HEIGHT) y = 1; else if (y <= 0) y = HEIGHT - 1; for (int i = 0; i < nTail; i++) if (tailX[i] == x && tailY[i] == y) gameover = true; for (int i = 0; i < OBSTACLE_COUNT; ++i) { if (x == obstacles[i][0] && y == obstacles[i][1]) { gameover = true; } } } void Algorithm() { if (!paused) { MoveSnake(x, y, tailX, tailY, nTail, dir); if (twoSnakeMode) { MoveSnake(x2, y2, tailX2, tailY2, nTail2, dir2); } static int timer = 0; const int timerThreshold = 50; timer++; if (timer == timerThreshold) { timer = 0; highScoreFruit = true; GenerateFruit(highScoreFruitX, highScoreFruitY); } if (x == highScoreFruitX && y == highScoreFruitY) { score += HIGH_SCORE_FRUIT_SCORE; highScoreFruit = false; nTail += 2; } if (twoSnakeMode && x2 == highScoreFruitX && y2 == highScoreFruitY) { score2 += HIGH_SCORE_FRUIT_SCORE; highScoreFruit = false; nTail2 += 2; } if (x == fruitX && y == fruitY) { score += NORMAL_FRUIT_SCORE; nTail++; GenerateFruit(fruitX, fruitY); } if (twoSnakeMode && x2 == fruitX && y2 == fruitY) { score2 += NORMAL_FRUIT_SCORE; nTail2++; GenerateFruit(fruitX, fruitY); } if (score >= WIN_SCORE) { gameover = true; gotoxy(0, HEIGHT + 3); Draw(); cout << "Player 1 wins!" << endl; return; } if (twoSnakeMode && score2 >= WIN_SCORE) { gameover = true; gotoxy(0, HEIGHT + 3); Draw(); cout << "Player 2 wins!" << endl; return; } } } void Index() { cout << "Press 1 for single snake mode" << endl; cout << "Press 9 for two snakes mode" << endl; cout << "Press 2 to exit\nPress p to pause\nPress r to resume\nPress q to quit" << endl; cout << "Rules:\nNormal fruit 'F' = 10 scores, increases length by 1;\nHigh-score fruit 'H' = 30 scores, increases length by 2;\nReach 500 scores to win!" << endl; } int main() { SetConsoleOutputCP(CP_UTF8); srand(time(0)); Index(); while (true) { int flag = 0; switch (_getch()) { case '1': twoSnakeMode = false; Setup(); while (!gameover) { Draw(); Input(); Algorithm(); Sleep(100); } gotoxy(0, WIDTH + 1); Index(); break; case '9': twoSnakeMode = true; Setup(); while (!gameover) { Draw(); Input(); Algorithm(); Sleep(100); } gotoxy(0, WIDTH + 1); Index(); break; case '2': flag = 1; break; } if (flag) break; } SetConsoleCursor(true); return 0; }