#include <Windows.h>
#include <vector> // for rain objects
#include <conio.h> // for keyboard input
#include <time.h> // for timer process
#include <fstream> // for load/save record
#include <algorithm> // for sort record
#define SCREEN_LEFT 20
#define SCREEN_RIGHT 60
#define SCREEN_WIDTH (SCREEN_RIGHT - SCREEN_LEFT)
#define PATH_RECORD "Record"
using namespace std;
void MoveTo(int x, int y)
{
COORD cur = { x, y };
SetConsoleCursorPosition(
GetStdHandle(STD_OUTPUT_HANDLE), cur);
}
int Compare(const void* a, const void* b)
{
return (*(int*)a < *(int*)b);
}
COORD myPos;
vector<COORD> vRainPos;
int stage, playtime;
int rainLen, rainElapse;
void init_game()
{
myPos.X = SCREEN_WIDTH / 2;
myPos.Y = 24;
vRainPos.clear();
stage = 1;
playtime = 0;
rainLen = 1;
rainElapse = 100;
}
void next_stage()
{
myPos.X = SCREEN_WIDTH / 2;
myPos.Y = 24;
vRainPos.clear();
stage++;
// rainLen++;
rainElapse *= 0.8;
}
void rain_occur()
{
COORD coord = { (rand() % SCREEN_WIDTH), 0 };
vRainPos.push_back(coord);
}
void rain_down()
{
for (int i = 0; i < vRainPos.size(); i++)
{
vRainPos[i].Y++;
if (vRainPos[i].Y > 24)
vRainPos.erase(vRainPos.begin() + i);
}
}
bool is_death()
{
for (int i = 0; i < vRainPos.size(); i++)
{
if ((myPos.X == vRainPos[i].X) &&
(myPos.Y <= vRainPos[i].Y && myPos.Y > vRainPos[i].Y - rainLen))
return true;
}
return false;
}
int update_record(int record[32])
{
FILE* file;
int nElem;
// Open record file (create if not exists)
if (fopen_s(&file, PATH_RECORD, "r+") != 0)
fopen_s(&file, PATH_RECORD, "w+");
// Load record from file
nElem = fread(record, sizeof(int), 5, file);
// Push new record and sort
record[nElem] = playtime;
nElem++;
qsort(record, nElem, sizeof(int), Compare);
// Save updated record to file
rewind(file);
fwrite(record, sizeof(int), min(nElem, 5), file);
fclose(file);
return min(nElem, 5);
}
void onPaint()
{
// Clear screen
system("cls");
// Display me
MoveTo(SCREEN_LEFT + myPos.X, 24);
_putch('@');
// Display rains
for (int i = 0; i < vRainPos.size(); i++)
{
for (int len = 0; len < rainLen; len++)
{
MoveTo(SCREEN_LEFT + vRainPos[i].X, vRainPos[i].Y - len);
_putch('*');
}
}
// Display screen wall
for (int y = 0; y < 25; y++)
{
MoveTo(SCREEN_LEFT, y);
_putch('I');
MoveTo(SCREEN_RIGHT, y);
_putch('I');
}
// Display stage number
MoveTo(2, 1);
printf("[%d stage]", stage);
// Display play time
MoveTo(2, 3);
printf("[d : d]", playtime/60, playtime`);
}
void onKeyboard()
{
switch (tolower(_getch())) {
case 'd':
if (myPos.X < SCREEN_WIDTH - 1)
myPos.X++;
break;
case 'a':
if (myPos.X > 0)
myPos.X--;
break;
}
}
int main()
{
clock_t clocks[32]; // for timer process
srand(GetTickCount());
while (true)
{
init_game();
for (int i = 0; i < 32; i++)
clocks[i] = clock();
while (!is_death())
{
// Process keyboard command
if (_kbhit())
{
onKeyboard();
onPaint();
}
// Process rain occur
if (clock() > clocks[1] + rainElapse)
{
clocks[1] = clock();
rain_occur();
onPaint();
}
// Process rain down
if (clock() > clocks[2] + rainElapse)
{
clocks[2] = clock();
rain_down();
onPaint();
}
// Process stage up
if (clock() > clocks[3] + 15000)
{
clocks[3] = clock();
next_stage();
onPaint();
}
// Update play time
playtime = (clock() - clocks[0]) / 1000;
}
// Get newely updated record
int record[32], nElem;
nElem = update_record(record);
// Display retry message box with record list
char text[256] = { 0 }, format[32];
for (int i = 0; i < nElem; i++)
{
sprintf_s(format ,"%d. d : d \n", i+1, record[i]/60, record[i]`);
strcat_s(text, format);
}
sprintf_s(format, "You : d : d \n", playtime/60, playtime`);
strcat_s(text, format);
if (MessageBoxA(NULL, text, "게임 오버", MB_RETRYCANCEL) == IDCANCEL)
break;
}
return 0;
}
댓글 0