Tranvick

XO

Apr 16th, 2013
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.56 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "UP_LAB5.h"
  3. #include <windowsx.h>
  4. #include <cmath>
  5.  
  6. #define MAX_LOADSTRING 100
  7. #define IDM_CLASSIC 0
  8. #define IDM_EXIT 1
  9. #define IDM_NEWGAME 2
  10. #define IDM_NCLASSIC 3
  11. #define IDM_MULTIPLAY 4
  12. #define IDM_SINGLEPLAY 5
  13. #define IDM_ABOUT 6
  14.  
  15. HINSTANCE hInst;
  16. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  17. INT_PTR CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM);
  18. INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
  19.  
  20. int APIENTRY _tWinMain(HINSTANCE hInstance,
  21.                      HINSTANCE hPrevInstance,
  22.                      LPTSTR    lpCmdLine,
  23.                      int       nCmdShow)
  24. {
  25.     static TCHAR szWindowClass[] = "Prog";
  26.     MSG msg;
  27.     HWND hWnd;
  28.     WNDCLASSEX wcex;
  29.  
  30.     wcex.cbSize = sizeof(WNDCLASSEX);
  31.     wcex.style          = CS_HREDRAW | CS_VREDRAW;
  32.     wcex.lpfnWndProc    = WndProc;
  33.     wcex.cbClsExtra     = 0;
  34.     wcex.cbWndExtra     = 0;
  35.     wcex.hInstance      = hInstance;
  36.     wcex.hIcon          = LoadIcon(hInstance,NULL);
  37.     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
  38.     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
  39.     wcex.lpszMenuName   = NULL;
  40.     wcex.lpszClassName  = szWindowClass;
  41.     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
  42.     RegisterClassEx(&wcex);
  43.  
  44.     hWnd = CreateWindow(szWindowClass, "Крестики-Нолики", WS_OVERLAPPEDWINDOW,
  45.         CW_USEDEFAULT, 0, 500, 500, NULL, NULL, hInstance, NULL);
  46.  
  47.     hInst = hInstance;
  48.     ShowWindow(hWnd, nCmdShow);
  49.     UpdateWindow(hWnd);
  50.  
  51.     while (GetMessage(&msg, NULL, 0, 0))
  52.     {
  53.             TranslateMessage(&msg);
  54.             DispatchMessage(&msg);
  55.     }
  56.  
  57.     return (int) msg.wParam;
  58. }
  59.  
  60. bool isNear(int x, int y, int map[111][111], int n) {
  61.     if (map[x][y]) return 0;
  62.     const int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0}, dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
  63.     for (int t = 0; t < 8; ++t)
  64.         if (x + dx[t] < n && y + dy[t] < n && x + dx[t] >= 0 && y + dy[t] >= 0 && map[x + dx[t]][y + dy[t]])
  65.             return true;
  66.     return false;
  67. }
  68.  
  69. double Calc(int x, int y, int map[111][111], int n, int w) {
  70.     double res = 0;
  71.     int t1 = 5, t2;
  72.     if (n == 3) t1 = 3;
  73.     t2 = t1 - 1;
  74.     for (int j = y - t2; j <= y; ++j) {
  75.         if (j < 0 || j + t2 >= n) continue;
  76.         int c = 1;
  77.         for (int t = 0; t < t1; ++t) {
  78.             if (!map[x][j + t]) continue;
  79.             if (map[x][j + t] != w) {
  80.                 c = 0;
  81.                 break;
  82.             } else ++c;
  83.         }
  84.         if (c == 1) c = 0;
  85.         if (c) res += pow(3.0, c + .0);
  86.         if (c == t1)
  87.             if (w == 2) res += 100000;
  88.             else res += 1000;
  89.     }
  90.     for (int i = x - t2; i <= x; ++i) {
  91.         if (i < 0 || i + t2 >= n) continue;
  92.         int c = 1;
  93.         for (int t = 0; t < t1; ++t) {
  94.             if (!map[i + t][y]) continue;
  95.             if (map[i + t][y] != w) {
  96.                 c = 0;
  97.                 break;
  98.             } else ++c;
  99.         }
  100.         if (c == 1) c = 0;
  101.         if (c) res += pow(3.0, c + .0);
  102.         if (c == t1)
  103.             if (w == 2) res += 100000;
  104.             else res += 1000;
  105.     }
  106.     for (int i = x - t2, j = y - t2; i <= x; ++i, ++j) {
  107.         if (i < 0 || j < 0 || i + t2 >= n || j + t2 >= n) continue;
  108.         int c = 1;
  109.         for (int t = 0; t < t1; ++t) {
  110.             if (!map[i + t][j + t]) continue;
  111.             if (map[i + t][j + t] != w) {
  112.                 c = 0;
  113.                 break;
  114.             } else ++c;
  115.         }
  116.         if (c == 1) c = 0;
  117.         if (c) res += pow(3.0, c + .0);
  118.         if (c == t1)
  119.             if (w == 2) res += 100000;
  120.             else res += 1000;
  121.     }
  122.     for (int i = x + t2, j = y - t2; i >= x; --i, ++j) {
  123.         if (i >= n || j < 0 || i - t2 < 0 || j + t2 >= n) continue;
  124.         int c = 1;
  125.         for (int t = 0; t < t1; ++t) {
  126.             if (!map[i - t][j + t]) continue;
  127.             if (map[i - t][j + t] != w) {
  128.                 c = 0;
  129.                 break;
  130.             } else ++c;
  131.         }
  132.         if (c == 1) c = 0;
  133.         if (c) res += pow(3.0, c + .0);
  134.         if (c == t1)
  135.             if (w == 2) res += 100000;
  136.             else res += 1000;
  137.     }
  138.     return res;
  139. }
  140.  
  141. bool check(int map[111][111]) {
  142.     int c = 0;
  143.     for (int i = 0; i < 3; ++i)
  144.         for (int j = 0; j < 3; ++j)
  145.             if (map[i][j] == 1) ++c;
  146.     if (c > 2) return false;
  147.     if (c == 1) {
  148.         if (!map[1][1]) map[1][1] = 2;
  149.         else map[0][0] = 2;
  150.         return true;
  151.     }
  152.     if (c == 2)
  153.         if (map[0][0] == 1 && map[2][2] == 1 || map[0][2] == 1 && map[2][0] == 1) {
  154.             map[0][1] = 2;
  155.             return true;
  156.         }
  157.     return false;
  158. }
  159. void GoAI(int map[111][111], int n) {
  160.     if (n == 3 && check(map)) return;
  161.     const double aggr = 0.8;
  162.     int x = -1, y = -1;
  163.     double best = -1.0;
  164.     for (int i = 0; i < n; ++i)
  165.         for (int j = 0; j < n; ++j) {
  166.             if (!isNear(i, j, map, n)) continue;
  167.             double g = Calc(i, j, map, n, 2) + aggr * Calc(i, j, map, n, 1);
  168.             if (g > best) {
  169.                 best = g;
  170.                 x = i;
  171.                 y = j;
  172.             }
  173.         }
  174.     map[x][y] = 2;
  175. }
  176.  
  177. void NewGame(HWND hWnd, int map[111][111], int n, int & turn) {
  178.     turn = 0;
  179.     for (int i = 0; i < n; ++i)
  180.         for (int j = 0; j < n; ++j) map[i][j] = 0;
  181.     InvalidateRect(hWnd, NULL, true);
  182. }
  183.  
  184. int GameOver(int map[111][111], int n) {
  185.     bool draw = 1;
  186.     int lim = 5;
  187.     if (n == 3) lim = 3;
  188.     for (int i = 0; i < n; ++i)
  189.         for (int j = 0; j < n; ++j) {
  190.             if (!map[i][j]) {
  191.                 draw = 0;
  192.                 continue;
  193.             }
  194.             for (int t = 1; t < lim; ++t) {
  195.                 if (i + t == n) break;
  196.                 if (map[i][j] != map[i + t][j]) break;
  197.                 if (t == lim - 1) return map[i][j];
  198.             }
  199.             for (int t = 1; t < lim; ++t) {
  200.                 if (j + t == n) break;
  201.                 if (map[i][j] != map[i][j + t]) break;
  202.                 if (t == lim - 1) return map[i][j];
  203.             }
  204.             for (int t = 1; t < lim; ++t) {
  205.                 if (j + t == n || i - t == -1) break;
  206.                 if (map[i][j] != map[i - t][j + t]) break;
  207.                 if (t == lim - 1) return map[i][j];
  208.             }
  209.             for (int t = 1; t < lim; ++t) {
  210.                 if (j + t == n || i + t == n) break;
  211.                 if (map[i][j] != map[i + t][j + t]) break;
  212.                 if (t == lim - 1) return map[i][j];
  213.             }
  214.         }
  215.     if (draw) return 3;
  216.     return 0;
  217. }
  218.  
  219. void EndGame(HWND hWnd, int player, int players) {
  220.     if (player == 3) MessageBox(hWnd, "Ничья", "Конец игры", MB_OK | MB_ICONINFORMATION);
  221.     if (player == 1) MessageBox(hWnd, "Победил первый игрок", "Конец игры", MB_OK | MB_ICONINFORMATION);
  222.     if (player == 2 && players == 2) MessageBox(hWnd, "Победил второй игрок", "Конец игры", MB_OK | MB_ICONINFORMATION);
  223.     if (player == 2 && players == 1) MessageBox(hWnd, "Победил компьютер", "Конец игры", MB_OK | MB_ICONINFORMATION);
  224. }
  225.  
  226. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  227. {
  228.     int wmId;
  229.     PAINTSTRUCT ps;
  230.     HDC hdc;
  231.     static HMENU hMenu, hFileMenu, hInfoMenu, hParamMenu;
  232.     static int iSize, map[111][111], turn, x, y, players, temp;
  233.     static RECT rect;
  234.     static const HPEN hpRed = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)),
  235.         hpBlue = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
  236.     GetClientRect(hWnd, &rect);
  237.     switch (message)
  238.     {
  239.     case WM_CREATE:
  240.         AppendMenu(hParamMenu = CreatePopupMenu(), MF_ENABLED | MF_STRING, IDM_CLASSIC, "Классические");
  241.         AppendMenu(hParamMenu, MF_ENABLED | MF_STRING, IDM_NCLASSIC, "5 в ряд");
  242.         AppendMenu(hParamMenu, MF_SEPARATOR, IDM_NCLASSIC, NULL);
  243.         AppendMenu(hParamMenu, MF_ENABLED | MF_STRING, IDM_MULTIPLAY, "Игрок против игрока");
  244.         AppendMenu(hParamMenu, MF_ENABLED | MF_STRING, IDM_SINGLEPLAY, "Игрок против компьютера");
  245.         AppendMenu(hFileMenu = CreatePopupMenu(), MF_ENABLED | MF_STRING, IDM_NEWGAME, "Новая игра");
  246.         AppendMenu(hFileMenu, MF_ENABLED | MF_POPUP, (UINT)hParamMenu, "Параметры");
  247.         AppendMenu(hFileMenu, MF_ENABLED | MF_STRING, IDM_EXIT, "Выход");
  248.         AppendMenu(hMenu = CreateMenu(), MF_ENABLED | MF_POPUP, (UINT)hFileMenu, "Игра");
  249.         AppendMenu(hInfoMenu = CreatePopupMenu(), MF_ENABLED | MF_STRING, IDM_ABOUT, "О программе");
  250.         AppendMenu(hMenu, MF_ENABLED | MF_POPUP, (UINT)hInfoMenu, "Справка");
  251.         SetMenu(hWnd, hMenu);
  252.         CheckMenuRadioItem(hMenu, IDM_CLASSIC, IDM_NCLASSIC, IDM_CLASSIC, MF_CHECKED);
  253.         CheckMenuRadioItem(hMenu, IDM_MULTIPLAY, IDM_SINGLEPLAY, IDM_SINGLEPLAY, MF_CHECKED);
  254.         iSize = 3;
  255.         turn = 0;
  256.         players = 1;
  257.         break;
  258.     case WM_COMMAND:
  259.         wmId = LOWORD(wParam);
  260.         switch (wmId)
  261.         {
  262.         case IDM_ABOUT:
  263.             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);
  264.             break;
  265.         case IDM_CLASSIC:
  266.             if (iSize != 3) {
  267.                 iSize = 3;
  268.                 CheckMenuRadioItem(hMenu, IDM_CLASSIC, IDM_NCLASSIC, IDM_CLASSIC, MF_CHECKED);
  269.                 NewGame(hWnd, map, iSize, turn);
  270.             }
  271.             break;
  272.         case IDM_NCLASSIC:
  273.             temp = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SIZE), hWnd, DlgProc, (LPARAM)iSize);
  274.             if (temp) {
  275.                 iSize = temp;
  276.                 CheckMenuRadioItem(hMenu, IDM_CLASSIC, IDM_NCLASSIC, IDM_NCLASSIC, MF_CHECKED);
  277.                 NewGame(hWnd, map, iSize, turn);
  278.             }
  279.         case IDM_NEWGAME:
  280.             NewGame(hWnd, map, iSize, turn);
  281.             break;
  282.         case IDM_SINGLEPLAY:
  283.             if (players != 1) {
  284.                 players = 1;
  285.                 NewGame(hWnd, map, iSize, turn);
  286.                 CheckMenuRadioItem(hMenu, IDM_MULTIPLAY, IDM_SINGLEPLAY, IDM_SINGLEPLAY, MF_CHECKED);
  287.             }
  288.             break;
  289.         case IDM_MULTIPLAY:
  290.             if (players != 2) {
  291.                 players = 2;
  292.                 NewGame(hWnd, map, iSize, turn);
  293.                 CheckMenuRadioItem(hMenu, IDM_MULTIPLAY, IDM_SINGLEPLAY, IDM_MULTIPLAY, MF_CHECKED);
  294.             }
  295.             break;
  296.         case IDM_EXIT:
  297.             PostQuitMessage(0);
  298.         }
  299.         break;
  300.     case WM_RBUTTONDOWN:
  301.     case WM_LBUTTONDOWN:
  302.         if (message == WM_LBUTTONDOWN) temp = 1;
  303.         else temp = 2;
  304.         if (turn != temp - 1) break;
  305.         if (turn == 1 && players != 2) break;
  306.         x = GET_X_LPARAM(lParam);
  307.         y = GET_Y_LPARAM(lParam);
  308.         x = x * iSize / rect.right;
  309.         y = y * iSize / rect.bottom;
  310.         if (map[y][x]) break;
  311.         map[y][x] = temp;
  312.         InvalidateRect(hWnd, NULL, false);
  313.         if (temp = GameOver(map, iSize)) {
  314.             EndGame(hWnd, temp, players);
  315.             NewGame(hWnd, map, iSize, turn);
  316.             break;
  317.         }
  318.         if (players != 1) turn ^= 1;
  319.         if (players == 1) {
  320.             GoAI(map, iSize);
  321.             InvalidateRect(hWnd, NULL, false);
  322.             if (temp = GameOver(map, iSize)) {
  323.                 EndGame(hWnd, temp, players);
  324.                 NewGame(hWnd, map, iSize, turn);
  325.                 break;
  326.             }
  327.         }
  328.         break;
  329.     case WM_PAINT:
  330.         hdc = BeginPaint(hWnd, &ps);
  331.         SelectPen(hdc, GetStockPen(BLACK_PEN));
  332.         for (int i = 0; i < iSize; ++i) {
  333.             MoveToEx(hdc, rect.right * (i + 1) / iSize, 0, NULL);
  334.             LineTo(hdc, rect.right * (i + 1) / iSize, rect.bottom);
  335.             MoveToEx(hdc, 0, rect.bottom * (i + 1) / iSize, NULL);
  336.             LineTo(hdc, rect.right, rect.bottom * (i + 1) / iSize);
  337.         }
  338.         for (int i = 0; i < iSize; ++i)
  339.             for (int j = 0; j < iSize; ++j)
  340.                 if (map[i][j]) {
  341.                     if (map[i][j] == 1) {
  342.                         SelectPen(hdc, hpRed);
  343.                         MoveToEx(hdc, rect.right * j / iSize, rect.bottom * i / iSize, NULL);
  344.                         LineTo(hdc, rect.right * (j + 1) / iSize, rect.bottom * (i + 1) / iSize);
  345.                         MoveToEx(hdc, rect.right * j / iSize, rect.bottom * (i + 1) / iSize, NULL);
  346.                         LineTo(hdc, rect.right * (j + 1) / iSize, rect.bottom * i / iSize);
  347.                     } else {
  348.                         SelectPen(hdc, hpBlue);
  349.                         Ellipse(hdc, rect.right * j / iSize, rect.bottom * i / iSize,
  350.                             rect.right * (j + 1) / iSize, rect.bottom * (i + 1) / iSize);
  351.                     }
  352.                 }
  353.         EndPaint(hWnd, &ps);
  354.         break;
  355.     case WM_DESTROY:
  356.         PostQuitMessage(0);
  357.         break;
  358.     default:
  359.         return DefWindowProc(hWnd, message, wParam, lParam);
  360.     }
  361.     return 0;
  362. }
  363.  
  364. INT_PTR CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  365. {
  366.     switch (message)
  367.     {
  368.     case WM_CLOSE:
  369.         EndDialog(hDlg, 0);
  370.         break;
  371.     }
  372.     return (INT_PTR)FALSE;
  373. }
  374.  
  375. INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  376. {
  377.     static int x;
  378.     switch (message)
  379.     {
  380.     case WM_INITDIALOG:
  381.         SetDlgItemInt(hDlg, IDC_EDIT1, (UINT)lParam > 4 ? (UINT)lParam : 5, false);
  382.         SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  383.         break;
  384.     case WM_COMMAND:
  385.         switch(LOWORD(wParam))
  386.         {
  387.         case IDCANCEL:
  388.             EndDialog(hDlg, 0);
  389.             break;
  390.         case ID_OK:
  391.             x = GetDlgItemInt(hDlg, IDC_EDIT1, NULL, false);
  392.             if (x > 4 && x <= 40) EndDialog(hDlg, x);
  393.             break;
  394.         }
  395.         break;
  396.     case WM_CLOSE:
  397.         EndDialog(hDlg, 0);
  398.         break;
  399.     }
  400.     return (INT_PTR)FALSE;
  401. }
Advertisement
Add Comment
Please, Sign In to add comment