鱼C论坛

 找回密码
 立即注册
查看: 1354|回复: 0

[技术交流] 自己写了一个简单的五子棋给各位大神看看

[复制链接]
发表于 2019-5-4 15:46:33 | 显示全部楼层 |阅读模式

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

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

x
这是我用 SDK 写的,很简单,基本功能是实现了  
/* -------------------------------------------------------------------
MyWindows.c -- 基本窗口模型
《Windows 程序设计(SDK)》视频教程
--------------------------------------------------------------------*/

#include <windows.h>
#include <strsafe.h>
#include<windowsx.h>

//  判断白黑棋是否赢
bool  black_white_win(const POINT *PW, int w_num);

//  一个画白色圆的函数 传入一个坐标
void  my_Circle(HDC hdc, POINT cri);

//  一个画黑色圆的函数 传入一个坐标
void  my_Circle_b(HDC hdc, POINT cri);

//  棋盘
void DrawSquare(HDC hdc, POINT point);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
        static TCHAR szAppName[] = TEXT("MyWindows");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;

        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;

        if (!RegisterClass(&wndclass))
        {
                MessageBox(NULL, TEXT("这个程序需要在 Windows NT 才能执行!"), szAppName, MB_ICONERROR);
                return 0;
        }

        hwnd = CreateWindow(szAppName,
                TEXT("鱼C工作室"),
                WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL);

        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);

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

        return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        HDC hdc;
        PAINTSTRUCT ps;
        RECT rect;
        static int cxClient, cyClient;      //  表是客户区的宽 和 高
        size_t  iTarget;                   //  unsigent int 无符号整形 用来计算字符串长度

        static int cx_char;        //  水平 与 垂直 方向字体的设置
        static int cy_char;

        //  TEXTMETRIC 结构记录当前设备环境中有关字体的各种信息。
        //  结构成员的值的单位取决于设备环境中当前选定的映射模式,默认的映射模式是 MM_TEXT,所以它们的值是以像素为单位的
        TEXTMETRIC tm;        //  指向 TEXTMETRIC 的指针

        static TCHAR szBuffer[128] = TEXT("五子棋少年的追梦之旅");

        static TCHAR sz_rule[128] = TEXT("规则:1.按鼠标左右键下棋 按左键白子先下 按右键黑子先下    2.任意一方五个棋子相连获得胜利");

        static TCHAR wb_szstr[128];

        int x, y , xPos , yPos;    //  xPos yPos 表示鼠标点击的坐标

        POINT point;

        static int numA = 0, numB = 0;    //  记录落子的个数

        static POINT w_point[1000];      //  记录白子的所有坐标

        static POINT b_point[1000];     //  记录黑子的所有坐标

        int i;

        //  控制黑白子是否落下的开关( 1表示关 0表示开)
        static int w_off = 0, b_off = 0;

        //  赢了后接受消息
        int S_MSG;



        switch (message)
        {
        case WM_CREATE:
                hdc = GetDC(hwnd);

                GetTextMetrics(hdc , &tm);

                cx_char = tm.tmAveCharWidth;
                cy_char = tm.tmHeight + tm.tmExternalLeading;

                ReleaseDC(hwnd , hdc);
                return 0;

        case WM_SIZE:
                cxClient = LOWORD(lParam);     //  获得客户区的宽
                cyClient = HIWORD(lParam);    //   获得客户区的高


        case WM_PAINT:
                hdc = BeginPaint(hwnd, &ps);
                GetClientRect(hwnd, &rect);


                SetTextAlign(hdc,GetTextAlign(hdc) | TA_LEFT );

                //  绘制棋盘方格
                StringCchLength(szBuffer , 128 , &iTarget);
                TextOut(hdc, cxClient/2-100, cy_char, szBuffer, iTarget);

                for (x = 40; x < cxClient-40; x+=20)
                {
                        for (y = 40; y < cyClient-40; y += 20)
                        {
                                point.x = x;
                                point.y = y;
                                DrawSquare(hdc, point);
                        }
                }


                StringCchLength(sz_rule, 128, &iTarget);

                TextOut(hdc, cy_char, cyClient-25, sz_rule, iTarget);



                EndPaint(hwnd, &ps);
                return 0;

                //  WM_LBUTTONUP        0x0202        释放鼠标左键
        case  WM_LBUTTONUP:
                hdc = GetDC(hwnd);
                GetClientRect(hwnd, &rect);

                xPos = GET_X_LPARAM(lParam);//  GET_X_LPARAM(lParam) 返回坐标的 x 值;
                yPos = GET_Y_LPARAM(lParam);//  GET_Y_LPARAM(lParam) 返回坐标的 y 值;
                //  用户通常没办法将鼠标100%点中下棋子的位置,因此我们的程序应该自动找到最接近的下子位置
                if (xPos % 20 >= 10)
                        xPos = xPos + 10 - xPos % 10;
                else
                        xPos = xPos - xPos % 10;

                if (yPos % 20 >= 10)
                        yPos = yPos + 10 - yPos % 10;
                else
                        yPos = yPos - yPos % 10;


                
                //  画一个白色的圆
                point.x = xPos;
                point.y = yPos;
                // 下的棋子的位置不能超界
                if (point.x < 40 || point.y < 40)
                {
                        ReleaseDC(hwnd, hdc);
                        return 0;
                }
                //  判断与黑子的坐标是否重复
                for (i = 0; i < numB; i++)
                {
                        if (point.x == b_point[i].x && point.y == b_point[i].y )
                        {
                                ReleaseDC(hwnd, hdc);
                                return 0;
                        }

                }

                //  判断白子有没有多画(只画一个白子)
                if (w_off == 1)
                {
                        ReleaseDC(hwnd, hdc);
                        return 0;
                }

                //  记录下白子的坐标
                w_point[numA] = point;
                numA+=1;

                
                


                StringCchPrintf(wb_szstr, 128, TEXT("%d 白棋坐标(%d , %d)"), numA ,  point.x, point.y);

                StringCchLength(wb_szstr, 128, &iTarget);

                TextOut(hdc , rect.right-200 , 10 , wb_szstr, iTarget);

                my_Circle(hdc , point);
                w_off = 1;  //  画完白子后关了
                b_off = 0; //   画完白子后开

                //  判断棋子是否赢
                if (  numA >= 5 && black_white_win(w_point , numA)  )
                {
                        S_MSG = MessageBox(NULL , TEXT("恭喜白子获得胜利\n是不是要开始新的一局?") , TEXT("赢了。。赢了") , MB_YESNO);

                        if (IDYES == S_MSG)
                        {
                                
                                for (int i = 0; i <numA; i++)
                                {
                                        w_point[i].x = 0;
                                        w_point[i].y = 0;

                                        b_point[i].x = 0;
                                        b_point[i].y = 0;
                                }

                                numB = 0;
                                numA = 0;

                                w_off = 0;
                                b_off = 0;

                                InvalidateRect(hwnd, NULL, TRUE);
                                UpdateWindow(hwnd);
                                ReleaseDC(hwnd, hdc);
                                return 0;
                        }

                }



                ReleaseDC(hwnd , hdc);
                return 0;
                //  WM_RBUTTONDOWN        0x0204        按下鼠标右键

        case WM_RBUTTONDOWN:
                hdc = GetDC(hwnd);
                GetClientRect(hwnd, &rect);

                xPos = GET_X_LPARAM(lParam);//  GET_X_LPARAM(lParam) 返回坐标的 x 值;
                yPos = GET_Y_LPARAM(lParam);//  GET_Y_LPARAM(lParam) 返回坐标的 y 值;
                                                                        //  用户通常没办法将鼠标100%点中下棋子的位置,因此我们的程序应该自动找到最接近的下子位置

                if (xPos % 20 >= 10)
                        xPos = xPos + 10 - xPos % 10;
                else
                        xPos = xPos - xPos % 10;

                if (yPos % 20 >= 10)
                        yPos = yPos + 10 - yPos % 10;
                else
                        yPos = yPos - yPos % 10;



                //  画一个黑色的圆
                point.x = xPos;
                point.y = yPos;
                // 下的棋子的位置不能超界
                if (point.x < 40 || point.y < 40)
                {
                        ReleaseDC(hwnd, hdc);
                        return 0;
                }
                //  判断与白子的坐标是否重复
                for (i = 0; i < numA; i++)
                {
                        if (point.x == w_point[i].x && point.y == w_point[i].y )
                        {
                                ReleaseDC(hwnd, hdc);
                                return 0;
                        }

                }

                //  判断黑子有没有多画(只画一个黑子)
                if (b_off == 1)
                {
                        ReleaseDC(hwnd, hdc);
                        return 0;
                }

                b_point[numB] = point;
                numB+=1;

                


                StringCchPrintf(wb_szstr, 128, TEXT("%d 黑棋坐标(%d , %d)"), numB, point.x, point.y);

                StringCchLength(wb_szstr, 128, &iTarget);

                TextOut(hdc, rect.left, 10, wb_szstr, iTarget);

                //  画黑子
                my_Circle_b(hdc, point);

                w_off = 0;  //  画完黑子后开
                b_off = 1;  //  画完黑子后关了

                //  判断棋子是否赢
                if (numB >= 5 && black_white_win(b_point, numB))
                {
                        S_MSG = MessageBox(NULL, TEXT("恭喜黑子获得胜利\n是不是要开始新的一局?"), TEXT("赢了。。赢了"), MB_YESNO);

                        if (IDYES == S_MSG)
                        {
                                
                                for (int i = 0; i < numB; i++)
                                {
                                        b_point[i].x = 0;
                                        b_point[i].y = 0;

                                        w_point[i].x = 0;
                                        w_point[i].y = 0;
                                }

                                numB = 0;
                                numA = 0;

                                w_off = 0;
                                b_off = 0;


                                InvalidateRect(hwnd, NULL, TRUE);
                                UpdateWindow(hwnd);
                                ReleaseDC(hwnd, hdc);
                                return 0;
                        }
                }

        
                ReleaseDC(hwnd, hdc);
                return 0;



        case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
        }

        return DefWindowProc(hwnd, message, wParam, lParam);
}

