//扫雷
#include <windows.h>
#include <windowsx.h>
#include <strsafe.h>
#include <time.h>
//格子区域大小(DIVISIONS * DIVISIONS)
#define DIVISIONS 20
//地雷数
#define MINECOUNT 40 //消息处理
LRESULT CALLBACK DealMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//写入地雷
void SetMine(int(*pChess)[DIVISIONS]);
//获取随机数
unsigned int GetRand();
//判断胜利
bool Win(int(*pChess)[DIVISIONS], int *pNotClickCount, int *pClickCount);
//重置
void Reset(HWND hWnd,int(*pChess)[DIVISIONS], int(*pClick)[DIVISIONS]); int WINAPI WinMain(
HINSTANCE hInstance, // 当前实例句柄
HINSTANCE hPrevInstance,// 前一实例句柄
LPSTR lpCmdLine, // 指向命令行参数的指针
int nCmdShow // 窗口的显示方式
)
{
HWND hWnd;
MSG msg;
WNDCLASS wndClass; wndClass.cbClsExtra = ;
wndClass.cbWndExtra = ;
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//画刷背景BLACK_PEN
wndClass.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wndClass.hIcon = LoadIcon(NULL, IDC_ARROW);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = DealMessage;
wndClass.lpszClassName = TEXT("MineSweeping");
wndClass.lpszMenuName = NULL;
wndClass.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("注册类失败,请检查参数是否成功设置"), TEXT("提示"), MB_OK);
} hWnd = CreateWindow(TEXT("MineSweeping"), // 窗口类名称
TEXT("扫雷"), // 窗口标题栏名称
WS_OVERLAPPEDWINDOW, // 窗口样式
CW_USEDEFAULT, // 窗口水平位置
CW_USEDEFAULT, // 窗口垂直位置
CW_USEDEFAULT, // 窗口宽度
CW_USEDEFAULT, // 窗口高度
NULL, // 父窗口句柄
NULL, // 窗口菜单句柄
hInstance, // 窗口实例句柄
NULL); // 窗口创建参数
if (!hWnd) // 新窗口创建失败
{
return FALSE;
} ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd); while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam;
} LRESULT CALLBACK DealMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//初始化要用到的变量
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
HBRUSH hBrush, hOldBrush;
TEXTMETRIC tm;
static int cxChar,cxCaps,cyChar; //输出整形用的缓冲区
TCHAR szBuffer[];
size_t iTarget; //地雷以及点击后雷个数存储区
static int iChess[DIVISIONS][DIVISIONS];
int(*pChess)[DIVISIONS] = iChess;
//点击后记录点击事件存储区
static int iClick[DIVISIONS][DIVISIONS];
int(*pClick)[DIVISIONS] = iClick; //pSize:当前一个格子宽高
//p:通用
static POINT pSize = { , }, p; //未点击的格子
int iNotClickCount;
//已经点击的格子
int iClickCount; switch (uMsg)
{
case WM_CREATE:
hdc = GetDC(hWnd);
//初始化
Reset(hWnd, pChess, pClick);
//获取字体高度
GetTextMetrics(hdc, &tm);
cyChar = tm.tmHeight + tm.tmExternalLeading;
//平均宽度
cxChar = tm.tmAveCharWidth;
//判断是否等宽字体
cxCaps = (tm.tmPitchAndFamily & ? : ) * cxChar / ; ReleaseDC(hWnd, hdc);
return ;
case WM_KEYDOWN:
//在没有鼠标的情况下,键盘模拟鼠标操作
ShowCursor(false);
GetCursorPos(&p);
ScreenToClient(hWnd, &p);
p.x = max(, min(DIVISIONS - , p.x / pSize.x));
p.y = max(, min(DIVISIONS - , p.y / pSize.y)); switch (wParam)
{
case VK_UP:
p.y = max(, p.y - );
break;
case VK_DOWN:
p.y = min(DIVISIONS - , p.y + );
break;
case VK_LEFT:
p.x = max(, p.x - );
break;
case VK_RIGHT:
p.x = min(DIVISIONS - , p.x + );
break;
case VK_HOME:
p.x = p.y = ;
break;
case VK_END:
p.x = p.y = DIVISIONS - ;
break;
case VK_RETURN:
case VK_SPACE:
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(p.x * pSize.x, p.y * pSize.y));
break;
}
p.x = (p.x * pSize.x) + (pSize.x / );
p.y = (p.y * pSize.y) + (pSize.y / ); ClientToScreen(hWnd, &p);
SetCursorPos(p.x, p.y);
ShowCursor(true);
return ;
case WM_SIZE:
//pSize每个格子大小,X宽,Y高
pSize.x = LOWORD(lParam) / DIVISIONS;
pSize.y = HIWORD(lParam) / DIVISIONS;
return ;
case WM_LBUTTONDOWN:
p.x = GET_X_LPARAM(lParam) / pSize.x;
p.y = GET_Y_LPARAM(lParam) / pSize.y;
if (p.x >= DIVISIONS || p.y >= DIVISIONS)
{
MessageBeep();
return ;
}
switch (iClick[p.x][p.y])
{
case :
MessageBeep();
return ;
case :
MessageBeep();
return ;
}
//判断是否点击到了雷
if (iChess[p.x][p.y] == -)
{
if (MessageBox(hWnd, TEXT("你踩到地雷了!"), TEXT("boom"), MB_OK) == IDOK)
{
Reset(hWnd,pChess, pClick);
InvalidateRect(hWnd, NULL, true);
}
}
else
{
//当前位置修改为点击过
iClick[p.x][p.y] = ;
//判断是否胜利
if (Win(pClick, &iNotClickCount, &iClickCount))
{
if (MessageBox(hWnd, TEXT("you win!"), TEXT("wow"), MB_OK) == IDOK)
{
Reset(hWnd,pChess, pClick);
}
}
//标题显示信息
StringCchPrintf(szBuffer, sizeof(szBuffer), TEXT("当前已经翻出的区域数%d,剩余区域数%d"), iClickCount, iNotClickCount);
StringCchLength(szBuffer, sizeof(szBuffer), &iTarget);
SetWindowText(hWnd, szBuffer);
//计算当前点击位置附近雷数
for (int x = -; x <= ; x++)
{
for (int y = -; y <= ; y++)
{
//超出客户区的格子不计算
if (p.x + x >= && p.x + x < DIVISIONS && p.y + y >= && p.y + y < DIVISIONS)
{
//当前格子不计算
if (x != || y != ) {
if (iChess[p.x + x][p.y + y] == -)
{
iChess[p.x][p.y]++;
}
}
}
}
}
}
//重绘格子
rect.left = p.x * pSize.x;
rect.top = p.y * pSize.y;
rect.right = (p.x + ) * pSize.x;
rect.bottom = (p.y + ) * pSize.y;
InvalidateRect(hWnd, &rect, true);
return ;
case WM_RBUTTONDOWN:
p.x = GET_X_LPARAM(lParam) / pSize.x;
p.y = GET_Y_LPARAM(lParam) / pSize.y;
if (p.x >= DIVISIONS || p.y >= DIVISIONS)
{
MessageBeep();
return ;
}
//当前格子标记地雷状态切换
switch (iClick[p.x][p.y])
{
case :
iClick[p.x][p.y] = ;
break;
case :
iClick[p.x][p.y] = ;
break;
default:
MessageBeep();
return ;
}
//重绘格子
rect.left = p.x * pSize.x;
rect.top = p.y * pSize.y;
rect.right = (p.x + ) * pSize.x;
rect.bottom = (p.y + ) * pSize.y;
InvalidateRect(hWnd, NULL, true);
return ;
case WM_MOUSEMOVE:
//鼠标超出扫雷区域鼠标禁止点击
p.x = GET_X_LPARAM(lParam) / pSize.x;
p.y = GET_Y_LPARAM(lParam) / pSize.y;
if (p.x >= DIVISIONS || p.y >= DIVISIONS)
{
SetCursor(LoadCursor(NULL, IDC_NO));
}
else
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
return ;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//扫雷棋盘绘画
for (int i = ; i < DIVISIONS; i++)
{
MoveToEx(hdc, pSize.x * i, , NULL);
LineTo(hdc, pSize.x * i, pSize.y * DIVISIONS); MoveToEx(hdc, , pSize.y * i, NULL);
LineTo(hdc, pSize.x * DIVISIONS, pSize.y * i);
}
//扫雷点击绘画
for (int x = ; x < DIVISIONS; x++)
{
for (int y = ; y < DIVISIONS; y++)
{
//0:未开过的格子,1:开过的格子,2:标记过的格子
switch (iClick[x][y])
{
case :
//每个格子背景变成灰色
hBrush = CreateSolidBrush(RGB(, , ));hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, x * pSize.x, y * pSize.y, (x + ) * pSize.x, (y + ) * pSize.y);
SelectObject(hdc, hOldBrush);DeleteObject(hBrush);DeleteObject(hOldBrush); //当前格子写入地雷数
//地雷数颜色随地雷数改变
switch (iChess[x][y])
{
case :
SetTextColor(hdc, RGB(, , )); break;
case :
SetTextColor(hdc, RGB(, , )); break;
case :
SetTextColor(hdc, RGB(, , )); break;
case :
SetTextColor(hdc, RGB(, , )); break;
case :
SetTextColor(hdc, RGB(, , )); break;
case :
SetTextColor(hdc, RGB(, , )); break;
case :
SetTextColor(hdc, RGB(, , )); break;
}
SetBkMode(hdc, TRANSPARENT);
StringCchPrintf(szBuffer, sizeof(szBuffer), TEXT("%d"), iChess[x][y]);
StringCchLength(szBuffer, sizeof(szBuffer), &iTarget);
TextOut(hdc, (x * pSize.x) + (pSize.x / ) - (cxChar / ), (y * pSize.y) + (pSize.y / ) - (cyChar / ), szBuffer, iTarget);
break;
case :
hBrush = CreateSolidBrush(RGB(, , ));hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
//画一个标记的旗子
MoveToEx(hdc, (x * pSize.x) + (pSize.x / ), (y * pSize.y) + (pSize.y / ) - , NULL);
LineTo(hdc, (x * pSize.x) + (pSize.x / ), (y * pSize.y) + (pSize.y / ) + ); Rectangle(hdc, (x * pSize.x) + (pSize.x / ), (y * pSize.y) + (pSize.y / ) - , (x * pSize.x) + (pSize.x / ) + , (y * pSize.y) + (pSize.y / )); MoveToEx(hdc, (x * pSize.x) + (pSize.x / ) - , (y * pSize.y) + (pSize.y / ) + , NULL);
LineTo(hdc, (x * pSize.x) + (pSize.x / ) + , (y * pSize.y) + (pSize.y / ) + ); SelectObject(hdc, hOldBrush);DeleteObject(hBrush);DeleteObject(hOldBrush);
break;
} }
} EndPaint(hWnd, &ps);
return ;
case WM_DESTROY:
PostQuitMessage();
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return ;
}
//产生随机数
unsigned int GetRand()
{
int r = rand();
r = r % DIVISIONS;
return r;
} //写入地雷
void SetMine(int(*pChess)[DIVISIONS])
{
POINT pPoint;
for (int i = ; i < MINECOUNT; i++)
{
while (true)
{
pPoint.x = GetRand();
pPoint.y = GetRand();
if (pChess[pPoint.x][pPoint.y] != -)
{
pChess[pPoint.x][pPoint.y] = -;
break;
}
}
}
return;
} //判断获胜
bool Win(int(*pChess)[DIVISIONS],int *pNotClickCount,int *pClickCount)
{
int i = ;
for (int x = ; x < DIVISIONS; x++)
{
for (int y = ; y < DIVISIONS; y++)
{
if (pChess[x][y] == || pChess[x][y] == )
{
i++;
}
}
}
*pNotClickCount = i;
*pClickCount = (DIVISIONS * DIVISIONS) - i;
if (i - MINECOUNT == )
{
return true;
}
return false;
} //重置
void Reset(HWND hWnd,int(*pChess)[DIVISIONS], int(*pClick)[DIVISIONS])
{
//防止随机数重复
srand((unsigned(time(NULL))));
SetCursor(LoadCursor(NULL, IDC_WAIT));
for (int x = ; x < DIVISIONS; x++)
{
for (int y = ; y < DIVISIONS; y++)
{
pChess[x][y] = ;
pClick[x][y] = ;
}
}
//memset(pChess, 0, sizeof(pChess));
//memset(pClick, 0, sizeof(pClick));
SetMine(pChess);
SetCursor(LoadCursor(NULL, IDC_ARROW));
InvalidateRect(hWnd, NULL, true);
return;
}

