Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- #include "UP_LAB5.h"
- #include <windowsx.h>
- #include <cmath>
- #define MAX_LOADSTRING 100
- #define IDM_CLASSIC 0
- #define IDM_EXIT 1
- #define IDM_NEWGAME 2
- #define IDM_NCLASSIC 3
- #define IDM_MULTIPLAY 4
- #define IDM_SINGLEPLAY 5
- #define IDM_ABOUT 6
- HINSTANCE hInst;
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
- INT_PTR CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM);
- INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
- int APIENTRY _tWinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine,
- int nCmdShow)
- {
- static TCHAR szWindowClass[] = "Prog";
- MSG msg;
- HWND hWnd;
- WNDCLASSEX wcex;
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance,NULL);
- wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wcex.lpszMenuName = NULL;
- wcex.lpszClassName = szWindowClass;
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
- RegisterClassEx(&wcex);
- hWnd = CreateWindow(szWindowClass, "Крестики-Нолики", WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, 500, 500, NULL, NULL, hInstance, NULL);
- hInst = hInstance;
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return (int) msg.wParam;
- }
- bool isNear(int x, int y, int map[111][111], int n) {
- if (map[x][y]) return 0;
- const int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0}, dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
- for (int t = 0; t < 8; ++t)
- if (x + dx[t] < n && y + dy[t] < n && x + dx[t] >= 0 && y + dy[t] >= 0 && map[x + dx[t]][y + dy[t]])
- return true;
- return false;
- }
- double Calc(int x, int y, int map[111][111], int n, int w) {
- double res = 0;
- int t1 = 5, t2;
- if (n == 3) t1 = 3;
- t2 = t1 - 1;
- for (int j = y - t2; j <= y; ++j) {
- if (j < 0 || j + t2 >= n) continue;
- int c = 1;
- for (int t = 0; t < t1; ++t) {
- if (!map[x][j + t]) continue;
- if (map[x][j + t] != w) {
- c = 0;
- break;
- } else ++c;
- }
- if (c == 1) c = 0;
- if (c) res += pow(3.0, c + .0);
- if (c == t1)
- if (w == 2) res += 100000;
- else res += 1000;
- }
- for (int i = x - t2; i <= x; ++i) {
- if (i < 0 || i + t2 >= n) continue;
- int c = 1;
- for (int t = 0; t < t1; ++t) {
- if (!map[i + t][y]) continue;
- if (map[i + t][y] != w) {
- c = 0;
- break;
- } else ++c;
- }
- if (c == 1) c = 0;
- if (c) res += pow(3.0, c + .0);
- if (c == t1)
- if (w == 2) res += 100000;
- else res += 1000;
- }
- for (int i = x - t2, j = y - t2; i <= x; ++i, ++j) {
- if (i < 0 || j < 0 || i + t2 >= n || j + t2 >= n) continue;
- int c = 1;
- for (int t = 0; t < t1; ++t) {
- if (!map[i + t][j + t]) continue;
- if (map[i + t][j + t] != w) {
- c = 0;
- break;
- } else ++c;
- }
- if (c == 1) c = 0;
- if (c) res += pow(3.0, c + .0);
- if (c == t1)
- if (w == 2) res += 100000;
- else res += 1000;
- }
- for (int i = x + t2, j = y - t2; i >= x; --i, ++j) {
- if (i >= n || j < 0 || i - t2 < 0 || j + t2 >= n) continue;
- int c = 1;
- for (int t = 0; t < t1; ++t) {
- if (!map[i - t][j + t]) continue;
- if (map[i - t][j + t] != w) {
- c = 0;
- break;
- } else ++c;
- }
- if (c == 1) c = 0;
- if (c) res += pow(3.0, c + .0);
- if (c == t1)
- if (w == 2) res += 100000;
- else res += 1000;
- }
- return res;
- }
- bool check(int map[111][111]) {
- int c = 0;
- for (int i = 0; i < 3; ++i)
- for (int j = 0; j < 3; ++j)
- if (map[i][j] == 1) ++c;
- if (c > 2) return false;
- if (c == 1) {
- if (!map[1][1]) map[1][1] = 2;
- else map[0][0] = 2;
- return true;
- }
- if (c == 2)
- if (map[0][0] == 1 && map[2][2] == 1 || map[0][2] == 1 && map[2][0] == 1) {
- map[0][1] = 2;
- return true;
- }
- return false;
- }
- void GoAI(int map[111][111], int n) {
- if (n == 3 && check(map)) return;
- const double aggr = 0.8;
- int x = -1, y = -1;
- double best = -1.0;
- for (int i = 0; i < n; ++i)
- for (int j = 0; j < n; ++j) {
- if (!isNear(i, j, map, n)) continue;
- double g = Calc(i, j, map, n, 2) + aggr * Calc(i, j, map, n, 1);
- if (g > best) {
- best = g;
- x = i;
- y = j;
- }
- }
- map[x][y] = 2;
- }
- void NewGame(HWND hWnd, int map[111][111], int n, int & turn) {
- turn = 0;
- for (int i = 0; i < n; ++i)
- for (int j = 0; j < n; ++j) map[i][j] = 0;
- InvalidateRect(hWnd, NULL, true);
- }
- int GameOver(int map[111][111], int n) {
- bool draw = 1;
- int lim = 5;
- if (n == 3) lim = 3;
- for (int i = 0; i < n; ++i)
- for (int j = 0; j < n; ++j) {
- if (!map[i][j]) {
- draw = 0;
- continue;
- }
- for (int t = 1; t < lim; ++t) {
- if (i + t == n) break;
- if (map[i][j] != map[i + t][j]) break;
- if (t == lim - 1) return map[i][j];
- }
- for (int t = 1; t < lim; ++t) {
- if (j + t == n) break;
- if (map[i][j] != map[i][j + t]) break;
- if (t == lim - 1) return map[i][j];
- }
- for (int t = 1; t < lim; ++t) {
- if (j + t == n || i - t == -1) break;
- if (map[i][j] != map[i - t][j + t]) break;
- if (t == lim - 1) return map[i][j];
- }
- for (int t = 1; t < lim; ++t) {
- if (j + t == n || i + t == n) break;
- if (map[i][j] != map[i + t][j + t]) break;
- if (t == lim - 1) return map[i][j];
- }
- }
- if (draw) return 3;
- return 0;
- }
- void EndGame(HWND hWnd, int player, int players) {
- if (player == 3) MessageBox(hWnd, "Ничья", "Конец игры", MB_OK | MB_ICONINFORMATION);
- if (player == 1) MessageBox(hWnd, "Победил первый игрок", "Конец игры", MB_OK | MB_ICONINFORMATION);
- if (player == 2 && players == 2) MessageBox(hWnd, "Победил второй игрок", "Конец игры", MB_OK | MB_ICONINFORMATION);
- if (player == 2 && players == 1) MessageBox(hWnd, "Победил компьютер", "Конец игры", MB_OK | MB_ICONINFORMATION);
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- int wmId;
- PAINTSTRUCT ps;
- HDC hdc;
- static HMENU hMenu, hFileMenu, hInfoMenu, hParamMenu;
- static int iSize, map[111][111], turn, x, y, players, temp;
- static RECT rect;
- static const HPEN hpRed = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)),
- hpBlue = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
- GetClientRect(hWnd, &rect);
- switch (message)
- {
- case WM_CREATE:
- AppendMenu(hParamMenu = CreatePopupMenu(), MF_ENABLED | MF_STRING, IDM_CLASSIC, "Классические");
- AppendMenu(hParamMenu, MF_ENABLED | MF_STRING, IDM_NCLASSIC, "5 в ряд");
- AppendMenu(hParamMenu, MF_SEPARATOR, IDM_NCLASSIC, NULL);
- AppendMenu(hParamMenu, MF_ENABLED | MF_STRING, IDM_MULTIPLAY, "Игрок против игрока");
- AppendMenu(hParamMenu, MF_ENABLED | MF_STRING, IDM_SINGLEPLAY, "Игрок против компьютера");
- AppendMenu(hFileMenu = CreatePopupMenu(), MF_ENABLED | MF_STRING, IDM_NEWGAME, "Новая игра");
- AppendMenu(hFileMenu, MF_ENABLED | MF_POPUP, (UINT)hParamMenu, "Параметры");
- AppendMenu(hFileMenu, MF_ENABLED | MF_STRING, IDM_EXIT, "Выход");
- AppendMenu(hMenu = CreateMenu(), MF_ENABLED | MF_POPUP, (UINT)hFileMenu, "Игра");
- AppendMenu(hInfoMenu = CreatePopupMenu(), MF_ENABLED | MF_STRING, IDM_ABOUT, "О программе");
- AppendMenu(hMenu, MF_ENABLED | MF_POPUP, (UINT)hInfoMenu, "Справка");
- SetMenu(hWnd, hMenu);
- CheckMenuRadioItem(hMenu, IDM_CLASSIC, IDM_NCLASSIC, IDM_CLASSIC, MF_CHECKED);
- CheckMenuRadioItem(hMenu, IDM_MULTIPLAY, IDM_SINGLEPLAY, IDM_SINGLEPLAY, MF_CHECKED);
- iSize = 3;
- turn = 0;
- players = 1;
- break;
- case WM_COMMAND:
- wmId = LOWORD(wParam);
- switch (wmId)
- {
- case IDM_ABOUT:
- DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);
- break;
- case IDM_CLASSIC:
- if (iSize != 3) {
- iSize = 3;
- CheckMenuRadioItem(hMenu, IDM_CLASSIC, IDM_NCLASSIC, IDM_CLASSIC, MF_CHECKED);
- NewGame(hWnd, map, iSize, turn);
- }
- break;
- case IDM_NCLASSIC:
- temp = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SIZE), hWnd, DlgProc, (LPARAM)iSize);
- if (temp) {
- iSize = temp;
- CheckMenuRadioItem(hMenu, IDM_CLASSIC, IDM_NCLASSIC, IDM_NCLASSIC, MF_CHECKED);
- NewGame(hWnd, map, iSize, turn);
- }
- case IDM_NEWGAME:
- NewGame(hWnd, map, iSize, turn);
- break;
- case IDM_SINGLEPLAY:
- if (players != 1) {
- players = 1;
- NewGame(hWnd, map, iSize, turn);
- CheckMenuRadioItem(hMenu, IDM_MULTIPLAY, IDM_SINGLEPLAY, IDM_SINGLEPLAY, MF_CHECKED);
- }
- break;
- case IDM_MULTIPLAY:
- if (players != 2) {
- players = 2;
- NewGame(hWnd, map, iSize, turn);
- CheckMenuRadioItem(hMenu, IDM_MULTIPLAY, IDM_SINGLEPLAY, IDM_MULTIPLAY, MF_CHECKED);
- }
- break;
- case IDM_EXIT:
- PostQuitMessage(0);
- }
- break;
- case WM_RBUTTONDOWN:
- case WM_LBUTTONDOWN:
- if (message == WM_LBUTTONDOWN) temp = 1;
- else temp = 2;
- if (turn != temp - 1) break;
- if (turn == 1 && players != 2) break;
- x = GET_X_LPARAM(lParam);
- y = GET_Y_LPARAM(lParam);
- x = x * iSize / rect.right;
- y = y * iSize / rect.bottom;
- if (map[y][x]) break;
- map[y][x] = temp;
- InvalidateRect(hWnd, NULL, false);
- if (temp = GameOver(map, iSize)) {
- EndGame(hWnd, temp, players);
- NewGame(hWnd, map, iSize, turn);
- break;
- }
- if (players != 1) turn ^= 1;
- if (players == 1) {
- GoAI(map, iSize);
- InvalidateRect(hWnd, NULL, false);
- if (temp = GameOver(map, iSize)) {
- EndGame(hWnd, temp, players);
- NewGame(hWnd, map, iSize, turn);
- break;
- }
- }
- break;
- case WM_PAINT:
- hdc = BeginPaint(hWnd, &ps);
- SelectPen(hdc, GetStockPen(BLACK_PEN));
- for (int i = 0; i < iSize; ++i) {
- MoveToEx(hdc, rect.right * (i + 1) / iSize, 0, NULL);
- LineTo(hdc, rect.right * (i + 1) / iSize, rect.bottom);
- MoveToEx(hdc, 0, rect.bottom * (i + 1) / iSize, NULL);
- LineTo(hdc, rect.right, rect.bottom * (i + 1) / iSize);
- }
- for (int i = 0; i < iSize; ++i)
- for (int j = 0; j < iSize; ++j)
- if (map[i][j]) {
- if (map[i][j] == 1) {
- SelectPen(hdc, hpRed);
- MoveToEx(hdc, rect.right * j / iSize, rect.bottom * i / iSize, NULL);
- LineTo(hdc, rect.right * (j + 1) / iSize, rect.bottom * (i + 1) / iSize);
- MoveToEx(hdc, rect.right * j / iSize, rect.bottom * (i + 1) / iSize, NULL);
- LineTo(hdc, rect.right * (j + 1) / iSize, rect.bottom * i / iSize);
- } else {
- SelectPen(hdc, hpBlue);
- Ellipse(hdc, rect.right * j / iSize, rect.bottom * i / iSize,
- rect.right * (j + 1) / iSize, rect.bottom * (i + 1) / iSize);
- }
- }
- EndPaint(hWnd, &ps);
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
- }
- INT_PTR CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch (message)
- {
- case WM_CLOSE:
- EndDialog(hDlg, 0);
- break;
- }
- return (INT_PTR)FALSE;
- }
- INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static int x;
- switch (message)
- {
- case WM_INITDIALOG:
- SetDlgItemInt(hDlg, IDC_EDIT1, (UINT)lParam > 4 ? (UINT)lParam : 5, false);
- SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
- break;
- case WM_COMMAND:
- switch(LOWORD(wParam))
- {
- case IDCANCEL:
- EndDialog(hDlg, 0);
- break;
- case ID_OK:
- x = GetDlgItemInt(hDlg, IDC_EDIT1, NULL, false);
- if (x > 4 && x <= 40) EndDialog(hDlg, x);
- break;
- }
- break;
- case WM_CLOSE:
- EndDialog(hDlg, 0);
- break;
- }
- return (INT_PTR)FALSE;
- }
Advertisement
Add Comment
Please, Sign In to add comment