基于c++控制台的扫雷游戏
Screen 类用于与控制台交互
gotoxy(short x, short y)跳转到控制台的指定位置
void Init() 获取控制台 句柄
bool changeColor(WORD color)变更颜色
/* 0 = 黑色 8 = 灰色搜索 1 = 蓝色 9 = 淡蓝色 2 = 绿色 A = 淡绿色 3 = 浅绿色 B = 淡浅绿色 4 = 红色 C = 淡红色 5 = 紫色 D = 淡紫色 6 = 黄色 E = 淡黄色 7 = 白色 F = 亮白色 FOREGROUND_BLUE 字体颜色:蓝 1 FOREGROUND_GREEN 字体颜色:绿 2 FOREGROUND_RED 字体颜色:红 4 FOREGROUND_INTENSITY 前景色高亮显示 8 BACKGROUND_BLUE 背景颜色:蓝 16 BACKGROUND_GREEN 背景颜色:绿 32 BACKGROUND_RED 背景颜色:红 64 BACKGROUND_INTENSITY 背景色高亮显示 128 */ class Screen { public: void gotoxy(short x, short y) { COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(hOut, pos); }; void Init() { hOut = GetStdHandle(STD_OUTPUT_HANDLE); assert(hOut != 0); } bool changeColor(WORD color) { SetConsoleTextAttribute(hOut,color); return true; } static Screen* instance() { static Screen screen; return &screen; } private: Screen() { } Screen(const Screen&); const Screen& operator=(const Screen&); HANDLE hOut; INPUT_RECORD inRec;/* 返回数据记录 */ DWORD numRead; /* 返回已读取的记录数 */ };
SL扫雷类
Init()初始化窗口高度宽度和类的数量,生成表格
InitTable() 有雷的地方值为-1,其它为周边雷的个数
DrawIn() 画窗口内部格子
DrawOut()画窗口边框
Run()运行游戏
bfs(int h,int w)对于值为0的格子,宽度搜索其周边的格子直到非0
show(int h,int w)当用户点击单击位置h,w 时被调用
完整代码:
#include<Windows.h> #include<iostream> #include<cassert> using std::cout; using std::cin; #include<vector> #include<time.h> #include<conio.h> #include<queue> using std::pair; using std::make_pair; using std::queue; using std::vector; /* 0 = 黑色 8 = 灰色搜索 1 = 蓝色 9 = 淡蓝色 2 = 绿色 A = 淡绿色 3 = 浅绿色 B = 淡浅绿色 4 = 红色 C = 淡红色 5 = 紫色 D = 淡紫色 6 = 黄色 E = 淡黄色 7 = 白色 F = 亮白色 FOREGROUND_BLUE 字体颜色:蓝 1 FOREGROUND_GREEN 字体颜色:绿 2 FOREGROUND_RED 字体颜色:红 4 FOREGROUND_INTENSITY 前景色高亮显示 8 BACKGROUND_BLUE 背景颜色:蓝 16 BACKGROUND_GREEN 背景颜色:绿 32 BACKGROUND_RED 背景颜色:红 64 BACKGROUND_INTENSITY 背景色高亮显示 128 */ class Screen { public: void gotoxy(short x, short y) { COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(hOut, pos); }; void Init() { hOut = GetStdHandle(STD_OUTPUT_HANDLE); assert(hOut != 0); } bool changeColor(WORD color) { SetConsoleTextAttribute(hOut,color); return true; } static Screen* instance() { static Screen screen; return &screen; } private: Screen() { } Screen(const Screen&); const Screen& operator=(const Screen&); HANDLE hOut; INPUT_RECORD inRec;/* 返回数据记录 */ DWORD numRead; /* 返回已读取的记录数 */ }; class SL { public: SL() { output = Screen::instance(); }; bool Init() { system("color 70"); SetWidth(); SetHeight(); SetNum(); InitTable(); right = 0; return true; } void InitTable() { table.resize(Height); for (int h = 0; h < Height; h++) { table[h].resize(Width); } int n = num; for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { n--; table[i][j] = -1; if (n <= 0) { j = Width; i = Height; } } } srand(time(0)); for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { int pi = rand() % Height; int pj = rand() % Width; std::swap(table[i][j], table[pi][pj]); } } for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { if (table[i][j] == -1) { int pos[][2] = { {-1,-1},{-1,1},{-1,0},{0,1},{0,-1},{ 1,-1 },{ 1,1 },{ 1,0 } }; for (int k = 0; k < 8; k++) { int hh = pos[k][0] + i; int ww = pos[k][1] + j; if (hh >= 0 && hh < Height && ww >= 0 && ww < Width && table[hh][ww] != -1) { table[hh][ww]++; } } } } } int a; a = 1; } void SetWidth() { output->gotoxy(0, 0); printf("%s", "请输入扫雷游戏的宽度: "); output->gotoxy(22, 0); cin >> Width; while (!check(Width, 20, 60)) { output->gotoxy(0, 0); printf("%s", "请重新输入扫雷游戏的宽度: "); output->gotoxy(26, 0); cin >> Width; } } void SetHeight() { output->gotoxy(0, 1); printf("%s", "请输入扫雷游戏的高度: "); output->gotoxy(22, 1); cin >> Height; while (!check(Height, 20, 60)) { output->gotoxy(0, 1); printf("%s", "请重新输入扫雷游戏的高度: "); output->gotoxy(26, 1); cin >> Height; } } void SetNum() { output->gotoxy(0, 2); printf("%s", "请输入雷的个数: "); output->gotoxy(22, 2); cin >> num; while ((num >= (Width*Height>>1))) { output->gotoxy(0, 2); printf("%s", "请重新输入雷的个数: "); output->gotoxy(26, 2); cin >> num; } } bool check(int val,int low,int height) { return val >= low && val <= height; } void DrawIn() { output->changeColor(0x76); for (int h = 0; h < Height; h++) { output->gotoxy(5, 4+h); for (int w = 0; w < Width; w++) { printf("%s", "■"); /* if (table[h][w] == -1) printf("%s", "★"); else printf("%c ", table[h][w]+'0'); */ } } } void DrawOut() { output->changeColor(0x75); output->gotoxy(3, 3); //printf("%s\n", "■"); for (int w = 0; w < (Width+2);w++) printf("%s", "■"); output->gotoxy(3, 3 + Height + 1); for (int w = 0; w < (Width + 2); w++) printf("%s", "■"); for (int h = 0; h < (Height + 2); h++) { output->gotoxy(3, 3 + h); printf("%s", "■"); output->gotoxy(3+(Width+1)*2, 3 + h); printf("%s", "■"); } } void Run() { COORD pos; pos.X = 5; pos.Y = 4; output->gotoxy(5, 4); bool run = true; while (run) { char ch = _getch(); switch (ch) { case 72: //printf("UP\n"); break; { pos.Y--; pos.Y = pos.Y < 4 ? 4 : pos.Y; output->gotoxy(pos.X, pos.Y); }break; case 80: //printf("DOWN\n"); break; { pos.Y++; pos.Y = pos.Y > (4 + Height - 1) ? (4 + Height - 1) : pos.Y; output->gotoxy(pos.X, pos.Y); }break; case 75: //printf("LEFT\n"); break; { pos.X-=2; pos.X = pos.X >= 5 ? pos.X : 5; output->gotoxy(pos.X, pos.Y); }break; case 77: //printf("RIGHT\n"); break; { pos.X += 2; pos.X = pos.X <= 5+(Width-1)*2 ? pos.X : 5 + (Width - 1) * 2; output->gotoxy(pos.X, pos.Y); }break; case 13: //Enter { int h = pos.Y - 4; int w = (pos.X - 5) >> 1; bool ret = show(h, w); if (!ret) { output->gotoxy(70, 0); printf("你输了!!!"); return; } else if((right+num) == (Width*Height)) { output->gotoxy(70, 0); printf("胜利!!!"); for (int h = 0; h < Height; h++) { for (int w = 0; w < Width; w++) { show(h, w); } } return; } } } } } bool show(int h,int w) { int ret = true; output->gotoxy(5 + w * 2, 4 + h); switch (table[h][w]) { case -2:break;//已处理过 case -1: printf("%s", "★"); ret = false; break; case 0: bfs(h,w); break; default: printf("%c ", table[h][w]+'0'); right++; table[h][w] = -2; } output->gotoxy(5 + w * 2, 4 + h); return ret; } void bfs(int h,int w) { using std::queue; queue<pair<int,int>> q; q.push(make_pair(h, w)); while (!q.empty()) { pair<int, int> n = q.front(); q.pop(); int h = n.first; int w = n.second; if (table[h][w] == -2)continue; output->gotoxy(5 + w * 2, 4 + h); if (table[h][w] == 0) { printf("%s", " "); right++; int pos[][2] = { { -1,-1 },{ -1,1 },{ -1,0 },{ 0,1 },{ 0,-1 },{ 1,-1 },{ 1,1 },{ 1,0 } }; for (int k = 0; k < 8; k++) { int hh = pos[k][0] + h; int ww = pos[k][1] + w; if (InWindow(hh, ww) && table[hh][ww]>=0) { q.push(make_pair(hh, ww)); } } } else { printf("%c ", table[h][w] + '0'); right++; } table[h][w] = -2; } } bool InWindow(int h, int w) { return h >= 0 && h < Height && w >= 0 && w < Width; } private: Screen* output; int Width; //窗口宽度 int Height; //窗口高度 int num; //雷的数量 int right; vector<vector<int>> table; }; int main() { Screen::instance()->Init(); Screen::instance()->gotoxy(20, 20); SL game; game.Init(); game.DrawOut(); game.DrawIn(); game.Run(); system("pause"); return 0; }