読者です 読者をやめる 読者になる 読者になる

とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

Windows プログラミング入門 リバーシ

久しぶりに遊べるレベルのプログラミングをC++でしてみた。パスの無いオセロみたいなもの。
とはいえC++とは言いがたいベターC。C++ライブラリも自作クラスもなし。極力短く書くことを心がけた。132行 *1

#include<Windows.h>
#include<WindowsX.h>
#include<tchar.h>

int const board_size = 10;
enum player_tag{e, w, b};
player_tag board_data[][board_size] = {
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, w, b, e, e, e, e},
 {e, e, e, e, b, w, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
 {e, e, e, e, e, e, e, e, e, e},
};
player_tag& board(int x, int y){ return board_data[y][x]; }

bool get_piece(player_tag player, int x, int y, int (*x_next)(int), int (*y_next)(int))
{
 if(!board(x, y) || board(x, y) == player)return false;
 else
  if(!board(x_next(x), y_next(y)))return false;
  else if(board(x_next(x), y_next(y)) == player ||
   get_piece(player, x_next(x), y_next(y), x_next, y_next))
  {
   board(x, y) = player;
   return true;
  }
  else return false;
}

int minus1(int a) { return a - 1; }
int plus1(int a)  { return a + 1; }
int nothing(int a){ return a; }

bool put_piece(player_tag player, int x, int y)
{
 if(board(x, y))return false;
 bool put = false;
 if(get_piece(player, x - 1, y,     minus1,  nothing))put = true;
 if(get_piece(player, x + 1, y,     plus1,   nothing))put = true;
 if(get_piece(player, x,     y - 1, nothing, minus1 ))put = true;
 if(get_piece(player, x,     y + 1, nothing, plus1  ))put = true;
 if(get_piece(player, x - 1, y - 1, minus1,  minus1 ))put = true;
 if(get_piece(player, x + 1, y + 1, plus1,   plus1  ))put = true;
 if(get_piece(player, x + 1, y - 1, plus1,   minus1 ))put = true;
 if(get_piece(player, x - 1, y + 1, minus1,  plus1  ))put = true;
 if(put)
 {
  board(x, y) = player;
  return true;
 }
 return false;
}

LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
 switch(msg)
 {
 case WM_LBUTTONDOWN:
  {
   WORD const x_pos = GET_X_LPARAM(lparam);
   WORD const y_pos = GET_Y_LPARAM(lparam);
   RECT client;
   GetClientRect(hwnd, &client);
   int const x = x_pos / (client.right / board_size);
   int const y = y_pos / (client.bottom / board_size);
   static player_tag player = b;
   if(put_piece(player, x, y))
    player = player == w ? b : w;
   InvalidateRect(hwnd, NULL, FALSE);
  }
  return 0;
 case WM_PAINT:
  {
   PAINTSTRUCT ps;
   HDC const hdc = BeginPaint(hwnd, &ps);
   RECT client;
   GetClientRect(hwnd, &client);
   LONG const mass_width = client.right / board_size;
   LONG const mass_height = client.bottom / board_size;
   LONG const piece_margin_width = mass_width / board_size;
   LONG const piece_margin_height = mass_height / board_size;
   for(int y = 1; y <= board_size - 2; ++y)
    for(int x = 1; x <= board_size - 2; ++x)
    {
     Rectangle(hdc, mass_width * x, mass_height * y,
      mass_width * (x + 1), mass_height * (y + 1));
     if(board(x, y))
     {
      HBRUSH const brush = CreateSolidBrush(board(x, y) == 1 ?
       RGB(0xFF, 0xFF, 0xFF) : RGB(0, 0, 0));
      HGDIOBJ const prev = SelectObject(hdc, brush);
      Ellipse(hdc,
       mass_width * x + piece_margin_width,
       mass_height * y + piece_margin_height,
       mass_width * (x + 1) - piece_margin_width,
       mass_height * (y + 1) - piece_margin_height);
      SelectObject(hdc, prev);
      DeleteObject(brush);
     }
    }
   EndPaint(hwnd, &ps);
   return 0;
  }
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 default:
  return DefWindowProc(hwnd, msg, wparam, lparam);
 }
}

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE, LPSTR, int cmd_show)
{
 WNDCLASSEX const wc = {
  sizeof(wc), CS_HREDRAW | CS_VREDRAW, window_proc, 0, 0, hinstance, 0,
  LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1),
  NULL, _T("my_window_class"),  0
 };
 HWND const hwnd = CreateWindow(
  MAKEINTRESOURCE(RegisterClassEx(&wc)), _T("my_title"), WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hinstance, NULL);
 ShowWindow(hwnd, cmd_show);
 MSG msg = {};
 for(; GetMessage(&msg, hwnd, 0, 0) > 0; DispatchMessage(&msg))
  TranslateMessage(&msg);
 return static_cast<int>(msg.wParam);
}

*1:これを7行におさめるのは厳しいだろうなぁ…