#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <conio.h>
#include <cmath>
#include <windows.h>
#include <bits/stdc++.h>
using namespace std;
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord;
void locate(int x, int y) {
coord.X = y;
coord.Y = x;
SetConsoleCursorPosition(hout, coord);
}
void hide() {
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(hout, &cursor_info);
}
double random(double start, double end) {
return start + (end - start) * rand() / (RAND_MAX + 1.0);
}
int m = 25, n = 40;
struct node {
int x, y;
};
struct Snake {
node body[1000];
int length;
int direction;
char headChar;
char bodyChar;
} snake1, snake2;
node food;
int direct[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};
bool allow_self_collision = false;
bool two_players = false;
void print_wall() {
cout << " ";
for (int i = 1; i <= n; i++) cout << "-";
cout << endl;
for (int j = 1; j <= m; j++) {
cout << "|";
for (int i = 1; i <= n; i++) cout << " ";
cout << "|" << endl;
}
cout << " ";
for (int i = 1; i <= n; i++)
cout << "-";
}
void print_snake(const Snake& s) {
locate(s.body[0].x, s.body[0].y);
cout << s.headChar;
for (int i = 1; i < s.length; i++) {
locate(s.body[i].x, s.body[i].y);
cout << s.bodyChar;
}
}
bool is_correct(const Snake& s) {
// 检查墙壁碰撞
if (s.body[0].x < 1 || s.body[0].y < 1 || s.body[0].x > m || s.body[0].y > n)
return false;
// 检查自身碰撞
if (!allow_self_collision) {
for (int i = 1; i < s.length; i++) {
if (s.body[0].x == s.body[i].x && s.body[0].y == s.body[i].y)
return false;
}
}
// 双人模式下检查与另一条蛇的碰撞
if (two_players) {
const Snake& other = (&s == &snake1) ? snake2 : snake1;
for (int i = 0; i < other.length; i++) {
if (s.body[0].x == other.body[i].x && s.body[0].y == other.body[i].y)
return false;
}
}
return true;
}
bool print_food() {
srand((unsigned)time(0));
while (true) {
food.x = rand() % m + 1;
food.y = rand() % n + 1;
bool valid = true;
// 检查是否与蛇1重叠
for (int k = 0; k < snake1.length; k++) {
if (snake1.body[k].x == food.x && snake1.body[k].y == food.y) {
valid = false;
break;
}
}
// 检查是否与蛇2重叠
if (two_players && valid) {
for (int k = 0; k < snake2.length; k++) {
if (snake2.body[k].x == food.x && snake2.body[k].y == food.y) {
valid = false;
break;
}
}
}
if (valid) break;
}
locate(food.x, food.y);
cout << "$";
return true;
}
bool go_ahead(Snake& s) {
node temp = s.body[s.length-1];
// 移动蛇身
for (int i = s.length-1; i >= 1; i--)
s.body[i] = s.body[i-1];
// 移动蛇头
s.body[0].x += direct[s.direction][0];
s.body[0].y += direct[s.direction][1];
// 打印移动后的蛇
locate(s.body[1].x, s.body[1].y);
cout << s.bodyChar;
bool ateFood = (s.body[0].x == food.x && s.body[0].y == food.y);
if (ateFood) {
s.length++;
s.body[s.length-1] = temp;
print_food();
} else {
locate(temp.x, temp.y);
cout << " ";
}
// 打印蛇头
locate(s.body[0].x, s.body[0].y);
cout << s.headChar;
if (!is_correct(s)) {
system("cls");
if (two_players) {
cout << ((&s == &snake1) ? "玩家2" : "玩家1") << "获胜!" << endl;
cout << "玩家1长度: " << snake1.length << endl;
cout << "玩家2长度: " << snake2.length << endl;
} else {
cout << "游戏结束! 你的长度: " << s.length << endl;
}
return false;
}
return true;
}
int main() {
cout << "--------------------贪吃蛇---------------------" << endl;
cout << "请注意窗口大小,以免发生错位.建议将窗口调为最大." << endl;
cout << "选择游戏模式: (1-单人, 2-双人): ";
int mode;
cin >> mode;
two_players = (mode == 2);
cout << "是否允许蛇碰到自己的身体? (1-允许, 0-不允许): ";
int allow_coll;
cin >> allow_coll;
allow_self_collision = (allow_coll == 1);
cout << "先选择难度(1-100, 1最简单,100最难): ";
int hard;
cin >> hard;
if (hard < 1 || hard > 100) {
cout << "无效难度!" << endl;
return 1;
}
// 初始化蛇1 - 左上角向右
snake1.length = 3;
snake1.direction = 3; // 右
snake1.headChar = '@';
snake1.bodyChar = '*';
for (int i = 0; i < 3; i++) {
snake1.body[i].x = 5;
snake1.body[i].y = 5 - i;
}
// 初始化蛇2 - 右下角向左
if (two_players) {
snake2.length = 3;
snake2.direction = 2; // 左
snake2.headChar = 'O';
snake2.bodyChar = '+';
for (int i = 0; i < 3; i++) {
snake2.body[i].x = m - 4;
snake2.body[i].y = n - 5 + i;
}
}
system("cls");
hide();
print_wall();
print_food();
print_snake(snake1);
if (two_players) {
print_snake(snake2);
}
locate(m+2, 0);
cout << "玩家1长度: " << snake1.length;
if (two_players) {
locate(m+3, 0);
cout << "玩家2长度: " << snake2.length;
}
double hard_len;
clock_t a, b;
while (true) {
hard_len = (double)snake1.length / (m * n);
a = clock();
while (true) {
b = clock();
if (b - a >= (int)(400 - 30 * hard) * (1 - sqrt(hard_len)))
break;
if (_kbhit()) {
int ch = _getch();
if (ch == 0xE0) { // 方向键
ch = _getch();
switch (ch) {
case 72: if (snake1.direction != 1) snake1.direction = 0; break; // 上
case 80: if (snake1.direction != 0) snake1.direction = 1; break; // 下
case 75: if (snake1.direction != 3) snake1.direction = 2; break; // 左
case 77: if (snake1.direction != 2) snake1.direction = 3; break; // 右
}
} else if (two_players) {
ch = tolower(ch);
if (ch == 'w' && snake2.direction != 1) snake2.direction = 0;
else if (ch == 's' && snake2.direction != 0) snake2.direction = 1;
else if (ch == 'a' && snake2.direction != 3) snake2.direction = 2;
else if (ch == 'd' && snake2.direction != 2) snake2.direction = 3;
}
}
}
bool snake1_alive = go_ahead(snake1);
locate(m+2, 12);
cout << snake1.length;
bool snake2_alive = true;
if (two_players) {
snake2_alive = go_ahead(snake2);
locate(m+3, 12);
cout << snake2.length;
}
if (!snake1_alive || !snake2_alive)
break;
}
system("pause");
return 0;
}