You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
9.2 KiB

#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;
}