扫雷,但C语言桌面版

直接贴代码,有时间再解释

main.c

#include "game.h"

HINSTANCE hInst;
int g = -1, m = 0;
char a[heng][shu] = {0}, b[heng][shu] = {0}, c[heng][shu] = {0};

LRESULT CALLBACK WndProc(  HWND hWnd,
                           UINT message,
                           WPARAM wParam,
                           LPARAM lParam) {
	PAINTSTRUCT ps;
	HDC hdc;

	int i,j,z;
	int wmId, wmEvent;

	static TCHAR szTextBuf[20];
	static HPEN hPen;	//画笔
	static HBRUSH hBrush;  //画刷
	static HFONT hFont; //声明一个逻辑字体句柄为静态变量
	static HWND hStatic;
	static HWND hStaticBtn[10][10]; //展示的格子
	switch(message) {
		case  WM_CREATE:
			//创建画刷
			hBrush = CreateSolidBrush( RGB(0x41, 0x96, 0x4F) );
			//创建逻辑字体
			hFont = CreateFont( -15/*高度*/, -7.5/*宽度*/, 0/*不用管*/, 0/*不用管*/, 400 /*一般这个值设为400*/,
			                    FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
			                    DEFAULT_CHARSET,  //这里我们使用默认字符集,还有其他以 _CHARSET 结尾的常量可用
			                    OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,  //这行参数不用管
			                    DEFAULT_QUALITY,  //默认输出质量
			                    FF_DONTCARE,  //不指定字体族*/
			                    TEXT("微软雅黑")  //字体名
			                  );
			hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));

			//创建静态文本控件
			hStatic = CreateWindow(
			              TEXT("static"),  //静态文本框的类名
			              TEXT("welcome 扫雷"),  //控件的文本
			              WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | SS_CENTER /*带边框*/,
			              200 /*X坐标*/, 10/*Y坐标*/, 150/*宽度*/, 40/*高度*/, hWnd/*父窗口句柄*/,
			              (HMENU)101, hInst, /*当前实例句柄*/ NULL
			          );
			for(i=0; i<10; i++) {
				for(j=0; j<10; j++) {
					z=i*10+j;
					//创建按钮控件szTextBuf
					wsprintf(szTextBuf, TEXT("%d"),z);
					hStaticBtn[i][j] = CreateWindow(
//					                       TEXT("button"),  //按钮控件的类名
					                       TEXT("static"),  //按钮控件的类名
					                       TEXT(" "),
					                       WS_CHILD | WS_VISIBLE | WS_BORDER | BS_FLAT/*扁平样式*/,
					                       120+j*33 /*X坐标*/, 60+i*33 /*Y坐标*/, 30 /*宽度*/, 30/*高度*/,
					                       hWnd, (HMENU)z /*控件唯一标识符*/, hInst, NULL
					                   );
				}
			}
			SendMessage(hStatic,WM_SETFONT,(WPARAM)hFont, NULL);//设置文本框字体
			for(i=0; i<10; i++) {
				for(j=0; j<10; j++) {
					SendMessage(hStaticBtn[i][j], WM_SETFONT, (WPARAM)hFont, NULL);//设置按钮字体
				}
			}
			break;
		case WM_KEYDOWN: {
			if(wParam == VK_ESCAPE) //按下esc退出
				DestroyWindow(hWnd);
			break;
		}
		case WM_LBUTTONDOWN: {//左键
			j = ( LOWORD(lParam) -120 ) / 33 + 1;
			i = ( HIWORD(lParam) -60  ) / 33 + 1;
			wsprintf(szTextBuf, TEXT("左键点击\n下标为 %d %d"),i,j);
			SetWindowText(hStatic, szTextBuf);
			if(i<=10 && i>0 && j<=10 && j>0) {
				g = dianji(a, b, c, i, j);
			}
			dayin(a ,hStaticBtn );

			if (g == 0) {
				baozha(a, b);
				dayin(a ,hStaticBtn );
				MessageBox(hWnd, "很不幸,你点到了炸弹\n游戏结束", TEXT("失败"), MB_ICONINFORMATION);
				DestroyWindow(hWnd);
			}
			break;
		}
		case WM_RBUTTONDOWN: {//右键
			j = ( LOWORD(lParam) -120 ) / 33 + 1;
			i = ( HIWORD(lParam) -60  ) / 33 + 1;
			if(i<=(shu-2) && i>0 && j<=(heng-2) && j>0) {
				a[i][j] = '?';
				m++;
			}
			dayin(a ,hStaticBtn );
			if (shengli(a, b, m ) == 1) {
				MessageBox(hWnd, "游戏胜利", TEXT("胜利"), MB_ICONINFORMATION);
				DestroyWindow(hWnd);
			}
			wsprintf(szTextBuf, TEXT("右键点击\n下标为 %d %d"),i,j);
			SetWindowText(hStatic, szTextBuf);
			break;
		}
		case WM_DESTROY: { //请做好善后工作
			DeleteObject(hBrush);
			DeleteObject(hFont);
			DeleteObject(hPen);
			PostQuitMessage(0);
			break;
		}

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; 
	HWND hwnd;
	MSG msg; 

	memset(&wc,0,sizeof(wc));
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.lpfnWndProc	 = WndProc;
	wc.hInstance	 = hInstance;
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);

	chushihua(b);//初始化炸弹和数字 

	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION); 
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION); 

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Welcome-扫雷",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
	                      600, /* x */
	                      150, /* y */
	                      600, /* width */
	                      500, /* height */
	                      NULL,NULL,hInstance,NULL);

	if(hwnd == NULL) {
		MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	while(GetMessage(&msg, NULL, 0, 0) > 0) { 
		TranslateMessage(&msg); 
		DispatchMessage(&msg); /* 向WndProc发送消息 */
	}
	return msg.wParam;
}

