#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <conio.h>
#include <utility>
#ifdef _WIN32
#include <windows.h>
#define CLEAR_SCREEN "cls"
#define SLEEP_MS(x) Sleep(x)
#else
#define CLEAR_SCREEN "clear"
#define SLEEP_MS(x) usleep(x * 1000)
#endif
using namespace std;
enum Direction { UP, DOWN, LEFT, RIGHT };
struct Bullet {
int x, y;
Direction dir;
bool alive;
Bullet(int x_, int y_, Direction dir_) : x(x_), y(y_), dir(dir_), alive(true) {}
};
class Tank {
public:
int x, y;
Direction dir;
bool alive;
char symbol;
Tank(int x_, int y_, char sym) : x(x_), y(y_), dir(UP), alive(true), symbol(sym) {}
bool move(Direction newDir, int mapWidth, int mapHeight, const vector<pair<int, int> >& obstacles);
};
const int MAP_WIDTH = 50;
const int MAP_HEIGHT = 25;
const int REFRESH_RATE = 100;
Tank player(20, 2, 'P');
Tank enemy(5, 45, 'E');
vector<Bullet> bullets;
vector<pair<int, int> > obstacles;
bool gameOver = false;
string winner = "";
bool isObstacle(int x, int y) {
for (vector<pair<int, int> >::const_iterator it = obstacles.begin(); it != obstacles.end(); ++it) {
if (it->first == x && it->second == y) {
return true;
}
}
return false;
}
bool Tank::move(Direction newDir, int mapWidth, int mapHeight, const vector<pair<int, int> >& obstacles) {
dir = newDir;
int newX = x, newY = y;
switch (newDir) {
case UP: newX--; break;
case DOWN: newX++; break;
case LEFT: newY--; break;
case RIGHT: newY++; break;
}
if (newX >= 1 && newX <= mapHeight-2 && newY >= 1 && newY <= mapWidth-2 && !isObstacle(newX, newY)) {
x = newX;
y = newY;
return true;
}
return false;
}
void initObstacles() {
obstacles.clear();
for (int i = 3; i <= 22; i += 2) {
obstacles.push_back(make_pair(i, 5));
}
for (int j = 7; j <= 15; j += 2) {
obstacles.push_back(make_pair(8, j));
}
for (int i = 10; i <= 22; i += 2) {
obstacles.push_back(make_pair(i, 20));
}
for (int j = 22; j <= 30; j += 2) {
obstacles.push_back(make_pair(15, j));
}
for (int i = 3; i <= 13; i += 2) {
obstacles.push_back(make_pair(i, 35));
}
for (int j = 37; j <= 45; j += 2) {
obstacles.push_back(make_pair(10, j));
}
obstacles.push_back(make_pair(5, 10));
obstacles.push_back(make_pair(12, 25));
obstacles.push_back(make_pair(18, 30));
obstacles.push_back(make_pair(7, 40));
obstacles.push_back(make_pair(20, 15));
}
void clearScreen() {
system(CLEAR_SCREEN);
}
void drawMap() {
clearScreen();
for (int i = 0; i < MAP_HEIGHT; i++) {
for (int j = 0; j < MAP_WIDTH; j++) {
if (i == 0 || i == MAP_HEIGHT-1 || j == 0 || j == MAP_WIDTH-1) {
cout << "#";
}
else if (isObstacle(i, j)) {
cout << "X";
}
else if (i == player.x && j == player.y && player.alive) {
cout << player.symbol;
}
else if (i == enemy.x && j == enemy.y && enemy.alive) {
cout << enemy.symbol;
}
else {
bool isBullet = false;
for (vector<Bullet>::iterator it = bullets.begin(); it != bullets.end(); ++it) {
if (it->alive && it->x == i && it->y == j) {
cout << "*";
isBullet = true;
break;
}
}
if (!isBullet) {
cout << " ";
}
}
}
cout << endl;
}
cout << "===== 坦克对战游戏(Dev-C++ 5.11)=====" << endl;
cout << "界面尺寸:宽" << MAP_WIDTH << " × 高" << MAP_HEIGHT << endl;
cout << "操作:W(上) A(左) S(下) D(右) 空格(发射) Q(退出)" << endl;
cout << "玩家:P 电脑:E 子弹:* 边界:# 障碍物:X" << endl;
if (gameOver) {
cout << "游戏结束!" << winner << "获胜!" << endl;
}
}
void checkCollision() {
for (vector<Bullet>::iterator it = bullets.begin(); it != bullets.end(); ) {
if (!it->alive) {
it = bullets.erase(it);
continue;
}
if (it->x == player.x && it->y == player.y && player.alive) {
player.alive = false;
gameOver = true;
winner = "电脑";
it->alive = false;
}
else if (it->x == enemy.x && it->y == enemy.y && enemy.alive) {
enemy.alive = false;
gameOver = true;
winner = "玩家";
it->alive = false;
}
else if (isObstacle(it->x, it->y)) {
it->alive = false;
}
else if (it->x <= 0 || it->x >= MAP_HEIGHT-1 || it->y <= 0 || it->y >= MAP_WIDTH-1) {
it->alive = false;
}
else {
++it;
}
}
}
void moveBullets() {
for (vector<Bullet>::iterator it = bullets.begin(); it != bullets.end(); ++it) {
if (!it->alive) continue;
switch (it->dir) {
case UP: it->x--; break;
case DOWN: it->x++; break;
case LEFT: it->y--; break;
case RIGHT: it->y++; break;
}
}
}
void enemyAI() {
if (!enemy.alive || gameOver) return;
int moveRand = rand() % 3;
if (moveRand == 0) {
Direction newDir = (Direction)(rand() % 4);
enemy.move(newDir, MAP_WIDTH, MAP_HEIGHT, obstacles);
}
int fireRand = rand() % 15;
if (fireRand == 0) {
bullets.push_back(Bullet(enemy.x, enemy.y, enemy.dir));
}
}
char getInput() {
#ifdef _WIN32
if (kbhit()) {
return getch();
}
#else
fd_set rfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
if (select(STDIN_FILENO+1, &rfds, NULL, NULL, &tv) > 0) {
return getchar();
}
#endif
return 0;
}
void handleInput() {
if (!player.alive || gameOver) return;
char key = getInput();
switch (key) {
case 'w': case 'W': player.move(UP, MAP_WIDTH, MAP_HEIGHT, obstacles); break;
case 's': case 'S': player.move(DOWN, MAP_WIDTH, MAP_HEIGHT, obstacles); break;
case 'a': case 'A': player.move(LEFT, MAP_WIDTH, MAP_HEIGHT, obstacles); break;
case 'd': case 'D': player.move(RIGHT, MAP_WIDTH, MAP_HEIGHT, obstacles); break;
case ' ': bullets.push_back(Bullet(player.x, player.y, player.dir)); break;
case 'q': case 'Q': gameOver = true; winner = "退出"; break;
}
}
int main() {
srand(static_cast<unsigned int>(time(NULL)));
initObstacles();
while (!gameOver) {
handleInput();
enemyAI();
moveBullets();
checkCollision();
drawMap();
SLEEP_MS(REFRESH_RATE);
}
drawMap();
cout << "\n按任意键退出..." << endl;
getch();
return 0;
}