WINAPI实现简易扫雷游戏的更多相关文章

  1. 洛谷 P2670 扫雷游戏==Codevs 5129 扫雷游戏

    题目描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有 ...

  2. 原生javascript扫雷游戏

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. Java练习(模拟扫雷游戏)

    要为扫雷游戏布置地雷,扫雷游戏的扫雷面板可以用二维int数组表示.如某位置为地雷,则该位置用数字-1表示, 如该位置不是地雷,则暂时用数字0表示. 编写程序完成在该二维数组中随机布雷的操作,程序读入3 ...

  4. JAVA_扫雷游戏(布置地雷)

    1.要为扫雷游戏布置地雷,扫雷游戏的扫雷面板可以用二维int数组表示.如某位置为地雷,则该位置用数字-1表示, 如该位置不是地雷,则暂时用数字0表示. 编写程序完成在该二维数组中随机布雷的操作,程序读 ...

  5. [LeetCode] Minesweeper 扫雷游戏

    Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...

  6. C语言二维数组实现扫雷游戏

    #include<stdio.h> //使用二维数组实现 扫雷 int main() { char ui[8][8]={ '+','+','+','+','+','+','+','+', ...

  7. 【Android】自己动手做个扫雷游戏

    1. 游戏规则 扫雷是玩法极其简单的小游戏,点击玩家认为不存在雷的区域,标记出全部地雷所在的区域,即可获得胜利.当点击不包含雷的块的时候,可能它底下存在一个数,也可能是一个空白块.当点击中有数字的块时 ...

  8. C#编写扫雷游戏

    翻看了下以前大学学习的一些小项目,突然发现有个项目比较有意思,觉得有必要把它分享出来.当然现在看来,里面有很多的不足之处,但因博主现在已经工作,没有时间再去优化.这个项目就是利用C#编写一个Windo ...

  9. [Swift]LeetCode529. 扫雷游戏 | Minesweeper

    Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...

