井字棋游戏
开发工具:Visual C++.NET 2003
程序员:黄江斌
程序功能:井字棋小游戏,人机对战版
时间:2005年8月28日
界面如下图:
程序分析:
CtictactoeView::CtictactoeView()//程序中关键变量赋初值
{
// TODO: 在此处添加构造代码
int i , j;
for( i = 0 ; i < 3 ; i++ )
for( j = 0 ; j < 3 ; j++ )
myGraph[i][j] = 0;
currX = -1;
currY = -1;
whosTurn = 1;
whosFirst = 1;
}
void CtictactoeView::OnDraw(CDC* pDC)//程序界面、游戏状态的显示
{
CtictactoeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
CBitmap bitmap[9];
CBitmap *pOldBitmap;
CDC MemDC;
int i , j;
int myTop = 5;
int myLeft;
int mySize = 100;
MemDC.CreateCompatibleDC( pDC );
for( i = 0 ; i < 3 ; i++ )
{
myTop = 5 + 105 * i;
myLeft = 5;
for( j = 0 ; j < 3 ; j++ )
{
myLeft = 5 + 105 * j;
if( myGraph[i][j] == 0 )
{
bitmap[ 3 * i + j ].LoadBitmap( IDB_BACKGROUND );
}
else if( myGraph[i][j] == 1 )
{
bitmap[ 3 * i + j ].LoadBitmap( IDB_CROSS );
}
else if( myGraph[i][j] == 2 )
{
bitmap[ 3 * i + j ].LoadBitmap( IDB_ROUND );
}
else
{
bitmap[3 * i + j ].LoadBitmap( IDB_CHOOSE );
}
pOldBitmap = MemDC.SelectObject( &bitmap[ 3 * i + j ] );
pDC->BitBlt( myLeft , myTop , mySize , mySize , &MemDC , 0 , 0 , SRCCOPY );
MemDC.SelectObject( pOldBitmap );
}
}
}
void CtictactoeView::OnMouseMove(UINT nFlags, CPoint point)//跟踪鼠标位置
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
this->point = point;
int x , y;
x = -1;
y = -1;
if( point.x >= 5 && point.x <= 105 )
x = 0;
else if( point.x >= 110 && point.x <= 210 )
x = 1;
else if( point.x >= 215 && point.x <= 315 )
x = 2;
if( point.y >= 5 && point.y <= 105 )
y = 0;
else if( point.y >= 110 && point.y <= 210 )
y = 1;
else if( point.y >= 215 && point.y <= 315 )
y = 2;
CRect mRect;
if( currX == x && currY == y )
return;
if( currX != -1 && currY != -1 && myGraph[currY][currX] == 3 )
{
myGraph[currY][currX] = 0;
mRect = CRect( 5 + currX * 105 , 5 + currY * 105 , 105 + currX * 105 , 105 + currY * 105 );
InvalidateRect( mRect );
currX = -1;
currY = -1;
}
if( x != -1 && y != -1 && myGraph[y][x] == 0 )
{
currX = x;
currY = y;
myGraph[y][x] = 3;
mRect = CRect( 5 + x * 105 , 5 + y * 105 , 105 + x * 105 , 105 + y * 105 );
InvalidateRect( mRect );
}
CView::OnMouseMove(nFlags, point);
}
void CtictactoeView::OnMouseX( CCmdUI *pCmdUI )//在状态栏中显示鼠标位置
{
CString cs;
cs.Format( "X=%d", point.x );
pCmdUI->SetText( cs );
}
void CtictactoeView::OnMouseY( CCmdUI *pCmdUI ) //在状态栏中显示鼠标位置
{
CString cs;
cs.Format( "Y=%d", point.y );
pCmdUI->SetText( cs );
}
void CtictactoeView::OnWhosFirst( CCmdUI *pCmdUI )//在状态栏中显示电脑先走还是人先走
{
if( whosFirst == 2 )
pCmdUI->SetText( "电脑先" );
else
pCmdUI->SetText( "用户先" );
}
void CtictactoeView::OnLButtonDown(UINT nFlags, CPoint point)//人走棋的输入部分
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if( currX == -1 || currY == -1 )
{
}
else
{
myGraph[currY][currX] = whosTurn;
CRect mRect;
mRect = CRect( 5 + currX * 105 , 5 + currY * 105 , 105 + currX * 105 , 105 + currY * 105 );
InvalidateRect( mRect );
if( whosTurn == 1 )
whosTurn = 2;
else
whosTurn = 1;
currX = -1;
currY = -1;
int ret = judgment();
if( ret == 0 )
computerPlay();
else
winner( ret );
}
CView::OnLButtonDown(nFlags, point);
}
void CtictactoeView::computerPlay(void) //电脑走棋的人工智能部分
{
long score[3][3];
long maxScore;
int x,y;
int i,j,k;
int me = 2;
int another = 1;
for( i = 0 ; i < 3 ; i++ )
for( j = 0 ; j < 3 ; j++ )
{
score[i][j] = 0;
if( myGraph[i][j] != 0 )
continue;
if( ( i + j ) % 2 == 0 )
score[i][j] += 10;
else
score[i][j] += 1;
if( i == 1 && j == 1 )
score[i][j] += 90;
for( k = 0 ; k < 3 ; k++ )
if( k != j )
{
if( myGraph[i][k] == me )
{
if( myGraph[i][3-j-k] == me )
score[i][j] += 100000;
else if( myGraph[i][3-j-k] == 0 )
score[i][j] += 1000;
break;
}
else if( myGraph[i][k] == another )
{
if( myGraph[i][3-j-k] == another )
score[i][j] += 10000;
else if( myGraph[i][3-j-k] == 0 )
score[i][j] += 750;
break;
}
}
for( k = 0 ; k < 3 ; k++ )
if( k != i )
{
if( myGraph[k][j] == me )
{
if( myGraph[3-i-k][j] == me )
score[i][j] += 1000000;
else if( myGraph[3-i-k][j] == 0 )
score[i][j] += 1000;
break;
}
else if( myGraph[k][j] == another )
{
if( myGraph[3-i-k][j] == another )
score[i][j] += 10000;
else if( myGraph[3-i-k][j] == 0 )
score[i][j] += 750;
break;
}
}
if( i == j )
{
for( k = 0 ; k < 3 ; k++ )
if( k != i )
{
if( myGraph[k][k] == me )
{
if( myGraph[3-i-k][3-i-k] == me )
score[i][j] += 1000000;
else if( myGraph[3-i-k][3-i-k] == 0 )
score[i][j] += 1000;
break;
}
else if( myGraph[k][k] == another )
{
if( myGraph[3-i-k][3-i-k] == another )
score[i][j] += 10000;
else if( myGraph[3-i-k][3-i-k] == 0 )
score[i][j] += 750;
break;
}
}
}
if( ( i + j ) == 2 )
{
for( k = 0 ; k < 3 ; k++ )
if( k != i && 2 - k != j )
{
if( myGraph[k][2-k] == me )
{
if( myGraph[3-i-k][i+k-1] == me )
score[i][j] += 1000000;
else if( myGraph[3-i-k][i+k-1] == 0 )
score[i][j] += 1000;
break;
}
else if( myGraph[k][2-k] == another )
{
if( myGraph[3-i-k][i+k-1] == another )
score[i][j] += 10000;
else if( myGraph[3-i-k][i+k-1] == 0 )
score[i][j] += 750;
break;
}
}
}
}
maxScore = 0;
for( i = 0 ; i < 3 ; i++ )
for( j = 0 ; j < 3 ; j++ )
if( score[i][j] > maxScore )
{
maxScore = score[i][j];
x = i;
y = j;
}
CRect mRect;
mRect = CRect( 5 + y * 105 , 5 + x * 105 , 105 + y * 105 , 105 + x * 105 );
InvalidateRect( mRect );
myGraph[x][y] = whosTurn;
if( whosTurn == 1 )
whosTurn = 2;
else
whosTurn = 1;
int ret = judgment();
if( ret != 0 )
winner( ret );
}
int CtictactoeView::judgment()//判断是否已经结束游戏,判决谁赢得比赛
{
int who;
int i,j;
bool flag;
for( who = 1 ; who <= 2 ; who++ )
{
//检查玩家who在行上是否成胜状态
for( i = 0 ; i < 3 ; i++ )
{
flag = true;
for( j = 0 ; j < 3 && flag ;j++ )
if( myGraph[i][j] != who )
flag = false;
//如果有成胜状态,就可以返回了
if( flag )
return who;
}
for( j = 0 ; j < 3 ; j++ )
{
flag = true;
for( i = 0 ; i < 3 && flag ; i++ )
if( myGraph[i][j] != who )
flag = false;
if( flag )
return who;
}
//检查斜列1有无成胜状态
flag = true;
for( i = 0 ; i < 3 && flag ; i++ )
if( myGraph[i][i] != who )
flag = false;
if( flag )
return who;
//检查斜列2有无成胜状态
flag = true;
for( i = 0 ; i < 3 && flag ; i++ )
if( myGraph[i][3-i-1] != who )
flag = false;
if( flag )
return who;
}
flag = true;
for( i = 0 ; i < 3 && flag ; i++ )
for( j = 0 ; j < 3 && flag ; j++ )
if( myGraph[i][j] == 0 )
flag = false;
if( flag )
return 3;
else
return 0;
return 0;
}
void CtictactoeView::winner( int who )//显示谁赢得比赛
{
switch( who )
{
case 1:
::AfxMessageBox( "祝贺你胜利啦!" );
break;
case 2:
::AfxMessageBox( "电脑胜利,你要加油噢!" );
break;
case 3:
::AfxMessageBox( "平局!" );
}
initGame();
}
void CtictactoeView::initGame(void)//一局游戏的初始化
{
int i , j;
for( i = 0 ; i < 3 ; i++ )
for( j = 0 ; j < 3 ; j++ )
myGraph[i][j] = 0;
currX = -1;
currY = -1;
CRect mRect;
mRect = CRect( 5 , 5 , 315 , 315 );
InvalidateRect( mRect );
if( whosFirst == 1 )
{
whosFirst = 2;
whosTurn = 2;
computerPlay();
}
else
{
whosFirst = 1;
whosTurn = 1;
}
}
void CtictactoeView::OnNewgame()//开始新的游戏
{
// TODO: 在此添加命令处理程序代码
initGame();
}