void  my_Circle(HDC hdc, POINT cri)
{

        //  根据中心点的坐标 确定左上角和右下角的坐标

        RECT rect;

        rect.right = cri.x - 10;
        rect.top = cri.y - 10;

        rect.left = cri.x + 10;
        rect.bottom = cri.y + 10;

        //  画园
        Ellipse(hdc, rect.right, rect.top, rect.left, rect.bottom);

        return;

}

void  my_Circle_b(HDC hdc, POINT cri)
{

        //  根据中心点的坐标 确定左上角和右下角的坐标
        RECT rect;
        //  定义一个画刷类型
        HBRUSH  hBrush, holdBrush;

        rect.right = cri.x - 10;
        rect.top = cri.y - 10;

        rect.left = cri.x + 10;
        rect.bottom = cri.y + 10;

        hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);  //  BLACK_BRUSH        黑色画刷
                                                                                                   //  SelectObject 函数用于选择一对象到指定的设备环境中,该新对象将替换先前的相同类型的对象
        holdBrush = (HBRUSH)SelectObject(hdc, hBrush);
        //  画园
        Ellipse(hdc, rect.right, rect.top, rect.left, rect.bottom);
        SelectObject(hdc, holdBrush);

        return;

}

void DrawSquare(HDC hdc, POINT point)
{
        MoveToEx(hdc, point.x, point.y, NULL);
        LineTo(hdc, point.x + 20, point.y);
        LineTo(hdc, point.x + 20, point.y + 20);
        LineTo(hdc, point.x, point.y + 20);
        LineTo(hdc, point.x, point.y);


}




