基于C++的无限扫雷
首页文章工具搜索

基于C++的无限扫雷

2026.08.14 [C++] [小游戏] 109 浏览


前言

这是我初中闲时使用C++ EGE库开发的一个小型扫雷游戏,高中时为了在学校大屏幕(触屏)游玩又适配了触屏操作;这个扫雷游戏异于传统扫雷游戏,我使用了区块技术动态生成地图来实现了无穷无尽的游戏体验。

机制

  • 无限地图:采用9×9区块动态生成,当视口进入新区块时候,旧区块会卸载并保存到磁盘,新区块会立即生成(为什么是9×9大小可能是当时为了疫情网课方便摸鱼???)。
  • 智能生成:难度会随着坐标的增大而增大。
  • 分数系统:初始50分,标记地雷加分,踩雷和错误标记扣分(当然你也可以通过修改配置文件来让你的分数为9999999)。

玩法

  • 左键点击:翻开格子,若踩雷-25分。
  • 右键点击:标记地雷,标记正确+3分,错误-30分。
  • 按下并拖拽:快速移动视口(左右键均可,属于一个小bug但是无伤大雅懒得改了)。
  • A/W/S/D:精准移动视口。

备注

为了方便学习编程,源代码我与程序放在一起了,使用前记得解压到一个专门的文件夹去使用。

关于源代码,我使用的是EGE24.04版本,目前EGE最新版本是25.11,新版本在编译我的代码的时候会出现一些显示异常。

源代码 & 程序本体

源代码

