实现功能:
1.左键翻开
2.右键标记
3.选择简单,中等,困难三个难度
4.左右键同时按下,当标记数量相匹配时自动翻开
5.角块不藏雷
6.需要自己配置图片(jpg格式),loadimage函数中有注释
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <graphics.h>
#include <easyx.h>
#include <windows.h>
#include <conio.h>
#include <Mmsystem.h>
#include <mciapi.h>
#pragma comment(lib,"winmm.lib")
#define SIZE 35
int ROW, COL, NUM; //行数 列数 雷数
int count; //已经翻开的个数
int c_mine; //已经标记个数
int map[40][20]; //定义二维数组地图
IMAGE img[20]; //图片
//初始化函数
void GameInit() {
srand((unsigned int)time(NULL)); //获得随机种子
for (int i = 0; i < ROW+2; i++) { //初始化地图
for (int j = 0; j < COL+2; j++) {
map[i][j] = 0;
}
}
int n = 0;
while (n < NUM) { //随机布雷
int r = rand() % ROW+1;
int c = rand() % COL+1;
if (map[r][c] == 0 ) { //判断是否已经布雷
if ((r == 1 && c == 1) || (r == 1 && c == COL) || (r == ROW && c == 1) || (r == ROW && c == COL)) {//角块不藏雷
continue;
}
map[r][c] = -1;
n++;
}
}
for (int i = 1; i <= ROW; i++) { //填充数字
for (int j = 1; j <= COL; j++) {
if (map[i][j] != -1) { //如果是雷则遍历九宫格填充数字
for (int m = i - 1; m <= i + 1; m++) {
for (int n = j - 1; n <= j + 1; n++) {
if (map[m][n] == -1) {
map[i][j]++;
}
}
}
}
}
}
for (int i = 1; i <= ROW; i++) { //加密覆盖空白图片
for (int j = 1; j <= COL; j++) {
map[i][j] += 20;
}
}
}
//自动翻开零块
void OpenZero(int r,int c) {
map[r][c] -= 20;
count++;
//递归翻开所有非雷块
for (int m = r - 1; m <= r + 1; m++) {
for (int n = c - 1; n <= c + 1; n++) {
if (m >= 1 && m <= ROW && n >= 1 && n <= COL) {
if (map[m][n] >= 19 && map[m][n] <= 28) {
if (map[m][n] != 20) {
map[m][n] -= 20;
count++;
}
else { //如果是零块继续递归翻开
OpenZero(m, n);
}
}
}
}
}
}
//游戏函数
int PlayGame() {
MOUSEMSG msg = { 0 }; //定义鼠标对象
int r, c;
int m_count = 0; //九宫格内标记的个数
while (1) {
msg = GetMouseMsg(); //获取鼠标信息
if (msg.mkLButton && msg.mkRButton) { //当左右键同时按下
r = msg.x / SIZE + 1;
c = msg.y / SIZE + 1;
if (map[r][c] >= 0 && map[r][c] <= 7) { //计算九宫格标记数量
for (int m = r - 1; m <= r + 1; m++) {
for (int n = c - 1; n <= c + 1; n++) {
if (map[m][n] >= 69) {
m_count++;
}
}
}
if (m_count == map[r][c]) { //如果标记数量等于中心数字,自动翻开
for (int m = r - 1; m <= r + 1; m++) {
for (int n = c - 1; n <= c + 1; n++) {
if (map[m][n] == 20) { //零块调用函递归数
OpenZero(m, n);
}
else if (map[m][n]>20 && map[m][n]<=28) { //数字块正常翻开
map[m][n] -= 20;
count++;
}
else if (map[m][n] == 19) { //雷块游戏结束
map[m][n] -= 20;
return -1;
}
}
}
}
}
}
switch (msg.uMsg) { //判断左右键
case WM_LBUTTONDOWN: //左键翻开空白块
r = msg.x / SIZE + 1;
c = msg.y / SIZE + 1;
if (map[r][c] >= 19 && map[r][c] <= 28) {
if (map[r][c] == 20) {
OpenZero(r,c);
}
else {
map[r][c] -= 20;
count++;
}
}
return(map[r][c]);
break;
case WM_RBUTTONDOWN: //右键标记
r = msg.x / SIZE + 1;
c = msg.y / SIZE + 1;
if (map[r][c] >= 19 && map[r][c] <= 28) { //标记
map[r][c] += 50;
c_mine++;
}
else if (map[r][c] > 30) { //取消标记
map[r][c] -= 50;
c_mine--;
}
return(map[r][c]);
break;
}
}
}
//绘制函数
void GameDraw() {
for (int i = 1; i <= ROW; i++) { //遍历
for (int j = 1; j <= COL; j++) {
if (map[i][j] >= 0 && map[i][j] <= 8) { //数字
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[map[i][j]]);
}
else if (map[i][j] >= 19 && map[i][j] <= 28) { //空白
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[10]);
}
else if (map[i][j] >= 69 && map[i][j] <= 78) { //标记
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[11]);
}
}
}
int temp = NUM - c_mine; //展示剩余雷的个数
wchar_t t[3];
_itow_s(temp, t, 10);
outtextxy(50, COL * SIZE, L"The number of remaining:");
outtextxy(221, COL * SIZE, t);
if (temp < 10) {
putimage(230, COL * SIZE, &img[0]);
}
}
//展示结果
void ShowResult() {
for (int i = 1; i <= ROW; i++) { //遍历
for (int j = 1; j <= COL; j++) {
if (map[i][j] == -1) { //踩到的雷
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[9]);
}
if (map[i][j] >= 0 && map[i][j] <= 8) { //数字
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[map[i][j]]);
}
else if (map[i][j] == 19) {
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[14]); //未翻开的雷
}
else if (map[i][j] == 69) {
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[12]); // 标记正确
}
else if (map[i][j] >= 70 && map[i][j] <= 78) {
putimage((i - 1) * SIZE, (j - 1) * SIZE, &img[13]); //标记错误
}
}
}
}
//绘制主界面
void DrawMenu() {
initgraph(400, 300); //绘制界面和加载图片
loadimage(&img[17], L"easy.jpg", 400, 100);
loadimage(&img[18], L"mid.jpg", 400, 100);
loadimage(&img[19], L"hard.jpg", 400, 100);
putimage(0, 0, &img[17]);
putimage(0, 100, &img[18]);
putimage(0, 200, &img[19]);
while (1) {
MOUSEMSG msg = { 0 };
int r, c;
msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN) {
if (msg.x >= 0 && msg.x <= 400) { //简单模式
if (msg.y > 0 && msg.y <= 100) {
ROW = COL = 8;
NUM = 10;
break;
}
else if (msg.y > 100 && msg.y <= 200) { //中等模式
ROW = COL = 16;
NUM = 40;
break;
}
else if (msg.y > 200 && msg.y <= 300) { //困难模式
ROW = 30;
COL = 16;
NUM = 99;
break;
}
}
}
}
}
//加载图片
void LoadImg() {
loadimage(&img[0], L"0.jpg", SIZE, SIZE);
loadimage(&img[1], L"1.jpg", SIZE, SIZE);
loadimage(&img[2], L"2.jpg", SIZE, SIZE);
loadimage(&img[3], L"3.jpg", SIZE, SIZE);
loadimage(&img[4], L"4.jpg", SIZE, SIZE);
loadimage(&img[5], L"5.jpg", SIZE, SIZE);
loadimage(&img[6], L"6.jpg", SIZE, SIZE);
loadimage(&img[7], L"7.jpg", SIZE, SIZE);
loadimage(&img[8], L"8.jpg", SIZE, SIZE);
loadimage(&img[9], L"9.jpg", SIZE, SIZE); //点开的雷
loadimage(&img[10], L"10.jpg", SIZE, SIZE); //空
loadimage(&img[11], L"11.jpg", SIZE, SIZE); //标
loadimage(&img[12], L"12.jpg", SIZE, SIZE); //标记正确
loadimage(&img[13], L"13.jpg", SIZE, SIZE); //标记错误
loadimage(&img[14], L"14.jpg", SIZE, SIZE); //未标记的雷
loadimage(&img[15], L"15.jpg", SIZE, SIZE); //失败
}
int main() {
my_begin:;
count = 0; //计数初始化
c_mine = 0;
DrawMenu();
LoadImg();
HWND hwnd = initgraph(ROW * SIZE, COL * SIZE+20); //绘制游戏界面
setbkcolor(WHITE);
setfillcolor(WHITE);
fillrectangle(0,0, ROW * SIZE, COL * SIZE + 20);
settextcolor(BLACK);
GameInit();
while (1) {
GameDraw();
if (PlayGame() == -1) { //失败
ShowResult();
mciSendString(L"open music01.wav alias m01", 0, 0, 0);
mciSendString(L"play m01", 0, 0, 0);
MessageBox(hwnd, L"WIN!", L"", MB_OK);
mciSendString(L"close m01", 0, 0, 0);
break;
}
if (ROW * COL - NUM == count) { //成功
ShowResult();
mciSendString(L"open music02.wav alias m02", NULL, 0, NULL);
mciSendString(L"play m02", NULL, 0, NULL);
MessageBox(hwnd, L"Lose!", L"", MB_OK);
mciSendString(L"close m02", NULL, 0, NULL);
break;
}
}
goto my_begin;
closegraph();
return 0;
}