본문 바로가기
::public/윈도우즈 응용 프로그래밍

오목 만들기(결과로직 없음)

by 해맑은욱 2019. 9. 24.
// 오목 만들기.
 
#include "stdafx.h"
#include "MyWindowsProject.h"
 
// 가로 세로 줄이 19개인 바둑판
#define        X_COUNT            19            
#define        Y_COUNT            19
// 화면에서 바둑판의 거리
#define        START_X            50
#define        START_Y            50
// 줄 사이의 간격. 바둑 돌 크기
#define        INTERVAL        26
// 바둑 돌의 반지름(줄 간격의 반)
#define        HALF_INTERVAL    INTERVAL / 2
// 바둑판에 돌이 놓일 수 있는 위치 계산
#define        XPOS(x)            (START_X + (x) * INTERVAL)
#define        YPOS(y)            (START_Y + (y) * INTERVAL)
 
// 바둑판에 돌이 놓여져 있는 판단하기 위한 변수 배열(0=없음,1=검은색,2=흰색)
unsigned char g_dol[Y_COUNT][X_COUNT];
// 바둑판에 놓일 돌의 색을 결정하는 변수.(0=검은색,1=흰색)
unsigned char g_step;
 
void OnPaint(HWND hWnd)
{
    PAINTSTRUCT ps;
    HDC h_dc = BeginPaint(hWnd, &ps);
 
    // 수직으로 선 그리기
    for (int x = 0; x < X_COUNT; x++)
    {
        // (x, 0)에서 (x, Y_COUNT - 1) 연결하는 선.
        MoveToEx(h_dc, XPOS(x), YPOS(0), NULL);
        LineTo(h_dc, XPOS(x), YPOS(Y_COUNT - 1));
    }
    // 수평으로 선 그리기
    for (int y = 0; y < Y_COUNT; y++)
    {
        // (0, y)에서 (X_COUNT - 1, y) 연결하는 선.
        MoveToEx(h_dc, XPOS(0), YPOS(y), NULL);
        LineTo(h_dc, XPOS(X_COUNT - 1), YPOS(y));
    }
 
    // 바둑판에 놓여진 돌을 각 위치별로 체크하여 그림.
    for (int y = 0; y < Y_COUNT; y++)
    {
        for (int x = 0; x < X_COUNT; x++)
        {
            if (g_dol[y][x] > 0// 바둑이 놓여져 있음(1=검은돌,2=흰돌)
            {
                if (g_dol[y][x] == 1)
                    SelectObject(h_dc, GetStockObject(BLACK_BRUSH));
                else
                    SelectObject(h_dc, GetStockObject(WHITE_BRUSH));
 
                // 바둑돌이 놓여질 위치 계산. 반지름이 HALF_INTERVAL인 원을 그림.
                Ellipse(h_dc, XPOS(x) - HALF_INTERVAL, YPOS(y) - HALF_INTERVAL, XPOS(x) + HALF_INTERVAL, YPOS(y) + HALF_INTERVAL);
            }
        }
    }
 
    EndPaint(hWnd, &ps);
}
 
void OnLButtonDown(HWND hWnd, int a_x, int a_y)
{
    // 바둑판 영역에만 돌을 놓을 수 있도록 터치한 위치 체크.
    if (a_x > (XPOS(0- HALF_INTERVAL) && a_y > (YPOS(0- HALF_INTERVAL)
        && a_x < (XPOS(X_COUNT - 1+ HALF_INTERVAL)
        && a_y < (YPOS(Y_COUNT - 1+ HALF_INTERVAL))
    {
        // 터치한 위치와 가까운 줄쪽으로 놓임.
        int x = (a_x - START_X + HALF_INTERVAL) / INTERVAL;
        int y = (a_y - START_Y + HALF_INTERVAL) / INTERVAL;
        // 돌이 없는 곳에만 놓을 수 있음.
        if (g_dol[y][x] == 0)
        {
            // g_step + 1하면 g_dol에 놓일 색상이 됨. g_step 0=검|1=흰 == g_dol 1=검|2=흰.
            g_dol[y][x] = g_step + 1;
            // 놓일 돌의 색상을 변경.
            g_step = !g_step;
            // 화면을 갱신해서 적용.
            InvalidateRect(hWnd, NULL, TRUE);
        }
    }
}
 
// 사용자가 메시지를 처리하는 함수.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//     HDC h_screen_dc = ::GetDC(NULL);    // 모니터 전체 화면용 DC
//     HDC h_dc = ::GetDC(hWnd);    // 현재 윈도우용 DC
//     int check = 0;
    switch (message)
    {
    case WM_PAINT:
        OnPaint(hWnd);
        break;
    case WM_LBUTTONDOWN:
        OnLButtonDown(hWnd, LOWORD(lParam), HIWORD(lParam));
        break;
    case WM_DESTROY:
        // 프로그램 종료
        PostQuitMessage(0);
        break;
    default:
        // 자신이 처리하지 않는 메시지들의 기본 작업을 대신 처리해주는 함수.
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
 
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,            // 프로그램의 instance 핸들 값.
                     _In_opt_ HINSTANCE hPrevInstance,    // 현재 사용안함. 항상 NULL.
                     _In_ LPWSTR    lpCmdLine,            // 하나의 문자열로 실행인자가 전달됨.
                     _In_ int       nCmdShow)            // 초기 기작 형식이 전달됨.
{
    // 윈도우 클래스 등록
    WNDCLASSEXW 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, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(24417677));    // 바둑판 컬러 설정
    wcex.lpszMenuName = IDI_APPLICATION;
    wcex.lpszClassName = L"MyWindow";
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    RegisterClassExW(&wcex);
 
    // 윈도우 생성
    HWND hWnd = CreateWindowW(L"MyWindow", L"scriptplay.tistory.com", WS_OVERLAPPEDWINDOW,
        5050600600, nullptr, nullptr, hInstance, nullptr);
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
 
    // 프로그램에 전달된 메시지를 번역하고 실행하는 작업.
    MSG msg;
    while (GetMessage(&msg, nullptr, 00))    // 메시지를 큐에서 읽는 함수.
    {
        TranslateMessage(&msg);                // 가상 키 메시지이면 ASCII 형태의 메시지를 추가로 생성.
        DispatchMessage(&msg);                // 변환된 메시지를 처리하는 함수.
    }
 
    return (int) msg.wParam;
}
 
cs

'::public > 윈도우즈 응용 프로그래밍' 카테고리의 다른 글

Direct2D  (0) 2019.09.25
Timer  (0) 2019.09.24
MessageBox  (0) 2019.09.24
Bitmap 복사  (0) 2019.09.24
WinProc(윈드 프록)  (0) 2019.09.23