社区讨论

《扫雷》

灌水区参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@lxldguyd
此快照首次捕获于
2024/06/19 13:07
2 年前
此快照最后确认于
2024/06/19 13:17
2 年前
查看原帖
鼠标UI\bold{\Large\color{red}鼠标UI}
CPP
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
using namespace std;


COORD GetPos() {
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO bInfo;
	GetConsoleScreenBufferInfo(hOut, &bInfo);
	return bInfo.dwCursorPosition;
}
void Gotoxy(int x, int y, int flag = 0) { //2全角 1相对 0绝对
	COORD coord;
	coord.X = x;
	coord.Y = y;
	if (flag & 1) {
		COORD crd = GetPos();
		coord.X += crd.X;
		coord.Y += crd.Y;
	}
	if (flag & 2) {
		coord.X <<= 1;
	}
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void Fill(int left, int top, int right, int buttom, char c = 32, int mode = 1) {
	if (mode) {
		left <<= 1;
		right <<= 1;
	}
	for (int i = top; i <= buttom; ++i) {
		Gotoxy(left,i);
		for (int i = left; i <= right; ++i) {
			printf("%c",c);
		}
	}
}
double GetScreenPercentage() {
	// 获取桌面窗口口句柄
	HWND hWnd = GetDesktopWindow();
	HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
	// 获取监视器逻辑尺寸
	MONITORINFOEX miex;
	miex.cbSize = sizeof(miex);
	GetMonitorInfo(hMonitor, &miex);
	int cxLogical = (miex.rcMonitor.right - miex.rcMonitor.left);
	int cyLogical = (miex.rcMonitor.bottom - miex.rcMonitor.top);
	// 获取监视器物理宽度与高度
	DEVMODE dm;
	dm.dmSize = sizeof(dm);
	dm.dmDriverExtra = 0;
	EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
	int cxPhysical = dm.dmPelsWidth;
	int cyPhysical = dm.dmPelsHeight;
	// 缩放比例计算 实际上使用任何一个即可
	double horzScale = ((double)cxPhysical / (double)cxLogical);
	double vertScale = ((double)cyPhysical / (double)cyLogical);
//	printf("cxPhysical = %d px.cyPhysical = %d px.\n", cxPhysical, cyPhysical);
//	printf("cxLogical = %d px.cyLogical = %d px.\n", cxLogical, cyLogical);
//	printf("horzScale = %.2f ,vertScale = %.2f \n", horzScale, vertScale );
	return horzScale;
}
POINT GetMousePosition(int x = 1,int n = 1, int l = 0) { //x相对窗口位置, n转化为黑窗口格子坐标 , l转化为全角
	double Percentage = GetScreenPercentage();
	HANDLE hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
//	HWND h=GetForegroundWindow();
	HWND h=GetConsoleWindow();
	CONSOLE_FONT_INFO consoleCurrentFont;
	POINT p;
	if(x) {
		GetCursorPos(&p);
		ScreenToClient(h,&p);
	} else {
		GetCursorPos(&p);
	}
	if(n) {
		GetCurrentConsoleFont(hOutput,FALSE,&consoleCurrentFont);
		p.x/=consoleCurrentFont.dwFontSize.X/Percentage;
		p.y/=consoleCurrentFont.dwFontSize.Y/Percentage;
		if (l) {
			p.x>>=1;
		}
	}
	return p;
}
int CheckMouse(int left, int top, int right, int buttom, int mode = 0) {
	if (mode) {
		left <<= 1;
		right <<= 1;
	}
	POINT p = GetMousePosition();
	if (p.x <= right && p.x >= left && p.y <= buttom && p.y >= top) {
		return 1;
	}
	return 0;
}
void HidePos() {
	CONSOLE_CURSOR_INFO cursor_info = {1, 0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void ShowPos() {
	CONSOLE_CURSOR_INFO cursor_info = {26, 1};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void SetColor(const short ForG = 7, const short BackG = 0) {
	WORD wColor = ((BackG & 0x0F) << 4) + (ForG & 0x0F);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),wColor);
}
void Edge(int left, int top, int right, int buttom, int mode = 1) {
	if (!mode) {
		left >>= 1;
		right >>= 1;
	}
	Gotoxy((left + 1) << 1, top);
	for (int i = left + 2; i <= right; ++i) {
		printf("▁");
	}
	Gotoxy(left << 1, top + 1);
	for (int i = top + 2; i <= buttom; ++i) {
		printf("▕");
		Gotoxy(-2,1,1);
	}
	Gotoxy(right << 1, top + 1);
	for (int i = top + 2; i <= buttom; ++i) {
		printf("▏");
		Gotoxy(-2,1,1);
	}
	Gotoxy((left + 1) << 1, buttom);
	for (int i = left + 2; i <= right; ++i) {
		printf("▔");
	}
}
void FixedSize() {
	SetWindowLongPtrA(
	    GetConsoleWindow(),
	    GWL_STYLE,
	    GetWindowLongPtrA(GetConsoleWindow(),
	                      GWL_STYLE)
	    & ~WS_SIZEBOX
	    & ~WS_MAXIMIZEBOX
	);
}
void SetFont(int size = 36, int num = 0) {
	CONSOLE_FONT_INFOEX cfi;
	cfi.cbSize = sizeof cfi;
	cfi.nFont = 0;
	cfi.dwFontSize.X = 0;
	cfi.dwFontSize.Y = size;
	cfi.FontFamily = FF_DONTCARE;
	cfi.FontWeight = FW_NORMAL;
	switch(num) {
		case 0:
			wcscpy(cfi.FaceName, L"NSimSun");
			break;//新宋体
		case 1:
			wcscpy(cfi.FaceName, L"Lucida Console");
			break;//一款个性独特的英文字体
		case 2:
			wcscpy(cfi.FaceName, L"Consolas");
			break;//等宽字体(Dev默认字体)
		case 3:
			wcscpy(cfi.FaceName, L"Raster");
			break;//点阵字体
	}
	SetCurrentConsoleFontEx(
	    GetStdHandle(STD_OUTPUT_HANDLE),
	    FALSE, &cfi
	);
}
#define QUICK_EDIT 0x01
#define INSERT 0x02
void CloseConsoleMode(UINT uTag) {
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	if(uTag & QUICK_EDIT)
		mode &= ~ENABLE_QUICK_EDIT_MODE;  //移除快速编辑模式
	if(uTag & INSERT)
		mode &= ~ENABLE_INSERT_MODE;      //移除插入模式
	SetConsoleMode(hStdin, mode);
}
void OpenConsoleMode(UINT uTag) {
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	if(uTag & QUICK_EDIT)
		mode |= ENABLE_QUICK_EDIT_MODE;  //设置快速编辑模式
	if(uTag & INSERT)
		mode |= ENABLE_INSERT_MODE;      //设置插入模式
	SetConsoleMode(hStdin, mode);
}
void SetSize(int col, int row) {
	char cmd[64];
	sprintf(cmd, "mode con cols=%d lines=%d", col, row);
	system(cmd);
}
int Click() {
	if (GetKeyState(1) & 0x8000) {
		mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
		return 1;
	}
	return 0;
}
int ClickR() {
	if (GetKeyState(4) & 0x8000) {
		mouse_event(MOUSEEVENTF_MIDDLEUP,0,0,0,0);
		return 1;
	}
	return 0;
}
int Rule() {
	SetColor(7);
	system("cls");
	printf("此游戏和传统扫雷类似, 可使用鼠标点击, 左键为挖开, 中键为标记\n");
	printf("在结算阶段感觉太慢时, 可以按任意键加快\n");
	Gotoxy(0,18);
	SetColor(7);
	printf("返回");
	int b = 0;
	while (1) {
		Sleep(5);
		if (CheckMouse(0,18,3,18)) {
			if (b == 0) {
				Gotoxy(0,18);
				SetColor(0,15);
				printf("返回");
				b = 1;
			}
			if (Click()) {
				return 0;
			}
		} else if (b == 1 && !CheckMouse(0,18,3,18)) {
			Gotoxy(0,18);
			SetColor(7);
			printf("返回");
			b = 0;
		}
	}


}
int Exit() {
	SetColor();
	system("cls");
	Edge(27,6,57,13,0);
	Gotoxy(18,8,2);
	SetColor(13);
	printf("确定要退出吗?");
	Gotoxy(17,10,2);
	SetColor(12);
	printf("是/YES");
	Gotoxy(22,10,2);
	SetColor(9);
	printf("否/NO");
	int b1=0,b2=0;
	while (1) {
		Sleep(5);
		if (CheckMouse(34,10,39,10)) {
			if (b1 == 0) {
				Gotoxy(17,10,2);
				SetColor(0,15);
				printf("是/YES");
				b1 = 1;
			}
			if (Click()) {
				SetColor();
				system("cls");
				exit(0);
			}
		} else {
			if (b1 == 1) {
				Gotoxy(17,10,2);
				SetColor(12);
				printf("是/YES");
				b1 = 0;
			}
		}
		if (CheckMouse(44,10,48,10)) {
			if (b2 == 0) {
				Gotoxy(22,10,2);
				SetColor(0,15);
				printf("否/NO");
				b2 = 1;
			}
			if (Click()) {
				return 0;
			}
		} else {
			if (b2 == 1) {
				Gotoxy(22,10,2);
				SetColor(9);
				printf("否/NO");
				b2 = 0;
			}
		}
	}
}
int creater() {
	SetColor();
	system("cls");
	printf("创作者: 洛谷用户 745288");
	Gotoxy(0,18);
	SetColor(7);
	printf("返回");
	int b = 0;
	while (1) {
		Sleep(5);
		if (CheckMouse(0,18,3,18)) {
			if (b == 0) {
				Gotoxy(0,18);
				SetColor(0,15);
				printf("返回");
				b = 1;
			}
			if (Click()) {
				return 0;
			}
		} else if (b == 1 && !CheckMouse(0,18,3,18)) {
			Gotoxy(0,18);
			SetColor(7);
			printf("返回");
			b = 0;
		}
	}
}
int Menu() {//1  Rule  2  Exit  3  creater
	SetColor(7);
	system("cls");
	SetColor(2);
	Edge(27,5,57,13,0);
	SetColor(15);
	Gotoxy(19,7,2);
	printf("开始游戏");
	Gotoxy(20,8,2);
	printf("规则");
	Gotoxy(39,9);
	printf("制作者");
	Gotoxy(20,10,2);
	printf("退出");
	int last = -1;
	while (1) {
		Sleep(5);
		POINT p = GetMousePosition();
		SetColor(10);
		if (p.x >= 36 && p.x <= 47 && p.y <= 10 && p.y >= 7) {
			if (p.y != last) {
				Gotoxy(36,p.y);
				printf("→");
				Gotoxy(46,p.y);
				printf("←");
				Gotoxy(36,last);
				printf("  ");
				Gotoxy(46,last);
				printf("  ");
				last = p.y;
			}
			if (Click()) {
				if (p.y == 7) {//开始
					return 0;
				} else if (p.y == 8) {//规则
					return 1;
				} else if (p.y == 9) {//制作者
					system("start https://www.luogu.com.cn/user/745288");
					return 3;
				} else if (p.y == 10) {//退出
					return 2;
				}
			}
		} else if (last != -1) {
			Gotoxy(36,last);
			printf("  ");
			Gotoxy(46,last);
			printf("  ");
			last = -1;
		}
	}
}
int c[20][20], c1[20][20];//地雷/地雷数量    标记/挖开
int n = 10, m = 20, tot, Top, Left;
int Rand() {
	mt19937 rnd(time(0));
	for (int i = 0; i < m; ++i) {
		int x = rnd()%n, y = rnd()%n;
		while (c[x][y] != 0) {
			x = rnd()%n, y = rnd()%n;
		}
		c[x][y] = -1;
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (c[i][j] == -1) {
				continue;
			}
			int tot = 0;
			for (int k = -1; k <= 1; ++k) {
				for (int l = -1; l <= 1; ++l) {
					if (i+k<0||i+k>=n||j+l<0||j+l>=n) continue;
					if (k == l && l == 0) {
						continue;
					}
					if (c[i+k][j+l] == -1) {
						++tot;
					}
				}
			}
			c[i][j] = tot;
		}
	}
	return 0;
}
int NewGame() {
	memset(c, 0, sizeof(c));
	memset(c1, 0, sizeof(c1));
	tot = 0;
	SetColor();
	system("cls");
	Edge(16,5,27,14);
	Gotoxy(18,8,2);
	printf("大小: %d",n);
	Gotoxy(18,10,2);
	printf("数量: %d",m);
	Gotoxy(21,9,2);
	for (int i = 0; i < 3; ++i) {
		printf(" ̄");
	}
	Gotoxy(21,11,2);
	for (int i = 0; i < 3; ++i) {
		printf(" ̄");
	}
	Gotoxy(41,12);
	SetColor(0,7);
	printf("确定");
	int b = 0;
	int now = 0;
	int size=n, num=m;
	string Size, Num;
	for (int i = 1; size / i; i *= 10) {
		Size += size / i % 10;
	}
	for (int i = 1; num / i; i *= 10) {
		Num += num / i % 10;
	}
	char cache;
	while (1) {
		Sleep(5);
		if (CheckMouse(41,12,44,12)) {//确定键
			if (b == 0) {
				Gotoxy(41,12);
				SetColor(0,15);
				printf("确定");
				b = 1;
			}
			if (Click()) {
				HidePos();
				if (size > 0 && num > 0 && num < size * size && size <= 20) {
					//输入成功
					n = size;
					m = num;
					Rand();
					return 0;
				} else if (size == num && num == 0) {
					Rand();
					return 0;
				} else {
					Gotoxy(19,7,2);
					SetColor(12);
					printf("输入不合法!");
					Sleep(1000);
					Gotoxy(19,7,2);
					SetColor(12);
					printf("           ");
				}
			}
		} else {
			if (b == 1) {
				Gotoxy(41,12);
				SetColor(0,7);
				printf("确定");
				b = 0;
			}
		}
		if (CheckMouse(42,8,47,8)) {//点击输入大小位置
			if (Click()) {
				now = 1;
				ShowPos();
			}
		} else if (CheckMouse(42,10,47,10)) {//点击输入数量位置
			if (Click()) {
				now = 2;
				ShowPos();
			}
		} else {
			if (Click()) {
				now = 0;
				HidePos();
			}
		}
		if (now == 1) {//移动光标
			COORD coord = GetPos();
			if (coord.X > 47 || coord.X < 42 || coord.Y != 8) Gotoxy(42+Size.size(),8);
		} else if (now == 2) {
			COORD coord = GetPos();
			if (coord.X > 47 || coord.X < 42 || coord.Y != 10) Gotoxy(42+Num.size(),10);
		}
		if (kbhit()) {//输入
			cache = getch();
			if (!isdigit(cache) && cache != 8) {
			} else if (now == 1) {
				SetColor();
				if (cache == 8) {
					if (Size.size()) {
						Size.pop_back();
						size /= 10;
						printf("\b \b");
					}
				} else {
					Size += cache;
					size = size * 10 + cache - 48;
					putchar(cache);
				}
			} else if (now == 2) {
				SetColor();
				if (cache == 8) {
					if (Num.size()) {
						Num.pop_back();
						num /= 10;
						printf("\b \b");
					}
				} else {
					Num += cache;
					num = num * 10 + cache - 48;
					putchar(cache);
				}
			}
		}
	}

	return 0;
}
long Lclock, Rclock;
int Game() {//0 胜利  1 失败
	POINT p = GetMousePosition();
	int x = -1, y = -1, px = p.x / 2, py = p.y;
	while (1) {
		if (kbhit()) {
			getch();
		}
		if (tot == n * n - m) {
			int wait = 1;
			for (int i = 0; i < n; ++i) {
				for (int j = 0; j < n; ++j) {
					if (kbhit()) {
						getch();
						wait = 0;
					} else if (Click()) {
						wait = 0;
					}
					if (i == px - Left && j == py - Top) {
						continue;
					}
					if (c[i][j] == -1) {
						Gotoxy(i + Left, j + Top, 2);
						if (wait) Sleep(250);
						if (c1[i][j] == 2) {
							SetColor(13);
						} else {
							SetColor(12);
						}
						printf("●");
					}
				}
			}
			Gotoxy(0,6);
			printf("请按任意键继续...");
			while (1) {
				Sleep(5);
				if (kbhit()) {
					getch();
					break;
				} else if (Click()) {
					break;
				}
			}
			return 0;
		}
		Sleep(5);
		p = GetMousePosition();
		px = p.x / 2;
		py = p.y;
		if (x != px || y != py) {
			if (x < Left + n && x >= Left && y >= Top && y < Top + n) {
				Gotoxy(x, y, 2);
				SetColor(3);
				if (c1[x - Left][y - Top] == 0) {
					printf("■");
				} else if (c1[x - Left][y - Top] == 1) {
					printf("%d",c[x - Left][y - Top]);
				} else if (c1[x - Left][y - Top] == 2) {
					SetColor(5);
					printf("■");
				}
			}
			if (px < Left + n && px >= Left && py >= Top && py < Top + n) {
				Gotoxy(px, py, 2);
				SetColor(11);
				if (c1[px - Left][py - Top] == 0) {
					printf("■");
				} else if (c1[px - Left][py - Top] == 1) {
					printf("%d",c[px - Left][py - Top]);
				} else if (c1[px - Left][py - Top] == 2) {
					SetColor(13);
					printf("■");
				}

			}
			x = px, y = py;
		}
		if (Click()) {
			if (px < Left || px >= Left + n || py >= Top + n || py < Top) {
			} else if (c1[px - Left][py - Top] != 0) {
				SetColor(12);
				Gotoxy(0,2);
				printf("左键错误: \n无法挖开已标记的方块");
				Lclock = clock();
			} else if (c[px - Left][py - Top] == -1) {
				Gotoxy(px, py, 2);
				SetColor(12);
				printf("死");
				int wait = 1;
				for (int i = 0; i < n; ++i) {
					for (int j = 0; j < n; ++j) {
						if (kbhit()) {
							getch();
							wait = 0;
						} else if (Click()) {
							wait = 0;
						}
						if (i == px - Left && j == py - Top) {
							continue;
						}
						if (c[i][j] == -1) {
							Gotoxy(i + Left, j + Top, 2);
							if (wait) Sleep(250);
							if (c1[i][j] == 2) {
								SetColor(13);
							} else {
								SetColor(12);
							}
							printf("●");
						}
					}
				}
				Gotoxy(0,6);
				printf("请按任意键继续...");
				while (1) {
					Sleep(5);
					if (kbhit()) {
						getch();
						break;
					} else if (Click()) {
						break;
					}
				}

				return 1;
			} else if (c[px - Left][py - Top] == 0) {
				SetColor(3);
				for (int i = -1; i <= 1; ++i) {
					for (int j = -1; j <= 1; ++j) {
						if (px + i < Left || px + i >= Left + n || py + j >= Top + n || py + j < Top) continue;
						if ((i == j && i == 0) || c1[px + i - Left][py + j - Top] == 1) continue;
						c1[px + i - Left][py + j - Top] = 1;
						Gotoxy(px + i, py + j, 2);
						printf("%d", c[px + i - Left][py + j - Top]);
						++tot;
					}
				}
				SetColor(11);
				c1[px - Left][py - Top] = 1;
				Gotoxy(px, py, 2);
				printf("%d", c[px - Left][py - Top]);
				++tot;
			} else {
				c1[px - Left][py - Top] = 1;
				Gotoxy(px, py, 2);
				SetColor(11);
				printf("%d", c[px - Left][py - Top]);
				++tot;
			}
		}
		if (ClickR()) {
			if (px < Left || px >= Left + n || py >= Top + n || py < Top) {
			} else if (c1[px - Left][py - Top] == 1) {
				SetColor(12);
				Gotoxy(0,0);
				printf("中键错误: \n无法标记已挖开的方块");
				Rclock = clock();
			} else if (c1[px - Left][py - Top] == 0) {
				c1[px - Left][py - Top] = 2;
				Gotoxy(px, py, 2);
				SetColor(13);
				printf("■");
			} else if (c1[px - Left][py - Top] == 2) {
				c1[px - Left][py - Top] = 0;
				Gotoxy(px, py, 2);
				SetColor(11);
				printf("■");
			}
		}
		if (clock() - Rclock > 1000) {
			SetColor();
			Gotoxy(0,0);
			printf("        ");
			Fill(0,0,10,1);
		}
		if (clock() - Lclock > 1000) {
			SetColor();
			Fill(0,2,10,3);
		}
	}
}
int mainfunc() {
	int flag;
	while (1) {
		flag = Menu();
		if (flag == 0) {
			NewGame();
			break;
		} else if (flag == 1) {
			Rule();
		} else if (flag == 2) {
			Exit();
		} else if (flag == 3) {
			creater();
		}
	}
	SetColor(3);
	system("cls");
	Left = 21 - (n >> 1);
	Top = 10 - (n >> 1);
	for (int i = 0; i < n; ++i) {
		Gotoxy(21 - (n >> 1),10 - (n >> 1) + i,2);
		for (int j = 0; j < n; ++j) {
			printf("■");
		}
	}
	int result = Game();
	SetColor();
	system("cls");
	Edge(27,5,57,13,0);
	Gotoxy(19,8,2);
	SetColor(13);
	printf("要继续吗?");
	Gotoxy(17,10,2);
	SetColor(11);
	printf("是/YES");
	Gotoxy(22,10,2);
	SetColor(12);
	printf("否/NO");
	Gotoxy(35,7);
	if (result) {
		SetColor(12);
		printf("很遗憾, 你输了");
	} else {
		SetColor(10);
		printf("恭喜! 你赢了! ");
	}
	int b1=0,b2=0;
	while (1) {
		Sleep(5);
		if (CheckMouse(34,10,39,10)) {
			if (b1 == 0) {
				Gotoxy(17,10,2);
				SetColor(0,15);
				printf("是/YES");
				b1 = 1;
			}
			if (Click()) {
				return 0;
			}
		} else {
			if (b1 == 1) {
				Gotoxy(17,10,2);
				SetColor(11);
				printf("是/YES");
				b1 = 0;
			}
		}
		if (CheckMouse(44,10,48,10)) {
			if (b2 == 0) {
				Gotoxy(22,10,2);
				SetColor(0,15);
				printf("否/NO");
				b2 = 1;
			}
			if (Click()) {
				SetColor();
				system("cls");
				exit(0);
			}
		} else {
			if (b2 == 1) {
				Gotoxy(22,10,2);
				SetColor(12);
				printf("否/NO");
				b2 = 0;
			}
		}
	}
	return 0;
}
int StartSet() {
	CloseConsoleMode(QUICK_EDIT);
	SetSize(88,20);
	SetFont();
	FixedSize();
	HidePos();
	return 0;
}
int main() {
	StartSet();
	int i = 1;
	char c[] = "扫雷-第1局";
	SetConsoleTitle(c);
	while (1) {
		mainfunc();
		sprintf(c, "扫雷-第%d局",++i);
		SetConsoleTitle(c);
	}

	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...