parent
ce701ea486
commit
95f30cd2a8
@ -0,0 +1,339 @@
|
||||
#include <iostream>
|
||||
#include <conio.h>
|
||||
#include <windows.h>
|
||||
#include <ctime>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in new issue