Files
2026-04-20 23:09:26 +04:30

1563 lines
48 KiB
C++

#include "game.hpp"
#include <iostream>
#include <string>
#include <conio.h>
#include <windows.h>
#include <chrono>
#include <ctime>
#include <thread>
#include <iomanip>
#include <fstream>
using namespace std;
// Structures
struct paddle
{
int x;
int width;
string paddleChar;
};
struct ball
{
int x;
int y;
int vx;
int vy;
};
struct brick
{
int x;
int y;
int width;
bool isBroken;
int color;
int CTB; // Collision TO Break
};
// Globals
const int width = 81;
const int height = 30;
int FPS = 60;
int frameDelay = 1000 / FPS;
int goldenCount = 0;
int TNTCount = 0;
int HardCount = 0;
int normalCount = 0;
const int panelx = 130;
const int panely = 5;
int score = 0;
int Broken = 0;
int life = 3;
int brickCol = 10;
int brickRow = 5;
const int brickWidth = 4;
const int brickGap = 1;
int brickColors[] = {9, 10, 11, 12, 13, 14};
brick bricks[14][8];
player Player = {};
paddle Paddle;
ball Ball;
// SetUp
void HideCursor(bool visible)
{
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
info.dwSize = 100;
info.bVisible = visible;
SetConsoleCursorInfo(consoleHandle, &info);
}
void initializeBricks();
void initializePaddle(paddle &paddle, int width);
void initializeBall(ball &Ball);
// Game
void input();
void logic(ball &);
// void render();
// void renderPanel();
bool game();
int gameDelay = 150;
bool gameOver = false;
bool bricksCount();
// Pause
void render(string pause);
void pauseMenu();
int pauseOption = 1;
// Other Prototypes
void explodeBricks(int col, int row);
void nextStage();
// Game History
player history[100] = {};
int historyCount = 0;
// Load Game
player loadedPlayer[100] = {};
int playerCount = 0;
int loadOption = 1; // for delete record index
// int main()
// {
// fstream file("loadGame.dat", ios::binary | ios::in | ios::out);
// file.seekp(0);
// player temp;
// file.read(reinterpret_cast<char *>(&temp), sizeof(player));
// file.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
// file.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
// file.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
// size_t len;
// file.read(reinterpret_cast<char *>(&len), sizeof(len));
// cout << sizeof(len) << endl;
// cout << len;
// }
bool game(int)
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
system("cls");
HideCursor(false);
life = Player.life;
score = Player.score;
pauseOption = 1;
renderPanel();
auto lastTime2 = std::chrono::steady_clock::now();
renderPanel();
while (!gameOver)
{
auto currentTime = std::chrono::steady_clock::now();
auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastTime2).count();
// broken == 50?
if (bricksCount())
{
nextStage();
Sleep(1000);
if (FPS < 120)
{
FPS += 20;
}
if (brickRow < 8)
{
brickRow++;
}
if (brickRow % 2 == 0 && brickCol < 14)
{
brickCol += 2;
}
initializeBricks();
initializePaddle(Paddle, width);
initializeBall(Ball);
}
auto frameStart = std::chrono::steady_clock::now();
input();
if (pauseOption == 2)
{
return false;
}
else if (pauseOption >= 2)
{
return true;
}
logic(Ball);
SetConsoleCursorPosition(h, {0, 5});
render();
auto frameTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - frameStart).count();
if (frameDelay > frameTime)
{
Sleep(frameDelay - frameTime); // تنظیم فاصله زمانی برای رسیدن به FPS ثابت
}
}
if (gameOver == true)
{
life--;
}
while (life > 0)
{
HideCursor(false);
initializePaddle(Paddle, width);
initializeBall(Ball);
COORD cursor = {0, 5};
gameOver = false;
auto lastTime = std::chrono::steady_clock::now();
SetConsoleCursorPosition(h, cursor);
render();
renderPanel();
char start = _getch();
if (start == 27)
{
pauseMenu();
}
while (!gameOver)
{
auto currentTime = std::chrono::steady_clock::now();
auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastTime).count();
// broken == 50?
if (bricksCount())
{
nextStage();
Sleep(1000);
if (FPS < 120)
{
FPS += 20;
}
if (brickRow < 8)
{
brickRow++;
}
if (brickRow % 2 == 0 && brickCol < 14)
{
brickCol += 2;
}
initializeBricks();
initializePaddle(Paddle, width);
initializeBall(Ball);
}
input();
if (pauseOption == 2)
{
return false;
}
else if (pauseOption >= 2)
{
return true;
}
if (elapsedTime > 75)
{
logic(Ball);
SetConsoleCursorPosition(h, cursor);
render();
lastTime = currentTime;
}
}
if (gameOver == true)
{
life--;
}
}
return true;
}
bool game()
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
system("cls");
HideCursor(false);
initializeBricks();
initializePaddle(Paddle, width);
initializeBall(Ball);
life = 3;
score = 0;
pauseOption = 1;
Broken = 0;
goldenCount = 0;
TNTCount = 0;
HardCount = 0;
normalCount = 0;
while (life > 0)
{
HideCursor(false);
initializePaddle(Paddle, width);
initializeBall(Ball);
COORD cursor = {0, 5};
gameOver = false;
auto lastTime = std::chrono::steady_clock::now();
SetConsoleCursorPosition(h, cursor);
render();
renderPanel();
char start = _getch();
if (start == 27)
{
pauseMenu();
}
while (!gameOver)
{
// broken == 50?
if (bricksCount())
{
nextStage();
Sleep(1000);
if (brickRow < 8)
{
brickRow++;
}
if (brickRow % 2 == 0 && brickCol < 14)
{
brickCol += 2;
}
initializeBricks();
initializePaddle(Paddle, width);
initializeBall(Ball);
SetConsoleCursorPosition(h, cursor);
HideCursor(false);
Broken = 0;
render();
renderPanel();
_getch();
}
auto frameStart = std::chrono::steady_clock::now();
input();
if (pauseOption == 2)
{
return false;
}
else if (pauseOption >= 2)
{
return true;
}
logic(Ball);
SetConsoleCursorPosition(h, cursor);
render();
auto frameTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - frameStart).count();
if (frameDelay > frameTime)
{
Sleep(frameDelay - frameTime); // تنظیم فاصله زمانی برای رسیدن به FPS ثابت
}
}
if (gameOver == true)
{
life--;
}
}
return true;
}
void initializeBricks()
{
int totalBrickWidth = brickCol * brickWidth + (brickCol - 1) * brickGap;
int start = (width - totalBrickWidth) / 2;
srand(time(0));
for (int col = 0; col < brickCol; col++)
{
for (int row = 0; row < brickRow; row++)
{
bricks[col][row].x = start + col * (brickWidth + brickGap);
bricks[col][row].y = row * 2 + 3;
bricks[col][row].width = brickWidth;
bricks[col][row].isBroken = false;
int r = rand() % 100;
if (r < 20)
{
bricks[col][row].color = 9;
}
else if (r < 40)
{
bricks[col][row].color = 10;
}
// else if (r < 60)
// {
// bricks[col][row].color = 11;
// }
else if (r < 80)
{
bricks[col][row].color = 13;
}
else if (r < 90)
{
bricks[col][row].color = 12;
}
else
{
bricks[col][row].color = 14;
}
if (bricks[col][row].color == 9)
{
bricks[col][row].CTB = 2;
}
else
{
bricks[col][row].CTB = 1;
}
}
}
}
void initializePaddle(paddle &Paddle, int width)
{
Paddle.width = 7;
Paddle.paddleChar = "━";
Paddle.x = (width - Paddle.width) / 2;
}
void initializeBall(ball &Ball)
{
srand(time(0));
Ball.x = Paddle.x + 3;
Ball.y = height - 3;
int sign = rand() % 2;
int value = rand() % 2 + 1;
Ball.vx = sign == 0 ? 1 : -1;
Ball.vy = value;
}
void render()
{
for (int y = 0; y < 30; y++)
{
cout << setw(45) << "";
for (int x = 0; x < 81; x++)
{
string c = " ";
if (y == 0 && x == 0)
{
c = "┌";
}
else if (y == 29 && x == 0)
{
c = "└";
}
else if (y == 29 && x == 80)
{
c = "┘";
}
else if (y == 0 && x == 80)
{
c = "┐";
}
else if (y == 0 && (x > 0 && x < 80))
{
c = "─";
}
else if (y == 29 && (x > 0 && x < 80))
{
c = "─";
}
else if (x == 0 && (y > 0 && y < 29))
{
c = "│";
}
else if (x == 80 && (y > 0 && y < 29))
{
c = "│";
}
for (int col = 0; col < brickCol; col++)
{
for (int row = 0; row < brickRow; row++)
{
if (y == bricks[col][row].y &&
x >= bricks[col][row].x &&
x < bricks[col][row].x + bricks[col][row].width && bricks[col][row].isBroken == false)
{
setColor(bricks[col][row].color);
c = "█";
}
}
}
if (y == height - 2 &&
x >= Paddle.x &&
x < Paddle.x + Paddle.width)
{
c = Paddle.paddleChar;
}
if (x > 0 && x < width - 1 && y > 0 && y < height - 1)
{
if (x == Ball.x && y == Ball.y)
c = "●";
}
cout << c;
setColor(7);
}
cout << endl;
}
}
void render(string pause)
{
for (int y = 0; y < 30; y++)
{
cout << setw(45) << "";
for (int x = 0; x < 81; x++)
{
string c = " ";
if (y == 0 && x == 0)
{
c = "┌";
}
else if (y == 29 && x == 0)
{
c = "└";
}
else if (y == 29 && x == 80)
{
c = "┘";
}
else if (y == 0 && x == 80)
{
c = "┐";
}
else if (y == 0 && (x > 0 && x < 80))
{
c = "─";
}
else if (y == 29 && (x > 0 && x < 80))
{
c = "─";
}
else if (x == 0 && (y > 0 && y < 29))
{
c = "│";
}
else if (x == 80 && (y > 0 && y < 29))
{
c = "│";
}
for (int col = 0; col < 10; col++)
{
for (int row = 0; row < 5; row++)
{
if (y == bricks[col][row].y &&
x >= bricks[col][row].x &&
x < bricks[col][row].x + bricks[col][row].width && bricks[col][row].isBroken == false)
{
c = "█";
}
}
}
if (y == height - 2 &&
x >= Paddle.x &&
x < Paddle.x + Paddle.width)
{
c = Paddle.paddleChar;
}
if (x > 0 && x < width - 1 && y > 0 && y < height - 1)
{
if (x == Ball.x && y == Ball.y)
c = "●";
}
cout << c;
}
cout << endl;
}
}
void input()
{
if (_kbhit())
{
char input = _getch();
switch (input)
{
case 'D':
case 'd':
{
if (Paddle.x + Paddle.width < 78 && (Ball.vx > 1 || Ball.vx < -1))
{
Paddle.x += 3;
}
else if (Paddle.x + Paddle.width < 79)
{
Paddle.x += 2;
}
break;
}
case 'A':
case 'a':
{
if (Paddle.x > 3 && (Ball.vx > 1 || Ball.vx < -1))
{
Paddle.x -= 3;
}
else if (Paddle.x > 2)
{
Paddle.x -= 2;
}
break;
}
case 27:
{
pauseMenu();
switch (pauseOption)
{
case 2:
{
}
}
break;
}
}
}
}
void playBeep(int F, int T)
{
thread t(Beep, F, T);
t.detach();
}
void bricksLogic(brick &B, int i, int j)
{
B.CTB--;
if (B.color == 9 && B.CTB == 1)
{
playBeep(600 + 9 * 50, 60);
B.color = 11;
}
if (B.CTB <= 0)
{
B.isBroken = true;
if (B.color == 12)
{
TNTCount++;
playBeep(600 + 12 * 50, 60);
explodeBricks(i, j);
}
if (B.color == 14)
{
goldenCount++;
playBeep(600 + 14 * 50, 60);
score += 20;
}
else
{
if (B.color == 14)
{
HardCount++;
}
else
{
normalCount++;
}
playBeep(600, 60);
score += 10;
}
Broken++;
renderPanel();
}
}
void logic(ball &)
{
// endGame -> you will lose a life
if (Ball.y >= height - 1)
{
// playBeep(200, 200);
// playBeep(300, 100);
// playBeep(400, 100);
// playBeep(500, 100);
playBeep(500, 300);
playBeep(350, 400);
playBeep(200, 600);
gameOver = true;
}
// Wall Collision
if (Ball.x >= width - 1 || Ball.x <= 1)
{
playBeep(520, 80);
Ball.vx > 0 ? Ball.vx = 1 : Ball.vx = -1;
Ball.vx *= -1;
}
if (Ball.y <= 1)
{
playBeep(520, 80);
Ball.vy *= -1;
}
// Brick Collision
bool collision = false;
for (int i = 0; i < brickCol && !collision; i++)
{
for (int j = 0; j < brickRow; j++)
{
// from below
if (Ball.x >= bricks[i][j].x - 1 &&
Ball.x < bricks[i][j].x + bricks[i][j].width + 1 &&
(Ball.y == bricks[i][j].y + 1) && bricks[i][j].isBroken == false && Ball.vy < 0)
{
collision = true;
Ball.vx > 0 ? Ball.vx = 1 : Ball.vx = -1;
Ball.vy > 0 ? Ball.vy = 1 : Ball.vy = -1;
Ball.vy *= -1;
if (j < brickRow - 1)
{
if (((Ball.y + Ball.vy) == bricks[i][j + 1].y) &&
bricks[i][j + 1].isBroken == false && (Ball.x + Ball.vx >= bricks[i][j + 1].x) &&
(Ball.x + Ball.vx < bricks[i][j + 1].x + bricks[i][j + 1].width))
{
Ball.y = bricks[i][j + 1].y - 2;
}
}
bricksLogic(bricks[i][j], i, j);
break;
}
// from left
else if (Ball.x == bricks[i][j].x - 1 &&
(Ball.y >= bricks[i][j].y - 1 && Ball.y <= bricks[i][j].y + 1) &&
bricks[i][j].isBroken == false && Ball.vx > 0)
{
collision = true;
Ball.vx > 0 ? Ball.vx = 1 : Ball.vx = -1;
Ball.vy > 0 ? Ball.vy = 1 : Ball.vy = -1;
Ball.vx *= -1;
if (i > 0)
{
// (Ball.x + Ball.vx) >= bricks[i - 1][j].x &&
if ((Ball.x + Ball.vx) >= bricks[i - 1][j].x &&
(Ball.x + Ball.vx) < bricks[i - 1][j].x + brickWidth &&
bricks[i - 1][j].isBroken == false && (Ball.y + Ball.vy == bricks[i - 1][j].y))
{
Ball.x += bricks[i - 1][j].x + brickWidth - 1 - (Ball.x + Ball.vx) + 1;
}
}
bricksLogic(bricks[i][j], i, j);
break;
}
// from right
else if (Ball.x == bricks[i][j].x + bricks[i][j].width + 1 &&
(Ball.y >= bricks[i][j].y - 1 && Ball.y <= bricks[i][j].y + 1) &&
bricks[i][j].isBroken == false && Ball.vx < 0)
{
collision = true;
Ball.vx > 0 ? Ball.vx = 1 : Ball.vx = -1;
Ball.vy > 0 ? Ball.vy = 1 : Ball.vy = -1;
Ball.vx *= -1;
if (i < brickCol - 1)
{
// (Ball.x + Ball.vx) >= bricks[i - 1][j].x &&
if ((Ball.x + Ball.vx) >= bricks[i + 1][j].x &&
(Ball.x + Ball.vx) < bricks[i + 1][j].x + brickWidth &&
bricks[i + 1][j].isBroken == false && (Ball.y + Ball.vy == bricks[i + 1][j].y))
{
Ball.x -= Ball.x + Ball.vx - bricks[i + 1][j].x + 1;
}
}
bricksLogic(bricks[i][j], i, j);
renderPanel();
break;
}
// from above
else if (Ball.x >= bricks[i][j].x - 1 &&
Ball.x < bricks[i][j].x + bricks[i][j].width + 1 &&
(Ball.y == bricks[i][j].y - 1) && bricks[i][j].isBroken == false && Ball.vy > 0)
{
collision = true;
Ball.vx > 0 ? Ball.vx = 1 : Ball.vx = -1;
Ball.vy > 0 ? Ball.vy = 1 : Ball.vy = -1;
Ball.vy *= -1;
if (j > 0)
{
if (((Ball.y + Ball.vy) == bricks[i][j - 1].y) &&
bricks[i][j - 1].isBroken == false && (Ball.x + Ball.vx >= bricks[i][j - 1].x) && (Ball.x + Ball.vx < bricks[i][j - 1].x + bricks[i][j + 1].width))
{
Ball.y += 2;
}
}
bricksLogic(bricks[i][j], i, j);
break;
}
}
}
int nextY = Ball.y + Ball.vx;
// Paddle Collision
int delta = 0;
if (Ball.x >= Paddle.x &&
Ball.x < Paddle.x + Paddle.width && Ball.y == height - 3)
{
playBeep(520, 80);
Ball.vx > 0 ? Ball.vx = 1 : Ball.vx = -1;
Ball.vy > 0 ? Ball.vy = 1 : Ball.vy = -1;
int pos = Paddle.x + Paddle.width - Ball.x;
switch (pos)
{
// case 0:
case 2:
case 1:
{
Ball.vy *= -1;
if (Ball.x < 20 && Ball.vx < 0 && Ball.vx < 0)
{
Ball.vx *= -1;
}
Ball.vx > 0 ? delta = 2 : delta = 0;
break;
}
// case 8:/
case 6:
case 7:
{
Ball.vy *= -1;
if (Ball.x > width - 20 && Ball.vx > 0)
{
Ball.vx *= -1;
}
Ball.vx > 0 ? delta = 0 : delta = -2;
break;
}
case 4:
{
// srand(time(0));
// Ball.vx = (rand() % 2 == 0) ? 1 : -1;
}
case 5:
case 3:
{
// Ball.vx = 0;
Ball.vy *= -1;
break;
}
}
}
Ball.vx += delta;
if (Ball.x + Ball.vx > width - 1)
{
Ball.x = width - 1;
}
else if (Ball.x + Ball.vx < 1)
{
Ball.x = 1;
}
else
{
Ball.x += Ball.vx;
}
Ball.y += Ball.vy;
}
bool bricksCount()
{
for (int i = 0; i < brickCol; i++)
{
for (int j = 0; j < brickRow; j++)
{
if (bricks[i][j].isBroken == false)
{
return false;
}
}
}
return true;
}
void renderPanel()
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(h, {panelx, panely});
cout << "┌───────────────────┐";
SetConsoleCursorPosition(h, {panelx, panely + 1});
cout << "│ Game Info │";
SetConsoleCursorPosition(h, {panelx, panely + 2});
cout << "├───────────────────┤";
SetConsoleCursorPosition(h, {panelx, panely + 3});
cout << "│ Score: " << setw(5) << score << " │";
SetConsoleCursorPosition(h, {panelx, panely + 4});
cout << "│ Life: " << setw(5) << life << " │";
SetConsoleCursorPosition(h, {panelx, panely + 5});
cout << "│ Bricks: " << setw(5) << (brickCol * brickRow) - Broken << " │";
SetConsoleCursorPosition(h, {panelx, panely + 6});
cout << "└───────────────────┘";
}
void selectPO(int option, int crrOption) // PO: pause option
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
if (option == crrOption)
{
SetConsoleTextAttribute(h, 1);
}
else
{
SetConsoleTextAttribute(h, 15);
}
}
void pauseMenu()
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h, 8);
SetConsoleCursorPosition(h, {0, 5});
render("pause");
renderPanel();
SetConsoleTextAttribute(h, 15);
SetConsoleCursorPosition(h, {65, 13});
cout << "╔══════════════════PAUSE══════════════════╗";
for (int i = 0; i < 13; i++)
{
SetConsoleCursorPosition(h, {65, SHORT(14 + i)});
cout << "║ ║";
}
SetConsoleCursorPosition(h, {65, 26});
SetConsoleTextAttribute(h, 15);
cout << "╚═════════════════════════════════════════╝";
while (true)
{
selectPO(1, pauseOption);
SetConsoleCursorPosition(h, {80, 14});
cout << "╔═══════════╗";
SetConsoleCursorPosition(h, {80, 15});
cout << "║ Resume ║";
SetConsoleCursorPosition(h, {80, 16});
cout << "╚═══════════╝";
selectPO(2, pauseOption);
SetConsoleCursorPosition(h, {80, 17});
cout << "╔═══════════╗";
SetConsoleCursorPosition(h, {80, 18});
cout << "║ Restart ║";
SetConsoleCursorPosition(h, {80, 19});
cout << "╚═══════════╝";
selectPO(3, pauseOption);
SetConsoleCursorPosition(h, {80, 20});
cout << "╔═══════════╗";
SetConsoleCursorPosition(h, {80, 21});
cout << "║ Save Game ║";
SetConsoleCursorPosition(h, {80, 22});
cout << "╚═══════════╝";
selectPO(4, pauseOption);
SetConsoleCursorPosition(h, {80, 23});
cout << "╔═══════════╗";
SetConsoleCursorPosition(h, {80, 24});
cout << "║ Quit ║";
SetConsoleCursorPosition(h, {80, 25});
cout << "╚═══════════╝";
while (true)
{
if (_kbhit())
{
char userInput = _getch();
if ((userInput == 'w' || userInput == 'W') && pauseOption > 1)
{
pauseOption -= 1;
break;
}
else if ((userInput == 's' || userInput == 'S') && pauseOption < 4)
{
pauseOption += 1;
break;
}
if (userInput == 13)
{
if (pauseOption <= 2)
{
SetConsoleTextAttribute(h, 7);
renderPanel();
}
return;
}
}
}
Sleep(10);
}
}
void setColor(int color)
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h, color);
}
void explodeBricks(int col, int row)
{
for (int dx = -1; dx <= 1; dx++)
{
for (int dy = -1; dy <= 1; dy++)
{
if (dx == 0 && dy == 0)
continue;
int c = col + dx;
int r = row + dy;
if (c >= 0 && c < brickCol && r >= 0 && r < brickRow)
{
if (!bricks[c][r].isBroken && !(c == col && r == row))
{
bricks[c][r].isBroken = true;
if (bricks[c][r].color == 14)
{
goldenCount++;
score += 20;
}
else
{
if (bricks[c][r].color == 9 || bricks[c][r].color == 11)
{
HardCount++;
}
else
{
normalCount++;
}
score += 10;
}
Broken++;
}
}
}
}
}
void saveHistory()
{
time_t now = time(nullptr);
tm *local = localtime(&now);
strftime(Player.date, 80, "%Y-%m(%b)-%d(%a)", local);
strftime(Player.time, 80, "%H:%M", local);
char *pointer = strstr(Player.name, "(auto save)"); // پیدا کردن کلمه
if (pointer != NULL)
{
int length = strlen("(auto save)");
// کپی کردن ادامه رشته روی بخش پیدا شده
strcpy(pointer, pointer + length);
}
ofstream file("history.txt", ios::app);
if (file.fail())
return;
file << Player.name << " "
<< Player.date << " "
<< Player.time << " "
<< score << endl; // PLayer.score = scores
file.close();
ofstream scores("scores.txt", ios::out | ios::app);
if (scores.fail())
return;
scores << Player.name << " "
<< goldenCount << " "
<< TNTCount << " "
<< HardCount << " "
<< normalCount << endl;
scores.close();
}
void loadScoresAndPrint(char name[])
{
// T: Tmep
string Tname;
int TgoldenCount = 0;
int TeTNTCount = 0;
int THardCount = 0;
int TnormalCount = 0;
ifstream scores("scores.txt", ios::in);
if (scores.fail())
return;
while (scores >> Tname >> TgoldenCount >> TNTCount >> THardCount >> TnormalCount)
{
if (Tname == name)
{
break;
}
}
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
system("cls");
setColor(7);
SetConsoleCursorPosition(h, {68, 15});
cout << "╔══════════════════════════════╗";
SetConsoleCursorPosition(h, {68, 16});
cout << "║ ║";
SetConsoleCursorPosition(h, {68, 17});
cout << "║ "; setColor(5); cout << "YOU HEAT "; setColor(7); cout <<" ║";
SetConsoleCursorPosition(h, {68, 18});
cout << "║ " << "\033[38;5;196mTNT: " << TNTCount;
SetConsoleCursorPosition(h, {99, 18});
cout << "\033[0m║";
SetConsoleCursorPosition(h, {68, 19});
cout << "║ ║";
SetConsoleCursorPosition(h, {68, 20});
cout << "║ " << "\033[38;5;226mGolden: " << TgoldenCount;
SetConsoleCursorPosition(h, {99, 20});
cout << "\033[0m║";
SetConsoleCursorPosition(h, {68, 21});
cout << "║ ║";
SetConsoleCursorPosition(h, {68, 22});
cout << "║ " << "\033[38;5;33mHard: " << THardCount;
SetConsoleCursorPosition(h, {99, 22});
cout << "\033[0m║";
SetConsoleCursorPosition(h, {68, 23});
cout << "║ ║";
SetConsoleCursorPosition(h, {68, 24});
cout << "║ " << "\033[38;5;181mNormal: " << TnormalCount;
SetConsoleCursorPosition(h, {99, 24});
cout << "\033[0m║";
SetConsoleCursorPosition(h, {68, 25});
cout << "\033[0m╚══════════════════════════════╝";
}
int sort()
{
if (historyCount == 1)
{
return history[0].score;
}
int high;
for (int i = 0; i < historyCount - 1; i++)
{
for (int j = 0; j < historyCount - i - 1; j++)
{
if (history[j].score < history[j + 1].score)
{
swap(history[j], history[j + 1]);
}
}
}
return history[0].score;
}
void loadHistory()
{
historyCount = 0;
ifstream file("history.txt");
file.seekg(0);
if (file.is_open())
{
while (file >> history[historyCount].name >> history[historyCount].date >> history[historyCount].time >> history[historyCount].score)
{
historyCount++;
}
}
file.close();
}
int Hoption = 1; // History option
void setHoptioncolor(int crrOption, int option)
{
if (crrOption == option)
{
setColor(13);
}
else
{
setColor(7);
}
}
bool printHistory(int historyCount)
{
setColor(5);
system("cls");
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(h, {54, 3});
cout << "==============================================================\n";
cout << setw(54) << "" << " GAME HISTORY\n";
cout << setw(54) << "" << "==============================================================\n\n";
cout << setw(54) << "";
cout << left
<< setw(6) << "Rank"
<< setw(15) << "Name"
<< setw(25) << "Date"
<< setw(10) << "Time"
<< setw(10) << "Score"
// << setw(8) << "Lives"
// << setw(8) << "Result"
<< endl;
cout << setw(54) << "" << "--------------------------------------------------------------\n";
setColor(7);
while (true)
{
SetConsoleCursorPosition(h, {0, 9});
for (int i = 0; i < historyCount; i++)
{
setHoptioncolor(Hoption, i + 1);
cout << setw(54) << "";
cout << left
<< setw(6) << i + 1
<< setw(15) << history[i].name
<< setw(25) << history[i].date
<< setw(10) << history[i].time
<< setw(10) << history[i].score
// << setw(8) << history[i].life
// << setw(8) << (history[i].win ? "WIN" : "LOSE")
<< endl;
}
setColor(5);
cout << setw(54) << "" << "==============================================================\n";
while (true)
{
if (_kbhit())
{
char userInput = _getch();
if ((userInput == 'w' || userInput == 'W') && Hoption > 1)
{
Hoption -= 1;
break;
}
else if ((userInput == 's' || userInput == 'S') && Hoption < historyCount)
{
Hoption += 1;
break;
}
else if (userInput == 13)
{
return true;
}
else if (userInput == 8)
{
return false;
}
}
}
}
setColor(7);
_getch();
}
void saveGame(player &p)
{
p.score = score;
p.life = life;
p.isActive = false;
time_t now = time(nullptr);
tm *local = localtime(&now);
strftime(Player.date, 80, "%Y-%m(%b)-%d(%a)", local);
strftime(Player.time, 80, "%H:%M", local);
// maybe ios::app
ofstream fOut("loadGame.dat", ios::app | ios::binary);
if (fOut.is_open())
{
fOut.write(reinterpret_cast<char *>(&p), sizeof(player));
fOut.write(reinterpret_cast<char *>(&Ball), sizeof(ball));
fOut.write(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
fOut.write(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len = Paddle.paddleChar.size();
fOut.write(reinterpret_cast<char *>(&len), sizeof(len));
fOut.write(Paddle.paddleChar.c_str(), len);
fOut.write(reinterpret_cast<char *>(&brickCol), sizeof(int));
fOut.write(reinterpret_cast<char *>(&brickRow), sizeof(int));
fOut.write(reinterpret_cast<char *>(&bricks), sizeof(brick) * brickCol * brickRow);
fOut.write(reinterpret_cast<char *>(&Broken), sizeof(int));
fOut.write(reinterpret_cast<char *>(&goldenCount), sizeof(int));
fOut.write(reinterpret_cast<char *>(&TNTCount), sizeof(int));
fOut.write(reinterpret_cast<char *>(&HardCount), sizeof(int));
fOut.write(reinterpret_cast<char *>(&normalCount), sizeof(int));
}
fOut.seekp(0, ios::end);
fOut.close();
}
// Half AI
void setAndMarkAsActive(int index)
{
// باز کردن فایل در حالت خواندن و نوشتن همزمان (ios::in | ios::out)
fstream file("loadGame.dat", ios::binary | ios::in | ios::out);
int count = 1;
player temp;
if (file.is_open())
{
if (index == 1)
{
while (file.read(reinterpret_cast<char *>(&temp), sizeof(player)))
{
if (temp.isActive == false)
{
int pointer = file.tellp();
int pos = pointer - sizeof(player);
temp.isActive = true;
char *find = strstr(temp.name, "(auto save)"); // پیدا کردن کلمه
if (find != NULL)
{
int length = strlen("(auto save)");
// کپی کردن ادامه رشته روی بخش پیدا شده
strcpy(find, find + length);
}
Player = temp;
file.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
file.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
file.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len;
file.read(reinterpret_cast<char *>(&len), sizeof(len)); // خواندن طول
Paddle.paddleChar.resize(len); // آماده‌سازی فضا برای استرینگ
file.read(&Paddle.paddleChar[0], len); // خواندن متن
file.read(reinterpret_cast<char *>(&brickCol), sizeof(int));
file.read(reinterpret_cast<char *>(&brickRow), sizeof(int));
file.read(reinterpret_cast<char *>(&bricks), sizeof(brick) * brickCol * brickRow);
file.read(reinterpret_cast<char *>(&Broken), sizeof(int));
file.read(reinterpret_cast<char *>(&goldenCount), sizeof(int));
file.read(reinterpret_cast<char *>(&TNTCount), sizeof(int));
file.read(reinterpret_cast<char *>(&HardCount), sizeof(int));
file.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
file.seekp(pos);
file.write(reinterpret_cast<char *>(&Player), sizeof(player));
break;
}
file.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
file.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
file.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len;
file.read(reinterpret_cast<char *>(&len), sizeof(len)); // خواندن طول
Paddle.paddleChar.resize(len); // آماده‌سازی فضا برای استرینگ
file.read(&Paddle.paddleChar[0], len); // خواندن متن
file.read(reinterpret_cast<char *>(&brickCol), sizeof(int));
file.read(reinterpret_cast<char *>(&brickRow), sizeof(int));
file.read(reinterpret_cast<char *>(&bricks), sizeof(brick) * brickCol * brickRow);
file.read(reinterpret_cast<char *>(&Broken), sizeof(int));
file.read(reinterpret_cast<char *>(&goldenCount), sizeof(int));
file.read(reinterpret_cast<char *>(&TNTCount), sizeof(int));
file.read(reinterpret_cast<char *>(&HardCount), sizeof(int));
file.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
}
}
else
{
while (count < index)
{
file.read(reinterpret_cast<char *>(&temp), sizeof(player));
if (temp.isActive == false)
{
count++;
}
file.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
file.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
file.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len;
file.read(reinterpret_cast<char *>(&len), sizeof(len)); // خواندن طول
Paddle.paddleChar.resize(len); // آماده‌سازی فضا برای استرینگ
file.read(&Paddle.paddleChar[0], len); // خواندن متن
file.read(reinterpret_cast<char *>(&brickCol), sizeof(int));
file.read(reinterpret_cast<char *>(&brickRow), sizeof(int));
file.read(reinterpret_cast<char *>(&bricks), sizeof(brick) * brickCol * brickRow);
file.read(reinterpret_cast<char *>(&Broken), sizeof(int));
file.read(reinterpret_cast<char *>(&goldenCount), sizeof(int));
file.read(reinterpret_cast<char *>(&TNTCount), sizeof(int));
file.read(reinterpret_cast<char *>(&HardCount), sizeof(int));
file.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
}
while (file.read(reinterpret_cast<char *>(&temp), sizeof(player)))
{
if (temp.isActive == false)
{
int pointer = file.tellp();
int pos = pointer - sizeof(player);
temp.isActive = true;
char *find = strstr(temp.name, "(auto save)"); // پیدا کردن کلمه
if (find != NULL)
{
int length = strlen("(auto save)");
// کپی کردن ادامه رشته روی بخش پیدا شده
strcpy(find, find + length);
}
Player = temp;
file.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
file.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
file.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len;
file.read(reinterpret_cast<char *>(&len), sizeof(len)); // خواندن طول
Paddle.paddleChar.resize(len); // آماده‌سازی فضا برای استرینگ
file.read(&Paddle.paddleChar[0], len); // خواندن متن
file.read(reinterpret_cast<char *>(&brickCol), sizeof(int));
file.read(reinterpret_cast<char *>(&brickRow), sizeof(int));
file.read(reinterpret_cast<char *>(&bricks), sizeof(brick) * brickCol * brickRow);
file.read(reinterpret_cast<char *>(&Broken), sizeof(int));
file.read(reinterpret_cast<char *>(&goldenCount), sizeof(int));
file.read(reinterpret_cast<char *>(&TNTCount), sizeof(int));
file.read(reinterpret_cast<char *>(&HardCount), sizeof(int));
file.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
file.seekp(pos);
file.write(reinterpret_cast<char *>(&Player), sizeof(player));
break;
}
file.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
file.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
file.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len;
file.read(reinterpret_cast<char *>(&len), sizeof(len)); // خواندن طول
Paddle.paddleChar.resize(len); // آماده‌سازی فضا برای استرینگ
file.read(&Paddle.paddleChar[0], len); // خواندن متن
file.read(reinterpret_cast<char *>(&brickCol), sizeof(int));
file.read(reinterpret_cast<char *>(&brickRow), sizeof(int));
file.read(reinterpret_cast<char *>(&bricks), (sizeof(brick) * brickCol * brickRow));
file.read(reinterpret_cast<char *>(&Broken), sizeof(int));
file.read(reinterpret_cast<char *>(&goldenCount), sizeof(int));
file.read(reinterpret_cast<char *>(&TNTCount), sizeof(int));
file.read(reinterpret_cast<char *>(&HardCount), sizeof(int));
file.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
}
}
file.close();
}
}
void setLGOColor(int crrOption, int option) // LGO : Load Game Option
{
if (crrOption == option)
{
setColor(14);
}
else
{
setColor(15);
}
}
void loadPlayer()
{
playerCount = 0;
// int count = 0;
ifstream fIn("loadGame.dat", ios::in | ios::binary);
player temp;
// int index = sizeof(ball) + sizeof(paddle) + sizeof(bricks) + sizeof(int);
fIn.seekg(0);
if (fIn.is_open())
{
while (fIn.read(reinterpret_cast<char *>(&temp), sizeof(player)))
{
if (temp.isActive == false)
{
loadedPlayer[playerCount] = temp;
playerCount++;
}
fIn.read(reinterpret_cast<char *>(&Ball), sizeof(ball));
fIn.read(reinterpret_cast<char *>(&Paddle.width), sizeof(int));
fIn.read(reinterpret_cast<char *>(&Paddle.x), sizeof(int));
size_t len;
fIn.read(reinterpret_cast<char *>(&len), sizeof(len)); // خواندن طول
Paddle.paddleChar.resize(len); // آماده‌سازی فضا برای استرینگ
fIn.read(&Paddle.paddleChar[0], len); // خواندن متن
fIn.read(reinterpret_cast<char *>(&brickCol), sizeof(int));
fIn.read(reinterpret_cast<char *>(&brickRow), sizeof(int));
fIn.read(reinterpret_cast<char *>(&bricks), sizeof(brick) * brickCol * brickRow);
fIn.read(reinterpret_cast<char *>(&Broken), sizeof(int));
fIn.read(reinterpret_cast<char *>(&goldenCount), sizeof(int));
fIn.read(reinterpret_cast<char *>(&TNTCount), sizeof(int));
fIn.read(reinterpret_cast<char *>(&HardCount), sizeof(int));
fIn.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
}
}
fIn.close();
}
bool printLoadGame()
{
setColor(6);
loadOption = 1;
system("cls");
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(h, {51, 3});
cout << "=================================================================\n";
cout << setw(51) << "" << " LOAD GAME\n";
cout << setw(51) << "" << "=================================================================\n\n";
cout << setw(51) << "";
cout << left
<< setw(4) << "#"
<< setw(15) << "Name"
<< setw(10) << "Score"
<< setw(8) << "Lives"
<< setw(22) << "Date"
<< setw(10) << "Time"
<< endl;
cout << setw(51) << "" << "-----------------------------------------------------------------\n";
while (true)
{
SetConsoleCursorPosition(h, {0, 9});
for (int i = 0; i < playerCount; i++)
{
setLGOColor(loadOption, i + 1);
cout << setw(51) << "";
cout << "|" << left
<< setw(3) << i + 1
<< setw(15) << loadedPlayer[i].name
<< setw(10) << loadedPlayer[i].score
<< setw(8) << loadedPlayer[i].life
<< setw(22) << loadedPlayer[i].date
<< setw(10) << loadedPlayer[i].time
<< endl;
if (i < playerCount - 1)
{
setColor(15);
cout << setw(51) << "" << "-----------------------------------------------------------------\n";
}
}
setColor(6);
cout << setw(51) << "" << "=================================================================\n";
while (true)
{
if (_kbhit())
{
char userInput = _getch();
if ((userInput == 'w' || userInput == 'W') && loadOption > 1)
{
loadOption -= 1;
break;
}
else if ((userInput == 's' || userInput == 'S') && loadOption < playerCount)
{
loadOption += 1;
break;
}
else if (userInput == 13)
{
if (playerCount > 0)
{
return true;
}
}
else if (userInput == 8)
{
return false;
}
}
}
}
setColor(7);
}
void nextStage()
{
HideCursor(true);
system("cls");
string newGame[35][80];
for (int H = 0; H < 35; H++)
{
for (int S = 0; S < 80; S++)
{
newGame[H][S] = " ";
}
}
newGame[0][0] = "╔";
newGame[0][54] = "╗";
newGame[34][0] = "╚";
newGame[34][54] = "╝";
for (int i = 1; i < 34; i++)
{
newGame[i][0] = "║";
newGame[i][54] = "║";
}
for (int i = 1; i < 54; i++)
{
newGame[0][i] = "═";
newGame[34][i] = "═";
}
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(h, {0, 14});
for (int i = 0; i < 10; i++)
{
cout << setw(60) << "";
for (int j = 0; j < 79; j++)
{
cout << newGame[i][j];
}
cout << endl;
}
SetConsoleCursorPosition(h, {60, 23});
cout << "╚═════════════════════════════════════════════════════╝";
SetConsoleTextAttribute(h, 12);
SetConsoleCursorPosition(h, {85, 18});
cout << "Great";
SetConsoleCursorPosition(h, {77, 19});
cout << "Loading next stage...";
SetConsoleTextAttribute(h, 7);
}