本帖最后由 人造人 于 2018-2-8 18:36 编辑
2018-02-08 更新
就差自动翻开的部分了吧
#include <iostream>
#include <string>
#include <ctime>
#include <windows.h>
#include <conio.h>
struct MapElem
{
bool status;
bool is_mine;
bool flag;
int count;
};
const int MAP_X = 16;
const int MAP_Y = 16;
MapElem map[MAP_X][MAP_Y];
void GlobalInit(void)
{
for(int i = 0; i < MAP_X; ++i)
{
for(int j = 0; j < MAP_Y; ++j)
{
map[i][j].is_mine = false;
map[i][j].status = false;
map[i][j].flag = false;
map[i][j].count = 0;
}
}
}
// 隐藏CMD窗口光标
void HideCursor(void)
{
CONSOLE_CURSOR_INFO cci;
cci.bVisible = FALSE;
cci.dwSize = sizeof(cci);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle, &cci);
}
static void GotoXY(int x, int y)
{
COORD c;
c.X = x * 2;
c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
static void DrawString(const char *str, int color)
{
static const WORD attr[] = {
FOREGROUND_RED | FOREGROUND_INTENSITY, //红色
FOREGROUND_GREEN | FOREGROUND_INTENSITY, //绿色
FOREGROUND_BLUE | FOREGROUND_INTENSITY, //蓝色
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY //白色
};
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD NumberOfAttrsWritten;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
printf(str);
FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attr[color], strlen(str), csbi.dwCursorPosition, &NumberOfAttrsWritten);
}
void SetMine(int num)
{
for(int i = 0; i < num; ++i)
{
int x, y;
do
{
x = rand() % MAP_X;
y = rand() % MAP_Y;
}
while(map[x][y].is_mine);
map[x][y].is_mine = true;
}
}
void ShowCount(int x, int y, int color)
{
if(!map[x][y].count)
{
DrawString("∷", color);
return;
}
char buf[3] = "①";
buf[1] += map[x][y].count - 1;
DrawString(buf, color);
}
const int MAP_OFFSET_X = 20;
const int MAP_OFFSET_Y = 10;
void DrawMap(void)
{
int color;
for(int i = 0; i < MAP_X; ++i)
{
for(int j = 0; j < MAP_Y; ++j)
{
if(map[i][j].flag)
color = 1;
else
color = 3;
GotoXY(i + MAP_OFFSET_X, j + MAP_OFFSET_Y);
if(map[i][j].flag)
{
DrawString("◎", color);
continue;
}
if(map[i][j].status)
{
if(map[i][j].is_mine)
DrawString("★", color);
else
ShowCount(i, j, color);
}
else
DrawString("■", color);
}
}
}
void UpdateCursor(POINT po)
{
DrawMap();
GotoXY(po.x + MAP_OFFSET_X, po.y + MAP_OFFSET_Y);
DrawString("□", 3);
}
bool SelectTarget(POINT cur)
{
if(map[cur.x][cur.y].status)
return false;
map[cur.x][cur.y].status = true;
DrawMap();
if(map[cur.x][cur.y].is_mine)
{
GotoXY(cur.x + MAP_OFFSET_X, cur.y + MAP_OFFSET_Y);
DrawString("★", 0);
return true;
}
return false;
}
void ShowMap(void)
{
int color;
for(int i = 0; i < MAP_X; ++i)
{
for(int j = 0; j < MAP_Y; ++j)
{
if(!map[i][j].status)
{
if(map[i][j].flag)
color = 1;
else
color = 3;
GotoXY(i + MAP_OFFSET_X, j + MAP_OFFSET_Y);
if(map[i][j].is_mine)
DrawString("★", color);
else
ShowCount(i, j, color);
}
}
}
}
int GetCount(int x, int y)
{
int count = 0;
// 左上角 -> 右上角
for(int i = 0; i < 3; ++i)
if((x - 1 + i >= 0) && (y - 1 >= 0))
if(map[x - 1 + i][y - 1].is_mine)
++count;
// 左下角 -> 右下角
for(int i = 0; i < 3; ++i)
if((x - 1 + i >= 0) && (y + 1 < MAP_Y))
if(map[x - 1 + i][y + 1].is_mine)
++count;
// 左边
if(x - 1 >= 0) // 有左边吗?
if(map[x - 1][y].is_mine)
++count;
// 右边
if(x + 1 < MAP_X) // 有右边吗?
if(map[x + 1][y].is_mine)
++count;
return count;
}
void GenerateCount(void)
{
for(int i = 0; i < MAP_X; ++i)
{
for(int j = 0; j < MAP_Y; ++j)
{
if(!map[i][j].is_mine)
map[i][j].count = GetCount(i, j);
}
}
}
int main(void)
{
srand((unsigned int)time(nullptr));
HideCursor();
GlobalInit();
SetMine(30);
GenerateCount();
DrawMap();
POINT cur = {MAP_X / 2, MAP_Y / 2};
UpdateCursor(cur);
char command;
while(1)
{
command = _getch();
switch(command)
{
case 'q':
case 'Q':
goto EXIT;
case 'w':
case 'W':
if(cur.y > 0)
{
--cur.y;
UpdateCursor(cur);
}
break;
case 's':
case 'S':
if(cur.y < MAP_Y - 1)
{
++cur.y;
UpdateCursor(cur);
}
break;
case 'a':
case 'A':
if(cur.x > 0)
{
--cur.x;
UpdateCursor(cur);
}
break;
case 'd':
case 'D':
if(cur.x < MAP_X - 1)
{
++cur.x;
UpdateCursor(cur);
}
break;
case 'f':
case 'F':
if(!map[cur.x][cur.y].status)
{
map[cur.x][cur.y].flag = !map[cur.x][cur.y].flag;
DrawMap();
}
break;
case ' ':
if(!map[cur.x][cur.y].flag)
if(SelectTarget(cur))
goto EXIT;
break;
}
}
EXIT:
ShowMap();
GotoXY(0, 34);
return 0;
}
|