📄 tttdoc.cpp
字号:
// tttdoc.cpp : implementation of the CTTTDoc class
//
#include "stdafx.h"
#include "ttt.h"
#include "tttdoc.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTTTDoc
IMPLEMENT_DYNCREATE(CTTTDoc, CDocument)
BEGIN_MESSAGE_MAP(CTTTDoc, CDocument)
//{{AFX_MSG_MAP(CTTTDoc)
ON_COMMAND(ID_OPTIONS_HUMANSTART, OnOptionsHumanstart)
ON_UPDATE_COMMAND_UI(ID_OPTIONS_HUMANSTART, OnUpdateOptionsHumanstart)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTTTDoc construction/destruction
CTTTDoc::CTTTDoc()
{
// TODO: add one-time construction code here
m_cWhoGoesFirst = 'X';
// this is not put in the OnNewDocument function since
// we may want to dynamically change it.
}
CTTTDoc::~CTTTDoc()
{
}
/////////////////////////////////////////////////////////////////////////////
// CTTTDoc Operations
void CTTTDoc::AnalyzeBoard()
{
int Sum, I, J;
int BestSum = 0;
int BestI, BestJ;
const int ImminentWin = 2;
const int ImminentLoss = -2; // for the computer, i.e. for 'O'
InitWinSumIterator();
while ( NextWinSum(Sum, I, J) )
{
switch (Sum)
{
case 3:
m_cGameStatus = 'O';
return;
case -3:
m_cGameStatus = 'X';
return;
// keep tract of the best sum coordinates for
// ImminentWin or ImminentLoss
case ImminentWin:
BestSum = Sum;
BestI = I;
BestJ = J;
break;
case ImminentLoss:
if ( BestSum != ImminentWin )
{
BestSum = Sum;
BestI = I;
BestJ = J;
}
break;
default:
break;
}
} // end while
// Save the imminent win/loss coordinates
if (abs(BestSum) == 2)
{
m_nBestI = BestI;
m_nBestJ = BestJ;
return;
}
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
// if there are blanks the game's still afoot
if (m_acBoard[i][j] == ' ')
{
m_nBestI = i;
m_nBestJ = j;
return;
}
// if there are no blanks and no wins it's a draw.
m_cGameStatus = 'C';
}
void CTTTDoc::InitWinSumIterator()
{
m_nIterator = 0;
}
BOOL CTTTDoc::NextWinSum(int &nSum, int &nBestI, int &nBestJ)
{
int i, j;
if (m_nIterator < 0)
return FALSE;
// Iterator was not initialized.
// hold the value of the original iterator
int nPosition = m_nIterator;
// increment the iterator for the next pass
m_nIterator++;
nSum = 0;
if (nPosition < BOARD_SIZE)
{
// calculate the appropriate horizontal win sum
for (j = 0; j < BOARD_SIZE; j++)
if (m_acBoard[nPosition][j] == 'X')
nSum--;
else if (m_acBoard[nPosition][j] == 'O')
nSum++;
else // m_acBoard[i][j] == ' '
{
nBestI = nPosition;
nBestJ = j;
}
return TRUE;
}
if (nPosition < 2*BOARD_SIZE )
{
// calculate the appropriate vertical win sum
// translate the iterator into array units
j = nPosition - BOARD_SIZE;
for (i = 0; i < BOARD_SIZE; i++)
if (m_acBoard[i][j] == 'X')
nSum--;
else if (m_acBoard[i][j] == 'O')
nSum++;
else // m_acBoard[i][j] == ' '
{
nBestI = i;
nBestJ = j;
}
return TRUE;
}
int nDiagonalWins = 2; // one for each diagonal
if (nPosition < 2*BOARD_SIZE + nDiagonalWins)
{
// calculate the appropriate diagonal win sum
// translate the iterator into diagonal iteration units
// n will take on values of 0 & 1
int n = nPosition - 2*BOARD_SIZE;
for (i = 0; i < BOARD_SIZE; i++)
{
j = n*(2-2*i) + i;
if (m_acBoard[i][j] == 'X')
nSum--;
else if (m_acBoard[i][j] == 'O')
nSum++;
else // m_acBoard[i][i] == ' '
{
nBestI = i;
nBestJ = j;
}
}
return TRUE;
}
return FALSE;
// m_nIterator went beyond the possible iterations
}
BOOL CTTTDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
// initialize the board with spaces
memset(m_acBoard[0], ' ', BOARD_SIZE*BOARD_SIZE);
m_cGameStatus = ' ';
m_nBestI = BOARD_SIZE/2;
m_nBestJ = BOARD_SIZE/2;
m_nIterator = -1;
// if the computer goes first then make a move.
if (m_cWhoGoesFirst == 'O')
m_acBoard[1][1] = 'O';
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CTTTDoc serialization
void CTTTDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CTTTDoc diagnostics
#ifdef _DEBUG
void CTTTDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CTTTDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTTTDoc commands
void CTTTDoc::OnOptionsHumanstart()
{
// TODO: Add your command handler code here
if (m_cWhoGoesFirst == 'X')
m_cWhoGoesFirst = 'O';
else
m_cWhoGoesFirst = 'X';
}
void CTTTDoc::OnUpdateOptionsHumanstart(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetRadio (m_cWhoGoesFirst == 'X');
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -