#include <windows.h>
#include <conio.h>
#include <string>
#include <ctime>
using namespace std;
struct pt //逻辑的
{
int x; //对应棋盘x方向上的坐标,x的值从0开始
int y; //对应棋盘y方向上的坐标,y的值从0开始
};
#define _or_ptx 0 //棋盘原点x坐标
#define _or_pty 0 //棋盘原点y坐标
#define _max_ptx 14 //棋盘最大x坐标
#define _max_pty 14 //棋盘最大y坐标
#define computerturn 1 //轮到电脑下棋
#define playturn 0 //轮到玩家下棋
#define maxelem 15 //棋盘大小,此值为实际大小,从1开始
pt m_pplastpos;//玩家走的前一步棋
pt m_pclastpos;//计算机走的前一步棋
bool m_bwfirst=false;//谁先走,1为电脑先走,0为玩家先走
bool m_binit=false;//判断游戏是否是处于刚开始阶段
void InitializeBoard();
void IsWin();//判断是否已有一方
bool pwin;
bool cwin;
bool ctable[15][15][572];
int win[2][572];
bool ptable[15][15][572];
pt ComTurn();
int GiveScore(int type,int x,int y);
bool SearchBlank(int &i,int &j,int nowboard[][15]);
void GetBoard(int tempboard[][15],int nowboard[][15]);
bool start;
bool player=false;
int board[15][15];
bool computer=false;
pt getpoint(int table[maxelem][maxelem], int max); //注:数组本来就是指向一个地址的,所以不需要加引用也可以改变其中的值
int table[maxelem][maxelem]; //如果电脑下子标记为1(电脑棋子颜色0x0b),玩家下子标记为2(玩家棋子颜色0x0e)
void gotoxy(int x, //前往x方向上对应的位置
int y); //前往y方向上对应的位置
void gotoxy(pt p); //上面函数的重载形式,传进一个点坐标
void Chang_Console_size(int max_x, //x方向上的长度,长度值从1开始
int max_y); //y方向上的长度,长度值从1开始
void color(int n_color); //n_color为颜色值,十六进制形式
void out(char* chars); //输出chars所指向的字符串
void out(int flag); //上面函数的重载形式flag = 0时输出●,flag = 1时输出■
void hidecur(); //隐藏光标
char getudlr(); //接受上下左右及回车按键
int get_rnum(int maxrand); //得到一个不大于maxrand的随机数
bool check(pt checkpoint, int table[maxelem][maxelem], int max, int checkcpflag); //检查是否获胜,checkcpflag=1是检查电脑是否获胜,checkcpflag=2是检查玩家是否获胜
void begin();
static int mainflag = 0;//指示缓冲区是否改变,如果没有改变则调用主函数,直到改变为止
int main()
{
begin();
while(mainflag++!=0){getch();getch();};
main();
return 0;
}
bool check(pt checkpoint, int board[maxelem][maxelem], int max, int checkcpflag) //检查是否获胜,checkcpflag=1是检查电脑是否获胜,checkcpflag=0是检查玩家是否获胜
{//本模块存在的问题:边缘判定具有BUG
switch(checkcpflag)
{
case 1:
if(1)
{
int ncount=0;
int ncount1=0;
int ncount2=0;
//横向扫描
for (int i=checkpoint.x; board[i][checkpoint.y]==checkcpflag; i--)
{
if (i>=0)
{
ncount1++;
}
}
for (int j=checkpoint.x; board[j][checkpoint.y]==checkcpflag; j++)
{
if (j<=max)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
ncount=0;
ncount1=0;
ncount2=0;
//纵向扫描
for (i=checkpoint.y; board[checkpoint.x][i]==checkcpflag; i--)
{
if (i>=0)
{
ncount1++;
}
}
for (j=checkpoint.y; board[checkpoint.x][j]==checkcpflag; j++)
{
if (j<=max)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
ncount=0;
ncount1=0;
ncount2=0;
//左上至右下扫描
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i--,j--)
{
if (i>=0&&j>=0)
{
ncount1++;
}
}
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i++,j++)
{
if (i<=max&&j<=max)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
ncount=0;
ncount1=0;
ncount2=0;
//坐下至右上扫描
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i--,j++)
{
if (i>=0&&j<=max)
{
ncount1++;
}
}
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i++,j--)
{
if (i<=max&&j>=0)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
}
break;
case 0:
if(1)
{
int ncount=0;
int ncount1=0;
int ncount2=0;
//横向扫描
for (int i=checkpoint.x; board[i][checkpoint.y]==checkcpflag; i--)
{
if (i>=0)
{
ncount1++;
}
}
for (int j=checkpoint.x; board[j][checkpoint.y]==checkcpflag; j++)
{
if(j<=max)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
ncount=0;
ncount1=0;
ncount2=0;
//纵向扫描
for (i=checkpoint.y; board[checkpoint.x][i]==checkcpflag; i--)
{
if(i>=0)
{
ncount1++;
}
}
for (j=checkpoint.y; board[checkpoint.x][j]==checkcpflag; j++)
{
if (j<=max)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
ncount=0;
ncount1=0;
ncount2=0;
//左上至右下扫描
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i--,j--)
{
if (i>=0&&j>=0)
{
ncount1++;
}
}
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i++,j++)
{
if (i<=max&&j<=max)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
ncount=0;
ncount1=0;
ncount2=0;
//坐下至右上扫描
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i--,j++)
{
if (i>=0&&j<=max)
{
ncount1++;
}
}
for (i=checkpoint.x,j=checkpoint.y; board[i][j]==checkcpflag; i++,j--)
{
if(i<=max&&j>=0)
{
ncount2++;
}
}
ncount = ncount1 + ncount2;
if (ncount>=6)
{
return true;
}
}
break;
}
return false;
}
pt ComTurn()
{
//bestx,best为当前最佳位置,i,j是人能下的各种位置;pi,pj是计算机能下的各种位置
int bestx,besty,i,j,pi,pj,ptemp,ctemp,pscore=10,cscore=-10000,ctempboard[15][15],ptempboard[15][15];
int m,n,temp1[20],temp2[20];//暂存第一步搜索的信息
if(start)
{
if(board[7][7]==2)
{
bestx=7;
besty=7;
}
else
{
bestx=8;
besty=8;
}
start=false;
}
else
{//寻找最佳位置
GetBoard(ctempboard,board);
while(SearchBlank(i,j,ctempboard))
{
n=0;
pscore=10;
GetBoard(ptempboard,board);
ctempboard[i][j]=3;//标记已被查找
ctemp=GiveScore(1,i,j);
for(m=0;m<572;m++)
{//暂时更改玩家信息
if(ptable[i][j][m])
{
temp1[n]=m;
ptable[i][j][m]=false;
temp2[n]=win[0][m];
win[0][m]=7;
n++;
}
}
ptempboard[i][j]=1;
// ChangeStatus(ptempboard);
pi=i;
pj=j;
while(SearchBlank(i,j,ptempboard))
{
ptempboard[i][j]=3;//标记已被查找
ptemp=GiveScore(0,i,j);
if(pscore>ptemp)////此时为玩家下子,运用极小极大法时应选取最小值
pscore=ptemp;
}
for(m=0;m<n;m++)
{//恢复玩家信息
ptable[pi][pj][temp1[m]]=true;
win[0][temp1[m]]=temp2[m];
}
if(ctemp+pscore>cscore)//此时为计算机下子,运用极小极大法时应选取最最大值
{
cscore=ctemp+pscore;
bestx=pi;
besty=pj;
}
}
}
board[bestx][besty]=1;
for(i=0;i<572;i++)
{//修改计算机下子后,棋盘的变化状况
if(ctable[bestx][besty][i]&&win[1][i]!=7)
win[1][i]++;
if(ptable[bestx][besty][i])
{
ptable[bestx][besty][i]=false;
win[0][i]=7;
}
}
pt bestpt;
bestpt.x=bestx;
bestpt.y=besty;
return bestpt;
}
pt getpoint(int table[maxelem][maxelem], int max) //注:数组本来就是指向一个地址的,所以不需要加引用也可以改变其中的值
{
pt bestpt;
bestpt.x = 0;
bestpt.y = 0;
bestpt.x = get_rnum(10);
bestpt.y = ge