game.h(跟终端版相比,基本没变)

#include <stdio.h>
#include <stdlib.h>  //这个是清屏函数所属函数库
#include <stdarg.h>	 //这个是可变入参头文件 
#include <time.h>    //这个函数库有产生时间戳的函数,产生随机数用
#include <windows.h> //延迟时间函数在这里,为了好看
#include <conio.h>   //getch函数的头文件

#define heng (10 + 2) // 顾名思义,横着得,这个20可以随意更改代表扫雷界面的长
#define shu (10 + 2)  // 顾名思义,竖着的,这个20同样随意更改,表示宽
#define lei 10        // 顾名思义,雷的数量哈哈哈哈

void denglu();                     // 登录界面打印
void game();                       // 游戏函数
void chushihua(char a[heng][shu]); // 初始化
void panduan(char b[heng][shu]);   // 判断雷周围的数字
void xunzhao(char a[heng][shu], char b[heng][shu], char c[heng][shu], int i, int j);
// 寻找可以扩散的方块,即空白块和最边上的数字块
int dianji(char a[heng][shu], char b[heng][shu], char c[heng][shu], int i, int j);
// 点击图上的方块(当然是通过写坐标)
void baozha(char a[heng][shu], char b[heng][shu]);        // 点到雷了,爆炸了
int shengli(char a[heng][shu], char b[heng][shu], int m ); // 胜利!!
void dayin(char a[heng][shu], HWND hStaticBtn[heng-2][shu-2]); // 胜利!!

game.c (跟终端版相比,基本没变)

#include "game.h"

void panduan(char b[heng][shu]) {
	int i, j;  // 记录每个方块的循环
	int x, y;  // 记录当前方块的数字
	int c = 0; // 记录(雷周围的)数字大小
	for (i = 1; i < heng - 1; i++)
		for (j = 1; j < shu - 1; j++)
			if (b[i][j] != '*') {
				c = 0;
				for (x = i - 1; x < i + 2; x++)
					for (y = j - 1; y < j + 2; y++)
						if (b[x][y] == '*')
							c++, b[i][j] = c + 48;
			}
}

void chushihua(char a[heng][shu]) {
	int r = lei;
	int i, j;
	srand((unsigned int)time(NULL)); // 保证每次产生的雷都不一样
	while (r) {
		i = rand() % (heng - 2) + 1;
		j = rand() % (shu - 2) + 1;
		if (a[i][j] != '*') { // 雷可不能放重
			a[i][j] = '*';
			r--;
		}
	}
	panduan(a);
}

void xunzhao(char a[heng][shu], char b[heng][shu], char c[heng][shu], int i, int j) {
	int x, y;
	if (i == 0 || j == 0 || i == heng - 1 || j == shu - 1)
		; // 把最边上的都给屏蔽掉
	else
		for (x = i - 1; x < i + 2; x++)
			for (y = j - 1; y < j + 2; y++)
				if (c[x][y] == 0) { // 每个寻找过得位置都置‘1’,防止浪费栈的空间
					c[x][y] = '1';
					if (b[x][y] == 0) { // 空白块直接展开,并且寻找下一个
						a[x][y] = '0';
						xunzhao(a, b, c, x, y);
					} else if (b[x][y] > '0' && b[x][y] < '9') // 数字块记录但是不再展开
						a[x][y] = b[x][y];
				}
}

int dianji(char a[heng][shu], char b[heng][shu], char c[heng][shu], int i, int j) {
	if (b[i][j] == '*')
		return 0;
	else {
		xunzhao(a, b, c, i, j);
		return 1;
	}
}

void baozha(char a[heng][shu], char b[heng][shu]) {
	int i, j;
	for (i = 0; i < heng; i++)
		for (j = 0; j < shu; j++)
			if (b[i][j] == '*')
				a[i][j] = b[i][j];
}

int shengli(char a[heng][shu], char b[heng][shu], int m ) {
	int i, j;
	int s = 0;;
	if (m == lei) 
		for (i = 1; i < heng; i++)
			for (j = 1; j < shu; j++)
				if (b[i][j] == '*' && a[i][j] == '?') // 雷的位置和标记位置一样
					s++;
	if (s == lei) 
		return 1;
	else
		return 0;
}

void dayin(char a[heng][shu], HWND hStaticBtn[heng-2][shu-2]) {
	int i,j;
	static TCHAR szTextBuf[5];
	for(i=0 ; i<heng-2 ; i++) {
		for(j=0 ; j<shu-2 ; j++) {
			wsprintf(szTextBuf, TEXT("%c"),a[i+1][j+1]);
			SetWindowText(hStaticBtn[i][j], szTextBuf);
			if(a[i+1][j+1]=='0'){
				SetBkColor(hStaticBtn[i][j], RGB(0x41, 0x96, 0x4F) ); 
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值