本题要求:
昨天做了手动的贪吃蛇,今天让我们的小蛇自己吃苹果吧~
输入格式:
无
输出格式:
无
输入样例:
无
输出样例:
无
解题思路 :
代码 :
#include <iostream>
#include <string>
#include <cstring>
#include <conio.h>
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <queue>
#include <stack>
using namespace std;
#define X 10
#define Y 10
enum FACE {UP_ = 0, DOWN_ = 1, LEFT_ = 2, RIGHT_ = 3};
int gameMap[X][Y];
void gotoXY(int x, int y) {
//Initialize the coordinates
COORD coord = {x, y};
//Set the position
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
pair<int, int> apple;
class Snake {
public:
int x; // 头部位置
int y;
int tx; // 尾巴位置
int ty;
int food;
int point;
FACE face;
Snake(int gameMap[X][Y]) {
init(gameMap);
}
void init(int gameMap[X][Y]) {
x = X / 2;
y = Y / 2;
tx = -1;
ty = -1;
food = 0;
point = 3;
face = UP_;
gameMap[x][y] = point;
setFood(gameMap);
}
void setFace(FACE f) {
switch(face) {
case UP_:
if (f != DOWN_) {
face = f;
}
break;
case DOWN_:
if (f != UP_) {
face = f;
}
break;
case LEFT_:
if (f != RIGHT_) {
face = f;
}
break;
case RIGHT_:
if (f != LEFT_) {
face = f;
}
break;
}
}
void setFood(int gameMap[X][Y]) {
int tempX, tempY;
srand(time(0));
do {
tempX = rand() % (X - 1) + 1;
tempY = rand() % (X - 1) + 1;
} while (gameMap[tempX][tempY]);
gameMap[tempX][tempY] = 2;
apple.first = tempX;
apple.second = tempY;
}
bool check(int gameMap[X][Y], int x, int y) {
if (x < 0 || y < 0 || x >= X || y >= Y || (gameMap[x][y] != 2 && gameMap[x][y] != 0)) {
return false;
} else {
if (gameMap[x][y] == 2) {
food++;
setFood(gameMap);
}
return true;
}
}
bool move(int gameMap[X][Y]) {
moveTail(gameMap);
return moveHead(gameMap);
}
bool moveHead(int gameMap[X][Y]) {
if (tx == -1) {
tx = x;
ty = y;
}
switch(face) {
case UP_:
y--;
break;
case DOWN_:
y++;
break;
case LEFT_:
x--;
break;
case RIGHT_:
x++;
break;
default:
getch();
break;
}
if (check(gameMap, x, y)) {
gameMap[x][y] = ++point;
return true;
} else {
return false;
}
}
void moveTail(int gameMap[X][Y]) {
if (food != 0) {
food--;
return;
}
int nextX = tx;
int nextY = ty;
int fx[4] = {1, -1, 0, 0};
int fy[4] = {0, 0, -1, 1};
for (int i = 0; i < 4; i++) {
if (gameMap[tx + fx[i]][ty + fy[i]] == gameMap[tx][ty] + 1) {
nextX = tx + fx[i];
nextY = ty + fy[i];
break;
}
}
gameMap[tx][ty] = 0;
tx = nextX;
ty = nextY;
}
};
Snake snake(gameMap);
void init();
void display(int gameMap[X][Y]);
void setFood(int gameMap[X][Y]);
void control(int ch);
stack<int> bfs(pair<int, int> start, pair<int, int> end) {
stack<int> path;
int dist[101][101];
int dist2[101][101];
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
dist[i][j] = 0x7f7f;
dist2[i][j] = -1;
}
}
queue<pair<int, int> > que;
dist[start.first][start.second] = 0;
que.push(start);
int fx[4] = {0, 0, -1, 1};
int fy[4] = {-1, 1, 0, 0};
while (que.size()) {
pair<int, int> now;
now = que.front();
que.pop();
if (now == end) {
break;
}
for (int i = 0; i < 4; i++) {
int nx = now.first + fx[i];
int ny = now.second + fy[i];
if (nx >= 0 && ny >= 0 && nx < X && ny < Y && (gameMap[nx][ny] == 0 || gameMap[nx][ny] == gameMap[end.first][end.second]) && dist[nx][ny] == 0x7f7f) {
que.push(pair<int, int>(nx, ny));
dist2[nx][ny] = i;
dist[nx][ny] = dist[now.first][now.second] + 1;
}
}
}
int d = dist2[end.first][end.second];
while (d != -1) {
path.push(d);
switch(d) {
case UP_:
d = dist2[end.first][++end.second];
break;
case DOWN_:
d = dist2[end.first][--end.second];
break;
case LEFT_:
d = dist2[++end.first][end.second];
break;
case RIGHT_:
d = dist2[--end.first][end.second];
break;
}
}
return path;
}
void moveFace(pair<int, int> &nowPos, int face) {
switch(face) {
case UP_:
nowPos.second--;
break;
case DOWN_:
nowPos.second++;
break;
case LEFT_:
nowPos.first--;
break;
case RIGHT_:
nowPos.first++;
break;
}
}
pair<int, int> findNear(int tx, int ty) {
pair<int, int> p;
int fx[4] = {1, -1, 0, 0};
int fy[4] = {0, 0, -1, 1};
for (int i = 0; i < 4; i++) {
if (gameMap[tx + fx[i]][ty + fy[i]] == gameMap[tx][ty] + 1) {
p.first = tx + fx[i];
p.second = ty + fy[i];
return p;
}
}
}
bool goAway() {
for (int i = 0; i < 4; i++) {
pair<int, int> nowPos(snake.x, snake.y);
moveFace(nowPos, i);
stack<int> path = bfs(nowPos, findNear(snake.tx, snake.ty));
if (!path.empty()) {
snake.setFace((FACE)path.top());
snake.move(gameMap);
display(gameMap);
}
}
}
bool autoMove(int gameMap[X][Y]) {
pair<int, int> nowPos(snake.x, snake.y);
stack<int> path = bfs(nowPos, apple);
if (!path.empty()) {
moveFace(nowPos, (FACE)path.top());
if (snake.tx != -1) {
stack<int> path2 = bfs(nowPos, pair<int, int>(snake.tx, snake.ty));
if (!path2.empty()) {
snake.setFace((FACE)path.top());
snake.move(gameMap);
display(gameMap);
} else {
goAway();
}
} else {
snake.setFace((FACE)path.top());
snake.move(gameMap);
display(gameMap);
}
} else {
goAway();
}
return true;
}
int main()
{
init();
display(gameMap);
while (true) {
if (kbhit()) {
char a = getch();
control(a);
}
if (autoMove(gameMap) == false) {
return 0;
}
}
return 0;
}
void init() {
memset(gameMap, 0, sizeof(gameMap));
for (int y = 0; y < Y; y++) {
for (int x = 0; x < X; x++) {
if (x == 0 || y == 0 || x == X - 1 || y == Y - 1) {
gameMap[x][y] = 1;
}
}
}
snake.init(gameMap);
}
void display(int gameMap[X][Y]) {
for (int y = 0; y < Y; y++) {
for (int x = 0; x < X; x++) {
gotoXY(x * 2, y);
switch(gameMap[x][y]) {
case 0: // 空白
cout << " ";
break;
case 1: // 墙
cout << "■";
break;
case 2: // 苹果
cout << "★";
break;
default: // 蛇身
cout << "□";
break;
}
}
}
gotoXY(snake.tx * 2, snake.ty);
cout << "☆";
gotoXY(0, 15);
gotoXY(snake.x * 2, snake.y);
cout << "●";
gotoXY(0, 15);
//getch();
}
void setFood(int gameMap[X][Y]) {
int tempX, tempY;
srand(time(0));
do {
tempX = rand() % (X - 1) + 1;
tempY = rand() % (X - 1) + 1;
} while (gameMap[tempX][tempY]);
gameMap[tempX][tempY] = 2;
}
void control(int ch) {
switch(ch) {
case 'w':
case 'W':
if (snake.face != DOWN_) {
snake.setFace(UP_);
}
break;
case 'a':
case 'A':
if (snake.face != RIGHT_) {
snake.setFace(LEFT_);
}
break;
case 'd':
case 'D':
if (snake.face != LEFT_) {
snake.setFace(RIGHT_);
}
break;
case 's':
case 'S':
if (snake.face != UP_) {
snake.setFace(DOWN_);
}
break;
}
}