前言
这是我初中闲时使用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;
}
相关推荐
C/C++去注释空行工具
99 浏览
基于HTML的重力翻转
84 浏览