Files
2026-04-14 20:09:11 +00:00

636 lines
21 KiB
C++

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <algorithm>
#include <cstdlib>
#include <termios.h>
#include <unistd.h>
#include <thread>
#include <chrono>
using namespace std;
// تعریف متغیرهای اصلی
const int SCREEN_WIDTH = 40;
const int SCREEN_HEIGHT = 20;
const char PLAYER_SHIP = 'A';
const char ENEMY_TYPE1 = 'X';
const char ENEMY_TYPE2 = 'Y';
const char ENEMY_TYPE3 = 'Z';
const char RED_UFO = 'U';
const char LASER = '|';
const char ENEMY_MISSILE = '*';
int score = 0, lives = 3, level = 1, gameTime = 0, laserCount = 1;
int playerX = SCREEN_WIDTH / 2, playerY = SCREEN_HEIGHT - 2;
int enemyX = 5, enemyY = 1, baseEnemySpeed = 500, enemySpeed = baseEnemySpeed;
bool moveRight = true;
bool ufoVisible = false;
int ufoX = -1, ufoY = 0, baseFireProbability = 2, enemiesDestroyed = 0;
const int ENEMY_ROWS = 3, ENEMY_COLS = 10, NUM_BARRIERS = 3, BARRIER_WIDTH = 5, BARRIER_HEIGHT = 2, thresholdToUpgrade = 15;
chrono::steady_clock::time_point startTime = chrono::steady_clock::now();
vector<vector<bool>> enemies(ENEMY_ROWS, vector<bool>(ENEMY_COLS, true));
vector<pair<int, int>> lasers, enemyMissiles;
vector<vector<int>> barriers(NUM_BARRIERS, vector<int>(BARRIER_WIDTH * BARRIER_HEIGHT, 3));
vector<pair<int, int>> barrierPositions = {{10, 15}, {20, 15}, {30, 15}};
void setColor(string colorCode) {
cout << "\033[" << colorCode << "m";
}
void resetColor() {
cout << "\033[0m";
}
char getInput() {
struct termios oldt, newt;
char ch;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
void updateGameTime() {
chrono::steady_clock::time_point currentTime = chrono::steady_clock::now();
gameTime = chrono::duration_cast<chrono::seconds>(currentTime - startTime).count();
}
void renderStatus() {
// نمایش وضعیت در بالای صفحه
cout << "\033[1;1H"; // تنظیم موقعیت چاپ به خط اول
setColor("36"); // رنگ فیروزه‌ای
cout << "Score: " << score << " | Lives: " << lives << " | Time: " << gameTime << "s";
resetColor();
cout << "\033[2;1H"; // رفتن به خط دوم برای نمایش صفحه بازی
}
void renderScreen() {
system("clear"); // پاک کردن صفحه
for (int y = 0; y < SCREEN_HEIGHT; y++) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
if (y == playerY && x == playerX) {
cout << PLAYER_SHIP; // نمایش سفینه بازیکن
} else {
// نمایش لیزرها
bool isLaser = false;
for (pair<int, int> &laser : lasers) {
if (laser.first == y && laser.second == x) {
cout << LASER;
isLaser = true;
break;
}
}
if (!isLaser) {
cout << " "; // فضای خالی
}
}
}
cout << endl;
}
}
void renderEnemies() {
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
if (enemies[i][j]) {
int x = enemyX + j;
int y = enemyY + i;
if (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT) {
cout << "\033[" << y + 1 << ";" << x + 1 << "H"; // تنظیم موقعیت چاپ در ترمینال
if (i == 0)
cout << ENEMY_TYPE3; // دشمن نوع سوم
else if (i == 1)
cout << ENEMY_TYPE2; // دشمن نوع دوم
else
cout << ENEMY_TYPE1; // دشمن نوع اول
}
}
}
}
}
void renderBarriers() {
for (int b = 0; b < NUM_BARRIERS; b++) {
int startX = barrierPositions[b].first;
int startY = barrierPositions[b].second;
for (int y = 0; y < BARRIER_HEIGHT; y++) {
for (int x = 0; x < BARRIER_WIDTH; x++) {
int idx = y * BARRIER_WIDTH + x;
if (barriers[b][idx] > 0) {
cout << "\033[" << (startY + y + 1) << ";" << (startX + x + 1) << "H"; // تنظیم موقعیت چاپ
if (barriers[b][idx] == 3) setColor("32"); // سبز (سالم)
else if (barriers[b][idx] == 2) setColor("33"); // زرد (آسیب‌دیده)
else setColor("31"); // قرمز (تقریباً نابود)
cout << "#";
resetColor();
}
}
}
}
}
void renderUFO() {
if (ufoVisible && ufoX >= 0 && ufoX < SCREEN_WIDTH) {
cout << "\033[" << ufoY + 1 << ";" << ufoX + 1 << "H"; // تنظیم موقعیت چاپ در ترمینال
setColor("31"); // رنگ قرمز
cout << RED_UFO;
resetColor();
}
}
void renderMissiles() {
for (pair<int, int> &missile : enemyMissiles) {
int x = missile.second;
int y = missile.first;
if (y >= 0 && y < SCREEN_HEIGHT) {
cout << "\033[" << y + 1 << ";" << x + 1 << "H"; // تنظیم موقعیت چاپ در ترمینال
setColor("33"); // رنگ زرد
cout << ENEMY_MISSILE;
resetColor();
}
}
}
void updateEnemies() {
// تغییر جهت حرکت در صورت رسیدن به لبه صفحه
if (moveRight) {
if (enemyX + ENEMY_COLS >= SCREEN_WIDTH) {
moveRight = false;
enemyY++; // حرکت به سمت پایین
} else {
enemyX++; // حرکت به راست
}
} else {
if (enemyX <= 0) {
moveRight = true;
enemyY++; // حرکت به سمت پایین
} else {
enemyX--; // حرکت به چپ
}
}
// افزایش سرعت با کاهش تعداد دشمنان
int remainingEnemies = 0;
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
if (enemies[i][j]) remainingEnemies++;
}
}
if (remainingEnemies > 0) {
enemySpeed = max(100, 500 - (remainingEnemies * 5)); // کاهش زمان برای افزایش سرعت
}
}
void updateLasers() {
for (vector<pair<int, int>>::iterator it = lasers.begin(); it != lasers.end();) {
it->first--; // حرکت تیر به بالا
if (it->first < 0) {
it = lasers.erase(it); // حذف تیر اگر از بالای صفحه خارج شد
} else {
// برخورد آینه‌ای
if (it->second <= 0 || it->second >= SCREEN_WIDTH - 1) {
it->second = max(0, min(SCREEN_WIDTH - 1, it->second)); // محدود کردن به صفحه
it->second *= -1; // معکوس کردن جهت حرکت افقی
}
++it;
}
}
}
void updateMissiles() {
for (vector<pair<int, int>>::iterator it = enemyMissiles.begin(); it != enemyMissiles.end();) {
it->first++; // حرکت موشک به پایین
if (it->first >= SCREEN_HEIGHT) {
it = enemyMissiles.erase(it); // حذف موشک اگر از صفحه خارج شد
} else {
++it;
}
}
}
void updateUFO() {
// اگر بشقاب پرنده در حال حرکت است
if (ufoVisible) {
ufoX++; // حرکت به سمت راست
if (ufoX >= SCREEN_WIDTH) {
ufoVisible = false; // اگر از صفحه خارج شد، ناپدید شود
ufoX = -1;
}
} else {
// ایجاد بشقاب پرنده به صورت تصادفی
if (rand() % 100 < 2) { // احتمال 2 درصد برای ظاهر شدن UFO
ufoVisible = true;
ufoX = 0; // شروع از لبه چپ صفحه
}
}
}
void enemyFire() {
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
if (enemies[i][j] && rand() % 100 < 2) { // احتمال 2 درصد برای شلیک موشک
enemyMissiles.push_back({enemyY + i + 1, enemyX + j});
}
}
}
}
void checkLaserHits() {
for (vector<pair<int, int>>::iterator it = lasers.begin(); it != lasers.end();) {
int laserX = it->second;
int laserY = it->first;
bool hit = false;
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
int enemyPosX = enemyX + j;
int enemyPosY = enemyY + i;
if (enemies[i][j] && laserX == enemyPosX && laserY == enemyPosY) {
enemies[i][j] = false; // حذف دشمن
it = lasers.erase(it); // حذف لیزر
hit = true;
break;
}
}
if (hit) break;
}
if (!hit) ++it;
}
}
void checkLaserBarrierHits() {
for (vector<pair<int, int>>::iterator it = lasers.begin(); it != lasers.end();) {
int laserX = it->second;
int laserY = it->first;
bool hit = false;
for (int b = 0; b < NUM_BARRIERS; b++) {
int startX = barrierPositions[b].first;
int startY = barrierPositions[b].second;
if (laserY >= startY && laserY < startY + BARRIER_HEIGHT &&
laserX >= startX && laserX < startX + BARRIER_WIDTH) {
int idx = (laserY - startY) * BARRIER_WIDTH + (laserX - startX);
if (barriers[b][idx] > 0) {
barriers[b][idx]--; // کاهش مقاومت مانع
it = lasers.erase(it); // حذف لیزر
hit = true;
break;
}
}
}
if (!hit) ++it;
}
}
void checkMissileHits() {
for (vector<pair<int, int>>::iterator it = enemyMissiles.begin(); it != enemyMissiles.end();) {
int missileX = it->second;
int missileY = it->first;
// برخورد با سفینه بازیکن
if (missileX == playerX && missileY == playerY) {
cout << "\nYour ship was hit! -1 life\n";
this_thread::sleep_for(chrono::milliseconds(500));
it = enemyMissiles.erase(it); // حذف موشک
// TODO: کاهش تعداد جان بازیکن
} else {
++it;
}
}
}
void checkMissileBarrierHits() {
for (vector<pair<int, int>>::iterator it = enemyMissiles.begin(); it != enemyMissiles.end();) {
int missileX = it->second;
int missileY = it->first;
bool hit = false;
for (int b = 0; b < NUM_BARRIERS; b++) {
int startX = barrierPositions[b].first;
int startY = barrierPositions[b].second;
if (missileY >= startY && missileY < startY + BARRIER_HEIGHT &&
missileX >= startX && missileX < startX + BARRIER_WIDTH) {
int idx = (missileY - startY) * BARRIER_WIDTH + (missileX - startX);
if (barriers[b][idx] > 0) {
barriers[b][idx]--; // کاهش مقاومت مانع
it = enemyMissiles.erase(it); // حذف موشک
hit = true;
break;
}
}
}
if (!hit) ++it;
}
}
void checkUFOHit() {
for (vector<pair<int, int>>::iterator it = lasers.begin(); it != lasers.end();) {
int laserX = it->second;
int laserY = it->first;
if (ufoVisible && laserX == ufoX && laserY == ufoY) {
ufoVisible = false; // حذف UFO
ufoX = -1;
it = lasers.erase(it); // حذف لیزر
cout << "\nYou destroyed the Red UFO! +100 points\n";
this_thread::sleep_for(chrono::milliseconds(500));
break;
} else {
++it;
}
}
}
void resetEnemies() {
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
enemies[i][j] = true; // تمام دشمنان دوباره ظاهر می‌شوند
}
}
enemyX = 5; // موقعیت اولیه دشمنان
enemyY = 1; // ارتفاع اولیه دشمنان
moveRight = true; // تنظیم جهت حرکت اولیه
}
void increaseDifficulty() {
level++; // افزایش سطح
enemySpeed = max(100, baseEnemySpeed - (level * 50)); // کاهش زمان حرکت دشمنان
baseFireProbability = min(10, baseFireProbability + level); // افزایش احتمال شلیک موشک
for (vector<int> &barrier : barriers) {
for (int &cell : barrier) {
cell = max(1, cell - 1); // کاهش مقاومت موانع
}
}
cout << "Level Up! Welcome to Level " << level << "!\n";
this_thread::sleep_for(chrono::seconds(2));
}
bool isLevelComplete() {
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
if (enemies[i][j]) {
return false; // اگر حداقل یک دشمن باقی مانده باشد، سطح کامل نشده است
}
}
}
return true; // تمام دشمنان نابود شده‌اند
}
void saveGame() {
ofstream saveFile("save.txt");
if (!saveFile) {
cout << "Error: Could not open save file.\n";
return;
}
// ذخیره وضعیت کلی بازی
saveFile << score << " " << lives << " " << gameTime << "\n";
saveFile << playerX << " " << playerY << "\n";
// ذخیره دشمنان
saveFile << enemyX << " " << enemyY << " " << moveRight << "\n";
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
saveFile << enemies[i][j] << " ";
}
saveFile << "\n";
}
// ذخیره موقعیت موانع
for (int b = 0; b < NUM_BARRIERS; b++) {
for (int idx = 0; idx < BARRIER_WIDTH * BARRIER_HEIGHT; idx++) {
saveFile << barriers[b][idx] << " ";
}
saveFile << "\n";
}
// ذخیره لیزرها
saveFile << lasers.size() << "\n";
for (pair<int, int> &laser : lasers) {
saveFile << laser.first << " " << laser.second << "\n";
}
// ذخیره موشک‌های دشمن
saveFile << enemyMissiles.size() << "\n";
for (pair<int, int> &missile : enemyMissiles) {
saveFile << missile.first << " " << missile.second << "\n";
}
// ذخیره وضعیت بشقاب پرنده قرمز
saveFile << ufoVisible << " " << ufoX << " " << ufoY << "\n";
saveFile.close();
cout << "Game saved successfully!\n";
}
void loadGame() {
ifstream loadFile("save.txt");
if (!loadFile) {
cout << "Error: Could not open save file.\n";
return;
}
// بارگذاری وضعیت کلی بازی
loadFile >> score >> lives >> gameTime;
loadFile >> playerX >> playerY;
// بارگذاری دشمنان
loadFile >> enemyX >> enemyY >> moveRight;
for (int i = 0; i < ENEMY_ROWS; i++) {
for (int j = 0; j < ENEMY_COLS; j++) {
bool temp;
loadFile >> temp;
enemies[i][j] = temp;
}
}
// بارگذاری موقعیت موانع
for (int b = 0; b < NUM_BARRIERS; b++) {
for (int idx = 0; idx < BARRIER_WIDTH * BARRIER_HEIGHT; idx++) {
loadFile >> barriers[b][idx];
}
}
// بارگذاری لیزرها
int laserCount;
loadFile >> laserCount;
lasers.clear();
for (int i = 0; i < laserCount; i++) {
int y, x;
loadFile >> y >> x;
lasers.push_back({y, x});
}
// بارگذاری موشک‌های دشمن
int missileCount;
loadFile >> missileCount;
enemyMissiles.clear();
for (int i = 0; i < missileCount; i++) {
int y, x;
loadFile >> y >> x;
enemyMissiles.push_back({y, x});
}
// بارگذاری وضعیت بشقاب پرنده قرمز
loadFile >> ufoVisible >> ufoX >> ufoY;
loadFile.close();
cout << "Game loaded successfully!\n";
}
struct PlayerScore {
string name;
int score;
int time;
bool operator<(const PlayerScore &other) const {
if (score != other.score) return score > other.score;
return time < other.time;
}
};
void saveScore(string playerName, int score, int time) {
ofstream leaderboardFile("leaderboard.txt", ios::app);
if (!leaderboardFile) {
cout << "Error: Could not open leaderboard file.\n";
return;
}
leaderboardFile << playerName << " " << score << " " << time << "\n";
leaderboardFile.close();
cout << "Score saved to leaderboard!\n";
}
void showLeaderboard() {
ifstream leaderboardFile("leaderboard.txt");
if (!leaderboardFile) {
cout << "Error: Could not open leaderboard file.\n";
return;
}
vector<PlayerScore> scores;
string name;
int score, time;
// خواندن اطلاعات از فایل
while (leaderboardFile >> name >> score >> time) {
scores.push_back({name, score, time});
}
leaderboardFile.close();
// مرتب‌سازی امتیازات
sort(scores.begin(), scores.end());
// نمایش جدول
system("clear");
cout << "===== Leaderboard =====\n";
cout << "Rank | Name | Score | Time (s)\n";
cout << "------------------------------\n";
for (size_t i = 0; i < scores.size(); i++) {
cout << i + 1 << " | " << scores[i].name << " | " << scores[i].score << " | " << scores[i].time << "\n";
}
cout << "\nPress any key to return to the main menu.\n";
getInput(); // انتظار برای ورودی
}
void handleInput() {
char input = getInput();
if (input == 'a' || input == 'A') {
if (playerX > 0) playerX--; // حرکت به چپ
} else if (input == 'd' || input == 'D') {
if (playerX < SCREEN_WIDTH - 1) playerX++; // حرکت به راست
} else if (input == ' ') {
// شلیک چند تیر به صورت هم‌زمان
if (lasers.size() < laserCount) {
for (int i = 0; i < laserCount; i++) {
lasers.push_back({playerY - 1, playerX + (i - laserCount / 2)}); // تیرها از نقاط مختلف شلیک می‌شوند
}
}
}
}
void newGame() {
while (true) {
updateGameTime(); // به‌روزرسانی زمان بازی
renderStatus(); // نمایش وضعیت بازی
renderScreen(); // نمایش صفحه
renderEnemies(); // نمایش دشمنان
renderUFO(); // نمایش بشقاب پرنده قرمز
renderMissiles(); // نمایش موشک‌های دشمنان
renderBarriers(); // نمایش موانع
handleInput(); // دریافت ورودی بازیکن
updateLasers(); // به‌روزرسانی لیزرها
checkLaserHits(); // چک کردن برخورد لیزرها با دشمنان
checkLaserBarrierHits();// چک کردن برخورد لیزرها با موانع
updateEnemies(); // به‌روزرسانی حرکت دشمنان
updateUFO(); // به‌روزرسانی حرکت بشقاب پرنده
checkUFOHit(); // چک کردن برخورد لیزر با UFO
enemyFire(); // شلیک موشک توسط دشمنان
updateMissiles(); // به‌روزرسانی حرکت موشک‌ها
checkMissileHits(); // چک کردن برخورد موشک‌ها با بازیکن
checkMissileBarrierHits();// چک کردن برخورد موشک‌ها با موانع
// بررسی پایان سطح
if (isLevelComplete()) {
increaseDifficulty(); // افزایش سختی
resetEnemies(); // بازنشانی دشمنان برای سطح جدید
}
// تاخیر برای کنترل سرعت بازی
this_thread::sleep_for(chrono::milliseconds(enemySpeed));
}
}
void showMenu() {
while (true) {
system("clear");
setColor("32");
cout << "==========================\n";
cout << " Welcome to Space Invaders \n";
cout << "==========================\n";
resetColor();
cout << "1. New Game\n";
cout << "2. Load Game\n";
cout << "3. Save Game\n";
cout << "4. How to Play\n";
cout << "5. Leaderboard\n";
cout << "6. Exit\n";
cout << "Select an option: ";
char choice = getInput();
switch (choice) {
case '1':
newGame();
break;
case '2':
loadGame();
break;
case '3':
saveGame();
break;
case '4':
// نمایش دستورالعمل‌ها
break;
case '5':
showLeaderboard();
break;
case '6':
return;
default:
cout << "Invalid option! Please try again.\n";
this_thread::sleep_for(chrono::seconds(1));
}
}
}
int main() {
showMenu();
return 0;
}