鱼C论坛

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

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

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

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

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

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

  5. #include <windows.h>
  6. #include <strsafe.h>
  7. #include<windowsx.h>

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

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

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

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

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

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

  23.         wndclass.style = CS_HREDRAW | CS_VREDRAW;
  24.         wndclass.lpfnWndProc = WndProc;
  25.         wndclass.cbClsExtra = 0;
  26.         wndclass.cbWndExtra = 0;
  27.         wndclass.hInstance = hInstance;
  28.         wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  29.         wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  30.         wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  31.         wndclass.lpszMenuName = NULL;
  32.         wndclass.lpszClassName = szAppName;

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

  38.         hwnd = CreateWindow(szAppName,
  39.                 TEXT("鱼C工作室"),
  40.                 WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
  41.                 CW_USEDEFAULT,
  42.                 CW_USEDEFAULT,
  43.                 CW_USEDEFAULT,
  44.                 CW_USEDEFAULT,
  45.                 NULL,
  46.                 NULL,
  47.                 hInstance,
  48.                 NULL);

  49.         ShowWindow(hwnd, iCmdShow);
  50.         UpdateWindow(hwnd);

  51.         while (GetMessage(&msg, NULL, 0, 0))
  52.         {
  53.                 TranslateMessage(&msg);
  54.                 DispatchMessage(&msg);
  55.         }

  56.         return msg.wParam;
  57. }

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

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

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

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

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

  72.         static TCHAR wb_szstr[128];

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

  74.         POINT point;

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

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

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

  78.         int i;

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

  81.         //  赢了后接受消息
  82.         int S_MSG;



  83.         switch (message)
  84.         {
  85.         case WM_CREATE:
  86.                 hdc = GetDC(hwnd);

  87.                 GetTextMetrics(hdc , &tm);

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

  90.                 ReleaseDC(hwnd , hdc);
  91.                 return 0;

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


  95.         case WM_PAINT:
  96.                 hdc = BeginPaint(hwnd, &ps);
  97.                 GetClientRect(hwnd, &rect);


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

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

  102.                 for (x = 40; x < cxClient-40; x+=20)
  103.                 {
  104.                         for (y = 40; y < cyClient-40; y += 20)
  105.                         {
  106.                                 point.x = x;
  107.                                 point.y = y;
  108.                                 DrawSquare(hdc, point);
  109.                         }
  110.                 }


  111.                 StringCchLength(sz_rule, 128, &iTarget);

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



  113.                 EndPaint(hwnd, &ps);
  114.                 return 0;

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

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

  126.                 if (yPos % 20 >= 10)
  127.                         yPos = yPos + 10 - yPos % 10;
  128.                 else
  129.                         yPos = yPos - yPos % 10;


  130.                
  131.                 //  画一个白色的圆
  132.                 point.x = xPos;
  133.                 point.y = yPos;
  134.                 // 下的棋子的位置不能超界
  135.                 if (point.x < 40 || point.y < 40)
  136.                 {
  137.                         ReleaseDC(hwnd, hdc);
  138.                         return 0;
  139.                 }
  140.                 //  判断与黑子的坐标是否重复
  141.                 for (i = 0; i < numB; i++)
  142.                 {
  143.                         if (point.x == b_point[i].x && point.y == b_point[i].y )
  144.                         {
  145.                                 ReleaseDC(hwnd, hdc);
  146.                                 return 0;
  147.                         }

  148.                 }

  149.                 //  判断白子有没有多画(只画一个白子)
  150.                 if (w_off == 1)
  151.                 {
  152.                         ReleaseDC(hwnd, hdc);
  153.                         return 0;
  154.                 }

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

  158.                
  159.                


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

  161.                 StringCchLength(wb_szstr, 128, &iTarget);

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

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

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

  170.                         if (IDYES == S_MSG)
  171.                         {
  172.                                
  173.                                 for (int i = 0; i <numA; i++)
  174.                                 {
  175.                                         w_point[i].x = 0;
  176.                                         w_point[i].y = 0;

  177.                                         b_point[i].x = 0;
  178.                                         b_point[i].y = 0;
  179.                                 }

  180.                                 numB = 0;
  181.                                 numA = 0;

  182.                                 w_off = 0;
  183.                                 b_off = 0;

  184.                                 InvalidateRect(hwnd, NULL, TRUE);
  185.                                 UpdateWindow(hwnd);
  186.                                 ReleaseDC(hwnd, hdc);
  187.                                 return 0;
  188.                         }

  189.                 }



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

  193.         case WM_RBUTTONDOWN:
  194.                 hdc = GetDC(hwnd);
  195.                 GetClientRect(hwnd, &rect);

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

  199.                 if (xPos % 20 >= 10)
  200.                         xPos = xPos + 10 - xPos % 10;
  201.                 else
  202.                         xPos = xPos - xPos % 10;

  203.                 if (yPos % 20 >= 10)
  204.                         yPos = yPos + 10 - yPos % 10;
  205.                 else
  206.                         yPos = yPos - yPos % 10;



  207.                 //  画一个黑色的圆
  208.                 point.x = xPos;
  209.                 point.y = yPos;
  210.                 // 下的棋子的位置不能超界
  211.                 if (point.x < 40 || point.y < 40)
  212.                 {
  213.                         ReleaseDC(hwnd, hdc);
  214.                         return 0;
  215.                 }
  216.                 //  判断与白子的坐标是否重复
  217.                 for (i = 0; i < numA; i++)
  218.                 {
  219.                         if (point.x == w_point[i].x && point.y == w_point[i].y )
  220.                         {
  221.                                 ReleaseDC(hwnd, hdc);
  222.                                 return 0;
  223.                         }

  224.                 }

  225.                 //  判断黑子有没有多画(只画一个黑子)
  226.                 if (b_off == 1)
  227.                 {
  228.                         ReleaseDC(hwnd, hdc);
  229.                         return 0;
  230.                 }

  231.                 b_point[numB] = point;
  232.                 numB+=1;

  233.                


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

  235.                 StringCchLength(wb_szstr, 128, &iTarget);

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

  237.                 //  画黑子
  238.                 my_Circle_b(hdc, point);

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

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

  245.                         if (IDYES == S_MSG)
  246.                         {
  247.                                
  248.                                 for (int i = 0; i < numB; i++)
  249.                                 {
  250.                                         b_point[i].x = 0;
  251.                                         b_point[i].y = 0;

  252.                                         w_point[i].x = 0;
  253.                                         w_point[i].y = 0;
  254.                                 }

  255.                                 numB = 0;
  256.                                 numA = 0;

  257.                                 w_off = 0;
  258.                                 b_off = 0;


  259.                                 InvalidateRect(hwnd, NULL, TRUE);
  260.                                 UpdateWindow(hwnd);
  261.                                 ReleaseDC(hwnd, hdc);
  262.                                 return 0;
  263.                         }
  264.                 }

  265.        
  266.                 ReleaseDC(hwnd, hdc);
  267.                 return 0;



  268.         case WM_DESTROY:
  269.                 PostQuitMessage(0);
  270.                 return 0;
  271.         }

  272.         return DefWindowProc(hwnd, message, wParam, lParam);
  273. }

  274. void  my_Circle(HDC hdc, POINT cri)
  275. {

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

  277.         RECT rect;

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

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

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

  284.         return;

  285. }

  286. void  my_Circle_b(HDC hdc, POINT cri)
  287. {

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

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

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

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

  302.         return;

  303. }

  304. void DrawSquare(HDC hdc, POINT point)
  305. {
  306.         MoveToEx(hdc, point.x, point.y, NULL);
  307.         LineTo(hdc, point.x + 20, point.y);
  308.         LineTo(hdc, point.x + 20, point.y + 20);
  309.         LineTo(hdc, point.x, point.y + 20);
  310.         LineTo(hdc, point.x, point.y);


  311. }




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

  315.         POINT temp;
  316.         POINT A[4];

  317.         int num_con = 0;

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

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

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

  336.                         }

  337.                 }
  338.                 if (num_con == 4)
  339.                         return true;
  340.                 else
  341.                         num_con = 0;


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

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

  355.                         }

  356.                 }
  357.                 if (num_con == 4)
  358.                         return true;
  359.                 else
  360.                         num_con = 0;


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

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

  374.                         }

  375.                 }
  376.                 if (num_con == 4)
  377.                         return true;
  378.                 else
  379.                         num_con = 0;


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

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

  393.                         }

  394.                 }
  395.                 if (num_con == 4)
  396.                         return true;
  397.                 else
  398.                         num_con = 0;


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

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

  412.                         }

  413.                 }
  414.                 if (num_con == 4)
  415.                         return true;
  416.                 else
  417.                         num_con = 0;


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

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

  431.                         }

  432.                 }
  433.                 if (num_con == 4)
  434.                         return true;
  435.                 else
  436.                         num_con = 0;

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

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

  450.                         }

  451.                 }
  452.                 if (num_con == 4)
  453.                         return true;
  454.                 else
  455.                         num_con = 0;

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

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

  469.                         }

  470.                 }
  471.                 if (num_con == 4)
  472.                         return true;
  473.                 else
  474.                         num_con = 0;
  475.        

  476.         }


  477.         return false;

  478. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-6 20:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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