#include #include #include // برای کار با فایل #include // برای دریافت ورودی کیبورد #include // برای مدیریت زمان #include // توابع استاندارد #include // برای دریافت تاریخ و زمان #include // برای مدیریت رشته‌ها #include // برای کنترل مکان‌نما و حذف پرش تصویر using namespace std; // تنظیمات کلی بازی const int WIDTH = 40; // عرض صفحه بازی const int HEIGHT = 20; // ارتفاع صفحه بازی // توابع کمکی برای گرافیک (جلوگیری از پرش تصویر) // انتقال مکان‌نما به مختصات (x, y) بدون پاک کردن کل صفحه void gotoxy(int x, int y) { COORD coord; coord.X = x; coord.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } // مخفی کردن نشانگر چشمک‌زن موس برای زیبایی void HideCursor() { HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO info; info.dwSize = 100; info.bVisible = FALSE; SetConsoleCursorInfo(consoleHandle, &info); } // ایجاد وقفه زمانی دقیق void waitFor(int milliseconds) { auto start = chrono::high_resolution_clock::now(); while (chrono::duration_cast(chrono::high_resolution_clock::now() - start).count() < milliseconds) { // حلقه انتظار (Busy wait) } } // کلاس توپ (Ball) class Ball { public: float x, y; // مختصات float dx, dy; // جهت حرکت bool moving; // وضعیت حرکت Ball(float startX, float startY) : x(startX), y(startY), dx(0.5f), dy(-1.0f), moving(false) {} // حرکت توپ بر اساس سرعت فعلی void move() { if (moving) { x += dx; y += dy; } } // بازنشانی توپ به مکان اولیه (بعد از باختن جان) void reset(float startX, float startY) { x = startX; y = startY; // جهت پرتاب تصادفی چپ یا راست dx = (rand() % 2 == 0 ? 0.5f : -0.5f); dy = -1.0f; moving = false; } }; // کلاس راکت (Paddle) class Paddle { public: float x; int y; int width; Paddle(int startX, int startY) : x(startX), y(startY), width(7) {} // حرکت به چپ با بررسی مرزها void moveLeft() { x -= 2; if (x < 1) x = 1; } // حرکت به راست با بررسی مرزها void moveRight() { x += 2; if (x + width > WIDTH - 1) x = WIDTH - 1 - width; } }; // کلاس آجر (Brick) class Brick { public: int x, y; bool active; // آیا آجر هنوز وجود دارد؟ int points; // امتیاز آجر Brick(int bx, int by) : x(bx), y(by), active(true), points(10) {} }; // کلاس اصلی بازی (Game Engine) class Game { private: bool gameOver; bool victory; int score; int lives; string playerName; Ball* ball; Paddle* paddle; vector bricks; public: Game(string name) { playerName = name; gameOver = false; victory = false; score = 0; lives = 3; // ایجاد اشیاء بازی paddle = new Paddle(WIDTH / 2 - 3, HEIGHT - 2); ball = new Ball(WIDTH / 2, HEIGHT - 3); // چیدمان آجرها for (int i = 0; i < 4; i++) { for (int j = 2; j < WIDTH - 2; j += 4) { bricks.push_back(Brick(j, i + 2)); } } } ~Game() { delete ball; delete paddle; } // رسم محیط بازی (بدون پرش تصویر) void draw() { gotoxy(0, 0); // پرش به ابتدای صفحه به جای پاک کردن کل آن string buffer = ""; // بافر برای ذخیره کل تصویر و چاپ یکجا // هدر بازی buffer += "PLAYER: " + playerName + " | SCORE: " + to_string(score) + " | LIVES: " + to_string(lives) + "\n"; for (int i = 0; i < WIDTH + 2; i++) buffer += "#"; buffer += "\n"; // رسم محتوا for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { if (j == 0) buffer += "#"; // دیوار چپ bool drawn = false; // رسم توپ if ((int)ball->x == j && (int)ball->y == i) { buffer += "O"; drawn = true; } // رسم راکت else if (i == paddle->y && j >= (int)paddle->x && j < (int)paddle->x + paddle->width) { buffer += "="; drawn = true; } else { // رسم آجرها for (auto& b : bricks) { if (b.active && b.x == j && b.y == i) { buffer += "[]"; drawn = true; j++; // پرش از روی کاراکتر دوم آجر break; } } } if (!drawn) buffer += " "; // فضای خالی if (j == WIDTH - 1) buffer += "#"; // دیوار راست } buffer += "\n"; } for (int i = 0; i < WIDTH + 2; i++) buffer += "#"; buffer += "\n"; // راهنما پایین صفحه if(!ball->moving) buffer += "\nPress 'SPACE' to start. 'a'/'d' to Move. 'q' Quit "; else buffer += "\n "; cout << buffer; // چاپ نهایی بافر } // دریافت ورودی از کاربر void input() { if (_kbhit()) { char current = _getch(); if (current == 'a' || current == 'A') paddle->moveLeft(); if (current == 'd' || current == 'D') paddle->moveRight(); if (current == 'q' || current == 'Q') gameOver = true; if (current == ' ') ball->moving = true; } } // منطق بازی (فیزیک و برخوردها) void logic() { if (!ball->moving) { // چسبیدن توپ به راکت قبل از پرتاب ball->x = paddle->x + paddle->width / 2; ball->y = paddle->y - 1; return; } ball->move(); // برخورد با دیوارهای چپ و راست if (ball->x <= 1 || ball->x >= WIDTH - 1) ball->dx = -ball->dx; // برخورد با سقف if (ball->y <= 0) ball->dy = -ball->dy; // برخورد با راکت if (ball->y >= paddle->y - 1 && ball->y <= paddle->y && ball->x >= paddle->x && ball->x <= paddle->x + paddle->width) { ball->dy = -ball->dy; ball->y = paddle->y - 1; } // افتادن توپ (باختن جان) if (ball->y >= HEIGHT) { lives--; ball->reset(paddle->x + paddle->width / 2, paddle->y - 1); if (lives <= 0) gameOver = true; } // برخورد با آجرها bool allDestroyed = true; for (auto& b : bricks) { if (b.active) { allDestroyed = false; if ((int)ball->x >= b.x && (int)ball->x < b.x + 2 && (int)ball->y == b.y) { b.active = false; ball->dy = -ball->dy; score += b.points; } } } // شرط پیروزی if (allDestroyed) { victory = true; gameOver = true; } } // ذخیره تاریخچه بازی در فایل void saveHistory() { ofstream outFile("game_history.txt", ios::app); // برای اضافه کردن به ته فایل if (outFile.is_open()) { // دریافت زمان فعلی time_t now = time(0); char* dt = ctime(&now); // حذف کاراکتر خط جدید از انتهای رشته زمان string timeStr = dt; if (!timeStr.empty() && timeStr.back() == '\n') timeStr.pop_back(); outFile << "Name: " << playerName << " | Score: " << score << " | Date: " << timeStr << endl; outFile.close(); } } // حلقه اصلی اجرای بازی void run() { system("cls"); // پاکسازی اولیه HideCursor(); while (!gameOver) { draw(); input(); logic(); waitFor(60); // کنترل سرعت بازی } // ذخیره امتیاز در پایان بازی saveHistory(); system("cls"); if (victory) { cout << "\n\n\t****************************\n"; cout << "\t* YOU WON! *\n"; cout << "\t* Score saved to history *\n"; cout << "\t****************************\n"; } else { cout << "\n\n\t----------------------------\n"; cout << "\t! GAME OVER !\n"; cout << "\t! Score saved to history !\n"; cout << "\t----------------------------\n"; } cout << "\nPress any key to exit..."; _getch(); } }; // توابع منو void showHelp() { system("cls"); cout << "========================================\n"; cout << " GAME HELP \n"; cout << "========================================\n"; cout << " Controls:\n"; cout << " 'a' / 'd' : Move Paddle Left/Right\n"; cout << " 'SPACE' : Launch Ball\n"; cout << " 'q' : Quit Game\n\n"; cout << " Rules:\n"; cout << " Break all bricks to win.\n"; cout << " Don't let the ball fall.\n"; cout << "\nPress any key to return..."; _getch(); } void showHistory() { system("cls"); cout << "========================================\n"; cout << " GAME HISTORY \n"; cout << "========================================\n"; ifstream inFile("game_history.txt"); string line; if (inFile.is_open()) { while (getline(inFile, line)) { cout << line << endl; } inFile.close(); } else { cout << "No history found yet.\n"; } cout << "\n========================================\n"; cout << "Press any key to return..."; _getch(); } int main() { srand(static_cast(time(0))); // تنظیم اولیه اعداد تصادفی while (true) { system("cls"); cout << "========================================\n"; cout << " BREAKOUT - MAIN MENU \n"; cout << "========================================\n"; cout << " 1. New Game\n"; cout << " 2. Game History\n"; cout << " 3. Help\n"; cout << " 4. Exit\n"; cout << "========================================\n"; cout << " Select Option: "; char choice = _getch(); if (choice == '1') { system("cls"); string pName; cout << "\nEnter Player Name: "; cin >> pName; Game breakout(pName); breakout.run(); } else if (choice == '2') { showHistory(); } else if (choice == '3') { showHelp(); } else if (choice == '4') { cout << "\nGoodbye!\n"; break; } } return 0; }