#include "stdafx.h"
#include "Gloab.h"
//定义点
struct Point
{
int x ;
int y ;
};
//定义棋子节点,用于悔棋
struct chessNode
{
Point point;//棋子的棋盘位置
int status;//下子者 0为电脑 ,1为棋手,2为空白
int win[2][252];//用于存储当前节点的胜利组合数目
};
class chess
{
private:
//定义棋盘上棋子的状态
//const int Black = 0;//黑棋为电脑
//const int White = 1;//白棋为棋手
//const int Blank = 2;//空白
//定义棋手和电脑的棋盘用于存放
bool playerBoard[11][11][252];
bool computerBoard[11][11][252];
//分别用于存放电脑和棋手在各点的得分
int computerGrade[11][11],playerGrade[11][11];
//计算在每种组合中电脑或棋手分别占据几粒棋子
//0代表电脑,1代表棋手
int win[2][252];
//定义是否为第一步棋
bool start;
//记录电脑和棋手的下棋步数
int computerCount;
int playerCount;
//用以进行当前下棋者的转换
bool player,computer;
//用于存放所有棋子的状态,位置和下子者,用于悔棋只用
chessNode allChess[122];
//是否游戏结束
bool gameover;
//获胜者 0为电脑 1为棋手 2为游戏未结束 -1为平局
int winner;
/*************功能函数**************************/
//把棋盘初始化为空白
int initBoard();
//初始化分数
void initialMark();
//初始化获胜的组合数
int initWinCompages();
//记录所下棋子的状态
void recordChessStatus(int horizontal , int vertical , int player);
//计算某个胜利组合中已经被某方占据的棋子数放到win[2][252]的数组中去, 参数分别为水平,竖直位置,最后是记录落子的是电脑还是棋手
int compute(int horizontal , int vertical , int player);
public:
//定义棋盘
int Board[11][11];
//构造函数
chess();
//电脑通过计算确定下棋位置
int computerPlay();
//棋手在棋盘中落子
int playerPlayChess(int horizontal , int vertical);
//悔棋,只能对己方上一步进行悔棋
int contritionChess();
//判断是否已经游戏结束
bool gameOver(int player);
//取得获胜者 0为电脑 1为棋手 2为棋局未结束 -1为平局
int getWinner();
};
/*************功能函数**************************/
//把棋盘初始化为空白
int chess::initBoard()
{
int i=0;
//把棋盘初始化为空格
for( i =0 ; i < 11 ;i++)
{
for(int j = 0 ; j < 11 ; j++)
Board[i][j] = 2;
}
//初始化棋局
for(i = 0 ; i<122 ; i++)
{
allChess[i].point.x = -1;
allChess[i].point.y = -1;
allChess[i].status = 2 ;
}
computerCount = playerCount = 0;
gameover = false ;
winner = 2;
return 0 ;
}
//初始化分数
void chess::initialMark()
{
for(int i = 0 ;i < 11 ; i ++)
for(int j = 0 ; j < 11 ; j++)
{
computerGrade[i][j] = 0 ;
playerGrade[i][j] = 0 ;
}
}
//初始化获胜的组合数
int chess::initWinCompages()
{
int i=0,j=0,k=0,num=0;
//初始化水平方向的获胜组合数
for(i = 0 ; i< 11; i++)
{
for(int j = 0 ; j < 7 ; j++)
{
for(k = 0; k < 5 ; k++)
{
playerBoard[i][j+k][num] = true;
computerBoard[i][j+k][num] = true;
}
num++;
}
}
//初始化垂直方向的获胜组合数
for(j = 0 ; j< 11; j++)
{
for(int i = 0 ; i < 7 ; i++)
{
for(k = 0; k < 5 ; k++)
{
playerBoard[i+k][j][num] = true;
computerBoard[i+k][j][num] = true;
}
num++;
}
}
//初始化正对角线方向获胜组合
for(i = 0 ; i< 7; i++)
{
for( j = 0 ; j < 7 ; j++)
{
for(k = 0; k < 5 ; k++)
{
playerBoard[i+k][j+k][num] = true;
computerBoard[i+k][j+k][num] = true;
}
num++;
}
}
//初始化反对角线方向获胜组合
for(i = 0 ; i < 7; i++)
for(j = 10 ;j >= 4 ; j--)
{
for(k = 0; k < 5 ; k++)
{
playerBoard[i+k][j+k][num] = true;
computerBoard[i+k][j+k][num] = true;
}
num++;
}
num = 0 ;
return 0;
}
//记录所下棋子的状态
void chess::recordChessStatus(int horizontal , int vertical , int player)
{
//存放位置是与下棋的步数相同,也就是从1开始到121,
allChess[(playerCount+computerCount)].point.x = horizontal;
allChess[(playerCount+computerCount)].point.y = vertical;
allChess[(playerCount+computerCount)].status = player;
//记录当前节点的获胜组合数
for(int i = 0 ; i <2 ; i++)
for(int j = 0 ; j <252 ;j++)
allChess[(playerCount+computerCount)].win[i][j] = win[i][j];
return ;
}
//计算某个胜利组合中已经被某方占据的棋子数放到win[2][252]的数组中去, 参数分别为水平,竖直位置,最后是记录落子的是电脑还是棋手
int chess::compute(int horizontal , int vertical , int player)
{
//如果棋子的位置不在11 * 11范围内的话返回错误
if((horizontal >=11)||(vertical >= 11)||(horizontal < 0)||(vertical < 0))
return -1 ;
for(int i = 0 ; i < 252 ; i++)
{
//如果落子者为棋手
if(player == 1)
{
if(playerBoard[horizontal][vertical][i] && (win[1][i] != -1))
{
//统计该组合中己方已占据几子,若是为-1表示该组合中有一个已经被对手占据,不可能胜利了
win[1][i]++;
}
if(computerBoard[horizontal][vertical][i])
{
//因为棋手已经在该组合中落下一子 所以电脑不可能通过此组合胜利
computerBoard[horizontal][vertical][i] = false;
win[0][i] = -1;
}
}
//如果落子者为电脑
else if(player == 0)
{
if(computerBoard[horizontal][vertical][i] && (win[0][i] != -1))
{
//统计该组合中己方已占据几子,若是为-1表示该组合中有一个已经被对手占据,不可能胜利了
win[0][i]++;
}
if(playerBoard[horizontal][vertical][i])
{
//因为棋手已经在该组合中落下一子 所以电脑不可能通过此组合胜利
playerBoard[horizontal][vertical][i] = false;
win[1][i] = -1;
}
}
}
return 1;
}
//构造函数
chess::chess()
{
initBoard();
initWinCompages();
initialMark();
start = true;
player = true;
computer = false;
}
//电脑通过计算确定下棋位置
int chess::computerPlay()
{
if(computer)
{
int i = 0,j = 0 , k = 0;
//用于存放棋盘中电脑和棋手的最高分数
int playerMax = 0 ,computerMax = 0;
int pX = -1,pY = -1,cX = -1 ,cY = -1;
//用于暂存电脑最后确定的下棋位置
int x , y ;
//如果为电脑的第一步棋则优先置于棋盘的中心位置
if(start)
{
if(Board[5][5] == 2)
{
x = 5;
y = 5;
}
else
{
x = 5;
y = 4;
}
Board[x][y] = 0;
compute(x,y,0);
computerCount++;
//记录所下棋子的状态
recordChessStatus(x,y,0);
computer = false;
player = true;
start = false;
return 1;
}
//先计算棋手的棋盘分数
for(i = 0 ; i < 11 ; i++)
for( j = 0 ; j < 11 ; j++)
{
//如果该位置为空才对该位置计分
if(Board[i][j] == 2)
{
for(int k = 0 ; k < 252 ; k ++ )
{
//确定该位置在哪个获胜的组合中
if(playerBoard[i][j][k])
{
switch(win[1][k])
{
//通过计算组合的五子中己方占据子数计分,1子五分,2子50,3子500,4子5000
case 1:
playerGrade[i][j] = playerGrade[i][j] + 5;
break;
case 2:
playerGrade[i][j] = playerGrade[i][j] + 50;
break;
case 3:
playerGrade[i][j] = playerGrade[i][j] + 500;
break;
case 4:
playerGrade[i][j] = playerGrade[i][j] + 5000;
break;
}
}
}
}
//如果当前位置大于之前找到的最高分位置,保存当前位置信息
if(playerGrade[i][j] > playerMax)
{
playerMax = playerGrade[i][j];
pX = i ;
pY = j ;
}
}
//计算电脑在棋盘位置的得分
for(i = 0 ; i < 11 ; i++)
for( j = 0 ; j < 11 ; j++)
{
//如果该位置为空才对该位置计分
if(Board[i][j] == 2)
{
for(int k = 0 ; k < 252 ; k ++ )
{
//确定该位置在哪个获胜的组合中
if(computerBoard[i][j][k])
{
switch(win[0][k])
{
//通过计算组合的五子中己方占据子数计分,1子五分,2子50,3子500,4子5000
//让电脑在同等条件下多得一分 , 使之更侧重于进攻,如果侧重于防守同理可得
case 1:
computerGrade[i][j] = computerGrade[i][j] + 6;
break;
case 2:
computerGrade[i][j] = computerGrade[i][j] + 51;
break;
case 3:
computerGrade[i][j] = computerGrade[i][j] + 501;
break;
case 4:
computerGrade[i][j] = computerGrade[i][j] + 5001;
break;
}
}
}
}
//如果当前位置大于之前找到的最高分位置,保存当前位置信息
if(computerGrade[i][j] > computerMax)
{
computerMax = computerGrade[i][j];
cX = i ;
cY = j ;
}
}
//如果电脑的最高分大于棋手最高分,则电脑进攻
if(computerMax > playerMax)
{
x = cX ;
y = cY ;
}
else
{
x = pX;
y = pY;
}
//将最佳下棋点置为电脑
Board[x][y] = 0 ;
//计算经过落子后某个胜利组合中已经被某方占据的棋子数
compute(x,y,0);
computerCount++;
//记录所下棋子的状态
recordChessStatus(x,y,0);
//下棋者转换
computer = false;
player = true;
if( computerCount == 60 ) //棋盘上无空位的情况
{
gameover = true ;
winner = -1;
}
initialMark();
return 1;
}
initialMark();
return -1;
}
//棋手在棋盘中落子
int chess::playerPlayChess(int horizontal , int vertical)
{
if(player)
{
//如果棋子的位置不在11 * 11范围内的话返回错误
if((horizontal >=11)||(vertical >= 11)||(horizontal < 0)||(vertical < 0))
return -1 ;
if(Board[horizontal][vertical] != 2)
return -1;
Board[horizontal][vertical] = 1;
playerCount++;
//记录所下棋子的状态
recordChessStatus(horizontal,vertical,1);
//计算棋手落子之后棋盘上棋手在一个组合中占有的棋子数
if(!compute(horizontal,vertical,1))
return -1;
player = false ;
computer = true ;
if( playerCount == 60 ) //棋盘上无空位的情况
{
gameover = true ;
winner = -1;
}
return 1;
}
else
return -1;
}
//悔棋,只能对己方上一步进行悔棋
int chess::contritionChess()
{
//用于存放当前步数
int step;
Point point ;
int player = 2;
step = computerCount + playerCount;
if(step > 1)
{
//先撤销电脑的下棋位置
//确认刚落子的是否为电脑
if((allChess[step].status == 0)&&(allChess[step].point.x != -1))
{
point = allChess[step].point;
Board[point.x][point.y] = 2;
allChess[step].status = 2;
allChess[step].point.x = -1;
allChess[step].point.y = -1;
//恢复step-1的组合胜利数
for(int i = 0 ; i <2 ; i++)
for(int j = 0 ; j <252 ;j++)
win[i][j] = allChess[(playerCount+computerCount)].win[i][j] ;
computerCount--;
step -- ;
}
//撤销棋手的棋
if((allChess[step].status == 1)&&(allChess[step].point.x != -1))
{
point = allChess[step].point;
Board[point.x][point.y] = 2;
allChess[step].status = 2;
allChess[step].point.x = -1;
allChess[step].point.y = -1;
//恢复step-1的组合胜利数
for(int i = 0 ; i <2 ; i++)
for(int j = 0 ; j <252 ;j++)
win[i][j] = allChess[(playerCount+computerCount)].win[i][j] ;
playerCount--;
step--;
}
}
return 1;
}
//判断是否已经游戏结束
bool chess::gameOver(int player)
{
if(!gameover)
{
int i ;
//如果为棋手,判断win[1][i]中是否有已经五子的组合
if(player == 1)
{
for( i = 0 ; i < 252 ; i++ )
if(win[1][i] == 5)
{
//游戏结束
gameover = true ;
winner = 1;
return true;
}
}
if(player == 0)
{
for( i = 0 ; i < 252 ; i++ )
if(win[0][i] == 5)
{
//游戏结束
gameover = true ;
winner = 0;
return true;
}
}
return false;
}
return true;
}
//取得获胜者 0为电脑 1为棋手 2为棋局未结束 -1为平局
int chess::getWinner()
{
return winner;
}