鱼C论坛

 找回密码
 立即注册
查看: 2663|回复: 4

Windows编程写了个扫雷,但是退出的时候会出现Stack Overflow求解决

[复制链接]
发表于 2014-7-26 14:50:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#define UNICODE
#include <Windows.h>
#include <strsafe.h>
#include <windowsx.h>
#include <time.h>

#define HEIGHT 15
#define WIDTH 15
#define MAX_STRING 256

#define LAND L'○'
#define MINE L'●'
#define SAFE L' '

TCHAR szMatrix[MAX_STRING][MAX_STRING];                //扫雷游戏区域
size_t nSide;                        //区域边长
BOOL bMine[MAX_STRING][MAX_STRING];        //记录雷的位置
UINT uMine[MAX_STRING][MAX_STRING];        //记录周围雷的个数
int nMine;        //记录雷的个数

LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,INT nCmdShow)
{
        static TCHAR szClassName[] = TEXT("MyClass");
        WNDCLASS wndclass;
        HWND hwnd;
        MSG msg;

        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hbrBackground = (HBRUSH)GetStockObject(DC_BRUSH);
        wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
        wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
        wndclass.hInstance = hInstance;
        wndclass.lpfnWndProc = WindowProc;
        wndclass.lpszClassName = szClassName;
        wndclass.lpszMenuName = NULL;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        
        if (!RegisterClass(&wndclass))
        {
                MessageBox(NULL,TEXT("本程序必须在WINNT下运行!"),TEXT("警告"),MB_OK);
                return 0;
        }

        nSide = 20;
        nMine = 40;
        for (int i=0;i<nSide;i++)
        {
                for (int j=0;j<nSide;j++)
                {
                        szMatrix[i][j] = LAND;
                }
        }

        srand((unsigned)time(NULL));
        //下面随机出现nMine颗雷
        for (int i=0;i<nMine;i++)
        {
                int x = rand()%nSide;
                int y = rand()%nSide;
                if (!bMine[x][y])
                {
                        bMine[x][y] = TRUE;
                }
                else
                {
                        i--;
                }
        }
        //下面计算每一块周围有多少颗雷
        for (int i=0;i<nSide;i++)
        {
                for (int j=0;j<nSide;j++)
                {
                        if (bMine[i][j])        continue;                //当前块是雷
                        int nCounts = 0;
                        for (int m=i-1;m<=i+1;m++)
                        {
                                if (m<0 || m>=nSide)        continue;
                                for (int n=j-1;n<=j+1;n++)
                                {
                                        if (n<0 || n>=nSide)        continue;
                                        if (bMine[m][n])        nCounts++;
                                }
                        }
                        //存储雷数nCounts
                        uMine[i][j] = nCounts;
                }
        }

        hwnd = CreateWindow(szClassName,
                                                TEXT("BY:落叶"),
                                                WS_OVERLAPPEDWINDOW,
                                                CW_USEDEFAULT,
                                                CW_USEDEFAULT,
                                                CW_USEDEFAULT,
                                                CW_USEDEFAULT,
                                                NULL,
                                                NULL,
                                                hInstance,
                                                NULL);

        ShowWindow(hwnd,nCmdShow);
        UpdateWindow(hwnd);

        while (GetMessage(&msg,NULL,0,0))
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }

        return msg.wParam;
}

void SwipeLand(HDC hdc,int x,int y,BOOL bRecord[MAX_STRING][MAX_STRING]);        //计算并现出没雷的连续区域

LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
        HDC hdc;
        PAINTSTRUCT ps;
        RECT rect;

        int i,j;        //循环变量
        int xPos,yPos;        //记录鼠标位置
        int x,y;        //记录地雷下标

        switch (uMsg)
        {
                case WM_PAINT:
                        hdc = BeginPaint(hwnd,&ps);
                        //绘制扫雷区域
                        for (i=0;i<nSide;i++)
                        {
                                for (j=0;j<nSide;j++)
                                {
                                        TextOut(hdc,i*WIDTH,j*HEIGHT,&szMatrix[i][j],1);
                                }
                        }
                        EndPaint(hwnd,&ps);
                        break;
                case WM_LBUTTONUP:
                        xPos = GET_X_LPARAM(lParam);
                        yPos = GET_Y_LPARAM(lParam);
                        x = xPos/WIDTH;
                        y = yPos/HEIGHT;
                        if (y < nSide && x < nSide)
                        {
                                hdc = GetDC(hwnd);
                                //判断是否有雷
                                if (bMine[x][y])
                                {
                                        //先显示雷的位置然后退出
                                        for (i=0;i<nSide;i++)
                                                for (j=0;j<nSide;j++)
                                                        if (bMine[i][j])
                                                                TextOut(hdc,i*WIDTH,j*HEIGHT,TEXT("●"),1);
                                        MessageBox(hwnd,TEXT("游戏结束!"),TEXT("提示"),MB_OK);
                                        ReleaseDC(hwnd,hdc);
                                        DestroyWindow(hwnd);
                                        break;
                                }
                                BOOL bRecord[MAX_STRING][MAX_STRING] = {FALSE};        //记录是否已遍历
                                SwipeLand(hdc,x,y,bRecord);
                                ReleaseDC(hwnd,hdc);
                        }
                        break;
                case WM_CLOSE:
                        if (IDYES == MessageBox(hwnd,TEXT("确认退出扫雷?"),TEXT("提示"),MB_YESNO | MB_ICONINFORMATION))
                                DestroyWindow(hwnd);
                        break;
                case WM_DESTROY:
                        PostQuitMessage(0);
                        break;
                default:
                        return DefWindowProc(hwnd,uMsg,wParam,lParam);
        }

        return 0;
}

void SwipeLand(HDC hdc,int x,int y,BOOL bRecord[MAX_STRING][MAX_STRING])        //计算并现出没雷的连续区域
{
        bRecord[x][y] = TRUE;
        if (x<0 || x>=nSide || y<0 || y>=nSide)        return;
        static TCHAR szMine[5];        //为显示雷做准备
        //现出当前位置
        StringCchPrintf(szMine,5,TEXT(" "));
        TextOut(hdc,x*WIDTH,y*HEIGHT,szMine,1);
        if (uMine[x][y]>0)
        {
                StringCchPrintf(szMine,5,TEXT("%d"),uMine[x][y]);
                TextOut(hdc,x*WIDTH,y*HEIGHT,szMine,1);
                return;
        }
        //现出上下左右4个方向
        if (!bRecord[x][y-1])        SwipeLand(hdc,x,y-1,bRecord);
        if (!bRecord[x][y+1])        SwipeLand(hdc,x,y+1,bRecord);
        if (!bRecord[x-1][y])        SwipeLand(hdc,x-1,y,bRecord);
        if (!bRecord[x+1][y])        SwipeLand(hdc,x+1,y,bRecord);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-7-26 18:01:33 | 显示全部楼层
好高端,大气
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-7-28 20:09:13 | 显示全部楼层
好流弊的样子
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-8-7 00:44:39 | 显示全部楼层
我也在写。。不过是淡季后图片的重绘问题。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-13 17:53:18 | 显示全部楼层
把问题顶起来
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 09:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表