#include <graphics.h> #include <math.h> #include <iostream> #include <fstream> #include <stdlib.h> #include <time.h> #include <string> #include<functional> using namespace std; struct m { bool fan, flag, lei; unsigned num; }; m mm[27][27] = {}; short view_x = 9, view_y = 9; long long map_x = 0, map_y = 0, marks = 50; //"mm"middle size string ts = "\"A,W,S,D\"移动视口"; void save_block(short x_, short y_); void read_block(short part_x, short part_y, long long xx, long long yy, bool rebuit = false, short leinum = 20) { ifstream in(to_string(xx) + "," + to_string(yy) + ".hs_block"); if (in && !rebuit) { for (int x = part_x * 9; x < part_x * 9 + 9; x++) { for (int y = part_y * 9; y < part_y * 9 + 9; y++) { in >> mm[x][y].fan >> mm[x][y].flag >> mm[x][y].lei; } } in.close(); } else { in.close(); srand((abs(xx) + abs(yy) + 1) / 2); for (int x = part_x * 9; x < part_x * 9 + 9; x++) { for (int y = part_y * 9; y < part_y * 9 + 9; y++) { mm[x][y] = {0, 0, 0, 0}; } } for (int i = 0; i <= min((long long)leinum, 5 * (abs(xx) + abs(yy) + 1)); i++) { mm[rand() % 9 + part_x * 9][rand() % 9 + part_y * 9].lei = true; } if (xx == 0 && yy == 0) { for (int x = part_x * 9; x < part_x * 9 + 9; x++) { for (int y = part_y * 9; y < part_y * 9 + 9; y++) { if (mm[x][y].lei) { mm[x][y].flag = true; } else { mm[x][y].fan = true; } } } } save_block(part_x, part_y); } } void save_basic() { ofstream out("data.hs_ini"); out << view_x << " " << view_y << "\n" << map_x << " " << map_y << " " << marks; out.close(); } void read_basic() { ifstream in("data.hs_ini"); if (in) { in >> view_x >> view_y >> map_x >> map_y >> marks; } else { view_x = 9, view_y = 9, map_x = 0, map_y = 0; save_basic(); } in.close(); } void save_block(short x_, short y_) { ofstream out(to_string(map_x + x_ - 1) + "," + to_string(map_y + y_ - 1) + ".hs_block"); for (int x = x_ * 9; x < x_ * 9 + 9; x++) { for (int y = y_ * 9; y < y_ * 9 + 9; y++) { out << mm[x][y].fan << " " << mm[x][y].flag << " " << mm[x][y].lei << "\n"; } } out.close(); } void read_block_all(bool rebuit = false, short leinum = 20) { for (int x = 0; x < 27; x++) { for (int y = 0; y < 27; y++) { mm[x][y].num = 0; } } for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { read_block(x, y, map_x + x - 1, map_y + y - 1, rebuit, leinum); } } for (int x = 0; x < 27; x++) { for (int y = 0; y < 27; y++) { if (mm[x][y].lei) { for (int _x = x - 1; _x <= x + 1; _x++) { for (int _y = y - 1; _y <= y + 1; _y++) { if (_x >= 0 && _x < 27 && _y >= 0 && _y <= 27) { mm[_x][_y].num++; } } } } } } } void touch_fan(bool ok = false) { if (ok)return; ok = true; for (int x = 0; x < 27; x++) { for (int y = 0; y < 27; y++) { if (mm[x][y].fan && mm[x][y].num == 0) { for (int _x = x - 1; _x <= x + 1; _x++) { for (int _y = y - 1; _y <= y + 1; _y++) { if (_x >= 0 && _x < 27 && _y >= 0 && _y <= 27 && mm[_x][_y].flag == false && mm[_x][_y].lei == false && mm[_x][_y].fan == false) { mm[_x][_y].fan = true; ok = false; } } } } } } touch_fan(ok); } color_t bkfancolor = EGERGB(20, 20, 60), bkcolor = EGERGB(40, 40, 100), leicolor = EGERGB(150, 40, 40), flagcolor = EGERGB(150, 70, 30); function<void(int, int, PIMAGE&)> s_img[] = { [](int x, int y, PIMAGE & img) {//flag setlinewidth(2, img); ege_line(x + 5, y + 5, x + 5, y + 25, img); ege_line(x + 5, y + 5, x + 25, y + 10, img); ege_line(x + 5, y + 15, x + 25, y + 10, img); }, [](int x, int y, PIMAGE & img) { //1 setcolor(EGERGB(20, 100, 0), img); setlinewidth(2, img); ege_line(x + 15, y + 5, x + 15, y + 25, img); }, [](int x, int y, PIMAGE & img) { //2 setcolor(EGERGB(30, 90, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 25, y + 5, x + 25, y + 15, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); ege_line(x + 5, y + 15, x + 5, y + 25, img); ege_line(x + 5, y + 25, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //3 setcolor(EGERGB(40, 80, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 25, y + 5, x + 25, y + 25, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); ege_line(x + 5, y + 25, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //4 setcolor(EGERGB(50, 70, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 5, y + 15, img); ege_line(x + 25, y + 5, x + 25, y + 25, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); }, [](int x, int y, PIMAGE & img) { //5 setcolor(EGERGB(60, 60, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 5, y + 5, x + 5, y + 15, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); ege_line(x + 25, y + 15, x + 25, y + 25, img); ege_line(x + 5, y + 25, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //6 setcolor(EGERGB(70, 50, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 5, y + 5, x + 5, y + 25, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); ege_line(x + 25, y + 15, x + 25, y + 25, img); ege_line(x + 5, y + 25, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //7 setcolor(EGERGB(80, 40, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 25, y + 5, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //8 setcolor(EGERGB(90, 30, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 5, y + 5, x + 5, y + 25, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); ege_line(x + 25, y + 5, x + 25, y + 25, img); ege_line(x + 5, y + 25, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //9 setcolor(EGERGB(100, 20, 0), img); setlinewidth(2, img); ege_line(x + 5, y + 5, x + 25, y + 5, img); ege_line(x + 5, y + 5, x + 5, y + 15, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); ege_line(x + 25, y + 5, x + 25, y + 25, img); ege_line(x + 5, y + 25, x + 25, y + 25, img); }, [](int x, int y, PIMAGE & img) { //lei setfillcolor(EGERGB(255, 255, 255), img); setlinewidth(2, img); solidcircle(x + 15, y + 15, 8, img); ege_line(x + 7, y + 7, x + 23, y + 23, img); ege_line(x + 7, y + 23, x + 23, y + 7, img); ege_line(x + 15, y + 5, x + 15, y + 25, img); ege_line(x + 5, y + 15, x + 25, y + 15, img); } }; void show(PIMAGE &img) { for (int x = view_x, xx = 0; x < view_x + 9; x++, xx++) { for (int y = view_y, yy = 0; y < view_y + 9; y++, yy++) { setcolor(EGERGB(255, 255, 255), img); setlinewidth(1, img); if (mm[x][y].fan) { if (mm[x][y].lei) { setfillcolor(leicolor, img); fillrect(xx * 30, yy * 30, xx * 30 + 30, yy * 30 + 30, img); s_img[10](xx * 30, yy * 30, img); } else if (mm[x][y].num != 0) { setfillcolor(bkfancolor, img); fillrect(xx * 30, yy * 30, xx * 30 + 30, yy * 30 + 30, img); s_img[mm[x][y].num](xx * 30, yy * 30, img); } else { setfillcolor(bkfancolor, img); fillrect(xx * 30, yy * 30, xx * 30 + 30, yy * 30 + 30, img); } } else { if (mm[x][y].flag) { setfillcolor(flagcolor, img); fillrect(xx * 30, yy * 30, xx * 30 + 30, yy * 30 + 30, img); s_img[0](xx * 30, yy * 30, img); } else { setfillcolor(bkcolor, img); fillrect(xx * 30, yy * 30, xx * 30 + 30, yy * 30 + 30, img); } } } } setcolor(EGERGB(255, 255, 255), img); setlinewidth(1, img); setfillcolor(bkcolor, img); fillrect(0, 270, 270, 300, img); fillrect(0, 300, 135, 330, img); fillrect(135, 300, 270, 330, img); setcolor(EGERGB(250, 250, 250), img); setbkmode(TRANSPARENT, img); setfont(20, 0, "黑体", img); outtextxy(5, 275, ts.c_str(), img); outtextxy(5, 305, string("分数:" + to_string(marks)).c_str(), img); outtextxy(140, 305, string(to_string((map_y - 1) * 9 + view_y) + "," + to_string((map_x - 1) * 9 + view_x)).c_str(), img); } int lcc(mouse_msg &a, mouse_msg &b) { return abs(a.x - b.x) + abs(a.y - b.y); } int main() { initgraph( 270, 330); setcaption("无限扫雷"); setcolor( RGB(0xff, 0xff, 0xff) ); setfillcolor( RGB(0, 0, 0xff) ); setrendermode(RENDER_MANUAL); setbkcolor(bkcolor); read_basic(); read_block_all(); PIMAGE bk = newimage(270, 330); mouse_msg mouse, old_mouse; key_msg key; bool refush = true; for ( ; is_run(); delay_ms(0) ) { touch_fan(); if (refush) { show(bk); refush = false; } setfillcolor(EGERGBA(255, 255, 255, 10)); cleardevice(); for (int i = 10; i > 0; i--) { ege_fillcircle(mouse.x, mouse.y, i * 5); } putimage_transparent(NULL, bk, 0, 0, EGERGB(255, 255, 255)); if (mousemsg()) { mouse = getmouse(); // flushmouse(); if (mouse.is_down()) { old_mouse = mouse; } else if (mouse.is_up()) { if (lcc(mouse, old_mouse) <= 20) { if (mouse.is_left()) {//鼠标操作 if (mouse.y <= 270) { refush = true; short x = mouse.x / 30, y = mouse.y / 30; if (!mm[view_x + x][view_y + y].flag && !mm[view_x + x][view_y + y].fan) { mm[view_x + x][view_y + y].fan = true; if (mm[view_x + x][view_y + y].lei) { ts = "触发地雷-25分!"; marks = marks - 25; } } else ts = "此处已经标记/翻开"; } } else if (mouse.is_right()) { if (mouse.y <= 270) { refush = true; short x = mouse.x / 30, y = mouse.y / 30; if (!mm[view_x + x][view_y + y].flag) { if (!mm[view_x + x][view_y + y].fan) { if (mm[view_x + x][view_y + y].lei) { ts = "标记地雷+3分!"; marks = marks + 3; mm[view_x + x][view_y + y].flag = true; } else { ts = "标记错误-30分!"; marks = marks - 30; } } else ts = "无效的标记!"; } else ts = "此处已经标记!"; } } } else { refush = true; short x = old_mouse.x / 30 - mouse.x / 30, y = old_mouse.y / 30 - mouse.y / 30; view_x = view_x + x; view_y = view_y + y; bool re = false; if (view_y <= 2) { view_y = view_y + 9, map_y--, re = true; } else if (view_y > 18) { view_y = view_y - 9, map_y++, re = true; } if (view_x <= 2) { view_x = view_x + 9, map_x--, re = true; } else if (view_x > 18) { view_x = view_x - 9, map_x++, re = true; } if (re) { read_block_all(); } } old_mouse = mouse; } else { } } if (kbmsg()) { key = getkey(); flushkey(); if (key.msg == key_msg_down) { if (key.key == key_W) { refush = true; view_y--; if (view_y <= 2) { view_y = view_y + 9, map_y--; read_block_all(); } } else if (key.key == key_S) { refush = true; view_y++; if (view_y > 18) { view_y = view_y - 9, map_y++; read_block_all(); } } else if (key.key == key_A) { refush = true; view_x--; if (view_x <= 2) { view_x = view_x + 9, map_x--; read_block_all(); } } else if (key.key == key_D) { refush = true; view_x++; if (view_x > 18) { view_x = view_x - 9, map_x++; read_block_all(); } } } } if (refush) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { save_block(x, y); } } save_basic(); } } delimage(bk); return 0; }