随机推荐

  1. CentOs7安装PHP

    来源:https://jingyan.baidu.com/article/2d5afd692df18d85a3e28e4c.html 一.下载源码 1.cd /usr/local/src/ 2. 执行 ...

  2. MFC树形控件的使用(右键点击)

    在MFC中,会用到树形控件,这里做下记录. 右键点击 1.添加右键点击事件(NM_RCLICK) 2.获得鼠标在Client的坐标 CPoint point; GetCursorPos(&po ...

  3. Noxim Overview

    PE+Router= Tile Node Architectural Elements: Buffer.h, Router.h, LocalRoutingTable.h, Tile.h, NoC.h, ...

  4. brew安装和换源

    命令行执行ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&q ...

  5. dom4j 通过 org.dom4j.XPath 设置命名空间来支持 带namespace 的 xpath

    测试文件 test.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:/ ...

  6. JAVA核心问题(一)反射之引言 构造函数

    反射,简单来说,就是在运行时获取Class对象的所有属性和方法,无论公有私有.虽然是一个基础问题,在这里还是全面的记录一下,认真对待! 获取构造函数 构造函数大致分为两种,public和非public ...

  7. C语言中的语句

    • 表达式语句 表达式后加 ; 构成表达式语句. a = b+c; x+y i++ • 控制语句 完成一定的控制功能. if(...){...}else{...}                   ...

  8. Codeforces Round #541--1131F. Asya And Kittens(基础并查集)

    https://codeforces.com/contest/1131/problem/F #include<bits/stdc++.h> using namespace std; int ...

  9. java jar 包加载文件问题

    场景:   A 项目是一个服务,然后部署到本地 maven 仓库里,然后 B 项目依赖 A 项目,调用  A 项目的方法,但是发现,报错,说找不到文件(config.xsv).这就很奇怪了,怎么会呢, ...

  10. Bootstrap框架的基本使用

    Bootstrap是什么 简介 就是已经写好的一个html和css的样式组合 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应 ...