//  判断白棋是否赢
bool  black_white_win(const POINT *PW, int w_num)
{

        POINT temp;
        POINT A[4];

        int num_con = 0;

        //  遍历整个数组
        for (int i = 0; i < w_num; i++)
        {
                //  把要判断的白子赋给temp
                temp = *(PW + i);

                for (int a = 0 ; a < 4; a++ )
                {
                        //同一方向的向右的四个棋子存入数组
                        A[a].x = temp.x + (a + 1) * 20;
                        A[a].y = temp.y;
                }

                //  判断同一方向的向右的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;


                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向左的四个棋子存入数组
                        A[a].x = temp.x - (a + 1) * 20;
                        A[a].y = temp.y;
                }

                //  判断同一方向的向左的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;


                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向上的四个棋子存入数组
                        A[a].x = temp.x;
                        A[a].y = temp.y - (a+1)*20;
                }

                //  判断同一方向的向上的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;


                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向下的四个棋子存入数组
                        A[a].x = temp.x;
                        A[a].y = temp.y + (a + 1) * 20;
                }

                //  判断同一方向的向下的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;


                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向左斜上的四个棋子存入数组
                        A[a].x = temp.x - (a + 1) * 20;
                        A[a].y = temp.y - (a + 1) * 20;
                }

                //  判断同一方向的向左斜上的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;


                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向左斜下的四个棋子存入数组
                        A[a].x = temp.x - (a + 1) * 20;
                        A[a].y = temp.y + (a + 1) * 20;
                }

                //  判断同一方向的向左斜下的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;

                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向右斜下的四个棋子存入数组
                        A[a].x = temp.x + (a + 1) * 20;
                        A[a].y = temp.y + (a + 1) * 20;
                }

                //  判断同一方向的向右斜下的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;

                for (int a = 0; a < 4; a++)
                {
                        //同一方向的向右斜上的四个棋子存入数组
                        A[a].x = temp.x + (a + 1) * 20;
                        A[a].y = temp.y - (a + 1) * 20;
                }

                //  判断同一方向的向右斜上的四个棋子是否在数组内
                for (int b = 0; b < 4; b++)
                {
                        for (int y = 0; y < w_num; y++)
                        {
                                if (A[b].x == (*(PW + y)).x && A[b].y == (*(PW + y)).y)
                                        num_con++;

                        }

                }
                if (num_con == 4)
                        return true;
                else
                        num_con = 0;
        

        }


        return false;

}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-17 04:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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