// OthelloDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Othello.h"
#include "OthelloDlg.h"
#include "RankDlg.h"
#include "NameDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
//말의 상태를 나타냄
#define HUMAN 0
#define COMPUTER 5
#define EMPTY 10 // 아무것도 없는 경우
#define OFFBOARD 11 // 말판 경계선
#define ACTIVATE 12 // 변해야 하는 경우
#define CHANGESTONESPEED 200
#define MOVESTONE 0
#define MESSAGE 1
//Timer ID
#define SHOWTYPE 0
#define CHANGESTONE 1
#define CENTER 318
static int GY[] = {156, 179, 204, 232, 264, 300, 341, 389, 435};
static int GX[] = {38, 40, 43, 46, 49, 52, 56, 61};
static int PY[] = {31, 33, 35, 39, 41, 50, 53, 52};
static int PX[] = {39, 41, 43, 45, 47, 51, 55, 57};
BOOL m_bSound;
static void PlaySound(LPCTSTR lpszSound)
{
if(m_bSound)
{
HRSRC hRes; // resource handle to wave file
HGLOBAL hData;
BOOL bOk = FALSE;
if ((hRes = ::FindResource(AfxGetResourceHandle(), lpszSound,
_T("WAVE"))) != NULL &&
(hData = ::LoadResource(AfxGetResourceHandle(), hRes)) != NULL)
{
// found the resource, play it
bOk = sndPlaySound((LPCTSTR)::LockResource(hData),
SND_MEMORY|SND_ASYNC|SND_NODEFAULT);
FreeResource(hData);
}
}
}
inline static void PlaySound(UINT nIDS)
{ PlaySound(MAKEINTRESOURCE(nIDS)); }
/////////////////////////////////////////////////////////////////////////////
// COthelloDlg dialog
COthelloDlg::COthelloDlg(CWnd* pParent /*=NULL*/)
: CDialog(COthelloDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(COthelloDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_nCurType = HUMAN;
m_nAnim = 0;
m_nIncrease = 1;
}
void COthelloDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COthelloDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COthelloDlg, CDialog)
//{{AFX_MSG_MAP(COthelloDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_WM_TIMER()
ON_WM_LBUTTONDOWN()
ON_COMMAND(ID_NEWGAME, OnNewgame)
ON_COMMAND(IDM_RANK, OnRank)
ON_COMMAND(IDM_SOUND, OnSound)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COthelloDlg member function
void COthelloDlg::DrawBackground()
{
CClientDC dc(this);
CDC MemDC;
CBitmap *pOldBitmap;
MemDC.CreateCompatibleDC(&dc);
pOldBitmap = (CBitmap *)MemDC.SelectObject(&m_bmpBack);
dc.BitBlt(0, 0, 634, 436, &MemDC, 0, 0, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
}
void COthelloDlg::DrawObject(int y, int x)
{
if(y>1)
RealDrawObject(y-1, x);
else
{
CClientDC dc(this);
CDC MemDC;
CBitmap *pOldBitmap;
MemDC.CreateCompatibleDC(&dc);
pOldBitmap = (CBitmap *)MemDC.SelectObject(&m_bmpBack);
dc.BitBlt(170, 140, 295, 15, &MemDC, 170, 140, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
}
RealDrawObject(y, x);
}
void COthelloDlg::ShowCurType()
{
CClientDC dc(this);
CDC MemDC;
CBitmap *pOldBitmap;
MemDC.CreateCompatibleDC(&dc);
if(m_nCurType == HUMAN)
{
pOldBitmap = (CBitmap *)MemDC.SelectObject(&m_bmpRed);
dc.BitBlt(220, 75, 55, 55, &MemDC, 55*m_nAnim, 0, SRCCOPY);
}
else
{
pOldBitmap = (CBitmap *)MemDC.SelectObject(&m_bmpGreen);
dc.BitBlt(358, 75, 55, 55, &MemDC, 55*m_nAnim, 0, SRCCOPY);
}
MemDC.SelectObject(pOldBitmap);
m_nAnim+=m_nIncrease;
if(m_nAnim > 7) //m_nIncrease = -1;
m_nAnim = 0;
else if(m_nAnim <= 0) m_nIncrease = 1;
}
void COthelloDlg::RealDrawObject(int y, int x)
{
CClientDC dc(this);
CDC MemDC, MemDCTemp;
CBitmap *pOB1, *pOB2, MemBmp;
MemDC.CreateCompatibleDC(&dc);
MemDCTemp.CreateCompatibleDC(&dc);
MemBmp.CreateCompatibleBitmap(&dc, PX[y-1], PY[y-1]);
int nDrawX = CENTER + (x-5)*GX[y-1] + GX[y-1]/2 - PX[y-1]/2;
int nDrawY = (GY[y-1]+GY[y])/2 - PY[y-1]/2 - 6;
pOB1 = (CBitmap *)MemDCTemp.SelectObject(&m_bmpBack);
pOB2 = (CBitmap *)MemDC.SelectObject(&MemBmp);
//copy background
//MemDC.BitBlt(0, 0, PX[y-1], PY[y-1], &MemDCTemp, nDrawX, nDrawY, SRCCOPY);
MemDC.BitBlt(0, 0, PX[y-1], 6, &dc, nDrawX, nDrawY, SRCCOPY);
MemDC.BitBlt(0, 6, PX[y-1], PY[y-1], &MemDCTemp, nDrawX, nDrawY+6, SRCCOPY);
int nType = m_nGame[y][x];
if(nType == ACTIVATE) nType = m_nCurType;
if(nType != OFFBOARD && nType != EMPTY)
{
//draw mask
MemDCTemp.SelectObject(&m_bmpM[y-1]);
MemDC.BitBlt(0, 0, PX[y-1], PY[y-1], &MemDCTemp, PX[y-1]*nType, 0, SRCPAINT);
//draw chip
MemDCTemp.SelectObject(&m_bmpP[y-1]);
MemDC.BitBlt(0, 0, PX[y-1], PY[y-1], &MemDCTemp, PX[y-1]*nType, 0, SRCAND);
}
dc.BitBlt(nDrawX, nDrawY, PX[y-1], PY[y-1], &MemDC, 0, 0, SRCCOPY);
MemDCTemp.SelectObject(pOB1);
MemDC.SelectObject(pOB2);
}
void COthelloDlg::Score()
{
int nHuman=0, nComputer=0;
int x, y;
for(y=1 ; y<9 ; y++)
for(x=1 ; x<9 ; x++)
{
if(m_nGame[y][x] == HUMAN) nHuman++;
else if(m_nGame[y][x] == COMPUTER) nComputer++;
}
CClientDC dc(this);
CDC MemDC;
CBitmap *pOldBitmap;
MemDC.CreateCompatibleDC(&dc);
pOldBitmap = (CBitmap *)MemDC.SelectObject(&m_bmpScore);
dc.BitBlt(279, 92, 12, 18, &MemDC, (nHuman/10)*12, 0, SRCCOPY);
dc.BitBlt(291, 92, 12, 18, &MemDC, (nHuman%10)*12, 0, SRCCOPY);
dc.BitBlt(324, 92, 12, 18, &MemDC, (nComputer/10)*12, 0, SRCCOPY);
dc.BitBlt(336, 92, 12, 18, &MemDC, (nComputer%10)*12, 0, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
}
BOOL COthelloDlg::CheckForfeit(int nType)
{
int x, y;
for(y=1 ; y<9 ; y++)
for(x=1 ; x<9 ; x++)
{
if(LegalMove(y, x, nType, FALSE))
return FALSE;
}
return TRUE;
}
BOOL COthelloDlg::CheckGameOver()
{
if(CheckForfeit(HUMAN) && CheckForfeit(COMPUTER)) return TRUE;
return FALSE;
}
void COthelloDlg::InitGame()
{
KillTimer(SHOWTYPE);
KillTimer(CHANGESTONE);
MSG msg;
while(::PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));
int i, j;
for(i=0 ; i<10 ; i++)
{
m_nGame[i][0] = OFFBOARD;
m_nGame[i][9] = OFFBOARD;
m_nGame[0][i] = OFFBOARD;
m_nGame[9][i] = OFFBOARD;
}
for(i=1 ; i<9 ; i++)
for(j=1 ; j<9 ; j++)
{
m_nGame[i][j] = EMPTY;
}
m_nGame[4][4] = m_nCurType;
m_nGame[5][5] = m_nCurType;
m_nGame[4][5] = GetOtherType(m_nCurType);
m_nGame[5][4] = GetOtherType(m_nCurType);
SetTimer(SHOWTYPE, 300, NULL);
}
BOOL COthelloDlg::LegalMove(int y, int x, int nType, BOOL bFlip)
{
int i, j;
BOOL bLegal = FALSE;
int nStepCount;
int nOtherType = GetOtherType(nType);
int nNext = GetNext(nType);
if(m_nGame[y][x] != EMPTY) return FALSE;
// 여덟 방향 주위를 살펴봄
for(int xdir=-1 ; xdir<2 ; xdir++)
for(int ydir=-1 ; ydir<2 ; ydir++)
{
nStepCount = 0;
// 양쪽으로 포위할 수 있는 상대방 말이 있는지 봄
do
{
nStepCount++;
i = x+nStepCount*xdir;
j = y+nStepCount*ydir;
} while ( i>0 && i<9 && j>0 && j<9 && m_nGame[j][i] == nOtherType);
if(i>0 && i<9 && j>0 && j<9 && nStepCount>1 && m_nGame[j][i]==nType)
{
bLegal = TRUE;
if(bFlip)
{
// 말 바꾸기
for(int k=1 ; k<nStepCount ; k++)
m_nGame[y+ydir*k][x+xdir*k] = ACTIVATE;
SetTimer(CHANGESTONE, CHANGESTONESPEED, NULL);
}
}
}
return bLegal;
}
void COthelloDlg::Forfeit()
{
MSG msg;
while(::PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));
if(m_nCurType == HUMAN)
AfxMessageBox("당신이 말을 놓을 자리가 하나도 없습니다.\n상대방에게 기회가 넘어갑니다.");
else
AfxMessageBox("상대방이 말을 놓을 자리가 하나도 없습니다.\n당신에게게 기회가 넘어갑니다.");
m_nCurType