C++黑白棋实验报告

黑白棋实验报告

我的黑白棋程序共分为两个大部分,UI部分和AI部分,分别通过若干个函数实现。UI 部分包括基本规则实现、界面设计、悔棋、存档读档、提示功能。AI部分包含搜索与剪枝、估价函数。

一、UI部分介绍

1、规则

黑白棋又叫翻转棋,棋盘为8*8正方形,有黑色和白色两种棋子,交替下棋,每次新下棋子和其他己方棋子夹住的对方棋子翻转为己方颜色。目前评价黑白棋棋力高低和局面优劣的主要参考标准包括:行动力,稳定子,外部子,内部子,奇偶性等等。

2、界面

界面为DOC命令行界面,用户使用鼠标点击菜单和棋盘。读取鼠标点击位置时使用ReadConsoleInput函数。游戏菜单包括新游戏和读档,新游戏需要点击选择人人对战/人机对战;先手/后手;难度。

游戏开始后界面为字符画出的棋盘,每次电脑下棋后更新棋盘位置。通过光标定位输出改变棋盘位置,避免连续刷屏给玩家带来不适。每次更新状态后提示可下棋位置,方便玩家选择。玩家点击棋盘上的位置即可下棋,点击无效位置无反应。

玩家在每次下棋时也可以点击菜单,菜单包括5个选项:存档,读档,悔棋,退出,作弊。每个子菜单均可返回主菜单。下面一一介绍各自功能的作用和实现方式。

3、悔棋

悔棋功能即为返回上一步下棋之前的状态,通过数组记录前一步棋盘状态,悔棋时返回上一步棋盘状态。悔棋功能可以无穷悔棋,如果已经是开局状态会提示无发悔棋。

4、存档与读档

存档和读档通过二进制文件流实现,共有三个存档位置,存在游戏安装目录下,存档时可选择三个存档中的一个存档。读档是若读取的是未存储的存档位置,会提示重新读档。

5、提示功能

提示功能是这个程序比较独特的功能之一,主要是在玩家不知道该怎么下时可以由AI 代替玩家下一步棋,实现较为简单。

一、AI部分介绍

1、最大最小值搜索

AI部分的主干采取的是博弈问题中常见的敌对搜索,原理较为简单,不在过多赘述。模拟自己下棋以及对手下棋,当到达一定深度时通过估值函数给出对局面的估价。然后再对手下棋层取子节点中的最小值(对手不想让“我”赢),自己下棋的层取子节点最大值。

2、剪枝:α-β剪枝和节点排序

Alpha-beta剪枝是敌对搜索中较为常见的最优性剪枝,由于每层中先搜索的节点(为简单,以下称为兄节点)的返回值实际上给出了本层同父节点(上一个节点相同)的界限,例如在最小值节点A的子节点中a的返回值为5,那么A的返回值至多为5。若A的兄节点B 的返回值为6,则AB的父节点X必定不会取A的值。故A节点的其他子节点的搜索已经无意义。此时A节点直接返回5。

我们发现在α-β剪枝中剪枝的效率同节点搜索顺序有极大关系,如果最先搜索的是最优解,那么剪枝效率极高。如果在最糟糕的情形下,先搜索的节点总比后搜索的节点糟糕,那么实际上不会进行剪枝。由此产生了对剪枝的进一步优化:节点排序。

节点排序是在搜索之前先对所有待搜索的点做一步预搜索(本程序中采用的是直接估值

的方式),按照大小顺序排序之后。按顺序进行搜索。这样先搜索的枝则有较大可能为较优枝,而预搜索层数很少,所以在时间上代价并不大。

3、估价函数

估价函数是决定棋力高低的重要因素,较常见的估价包括行动力(可以下棋的位置)、稳定子、内部子(相对稳定子),外部子(危险子)、奇偶性(最后一步谁下)。因为估价函数的复杂性会使得AI思考时间迅速上升,故在折中考虑以及多次实践之后,我采取了以行动力为主,同时对于绝对稳定子(四个角上的子)和最大危险子(2,2 2,7 7,2 7,7)进行考虑。在试验多次后和考虑全部稳定子相比差距并不大,而时间上略有减少。因此采用这种方式。

4、残局搜索(终局搜索)

黑白棋在即将结束时的考虑因素和中局不太相同,中局时主要考虑稳定子和行动力。但是在残局时应该考虑最多的是最终棋子数目,而且残局是可下棋位置逐渐变少,搜索层数限制的不大,因此在残局时直接搜索至游戏结束,从中选出必胜策略。

代码:

文件1:“MyFunction,h”

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

/*引用外部变量*/

extern HANDLE hout;

extern HANDLE hin;

extern INPUT_RECORD mouseRec;//控制台输入信息

extern DWORD res;

extern string sidestr[3];//输出字符

extern int turn_side[2];//表示走棋次序对应黑棋/白棋

extern int dir[8][2];//方向

extern int board[9][9];//棋盘

extern int former_board[64][9][9];//记录历史棋盘

extern int step;//步数

extern int depth;//搜索深度

extern int playerside;//玩家的颜色

extern int aput_x,aput_y;//每次AI走的棋子

extern int turn[2];//表示走棋次序对应玩家/AI

/*-------------------------------------------基本功能函数-------------------------------------------*/

/*清屏函数*/

inline void clear_screen()

{

COORD home={0,0};

DWORD dummy;

CONSOLE_SCREEN_BUFFER_INFO csbi;

GetConsoleScreenBufferInfo(hout,&csbi);

FillConsoleOutputCharacter(hout,' ',csbi.dwSize.X*csbi.dwSize.Y,home,&dummy);

SetConsoleCursorPosition(hout,home);

}

/*隐藏光标*/

inline void hide()

{

CONSOLE_CURSOR_INFO cursor_info={1,0};

SetConsoleCursorInfo(hout, &cursor_info);

}

/*光标定位*/

inline void locate(int x,int y)

{

COORD coord;//光标位置

coord.X=x;

coord.Y=y;

SetConsoleCursorPosition(hout,coord);//光标定位

}

/*读取当前鼠标点击位置*/

inline COORD get_mouse()

{

while(1){

COORD pos;

ReadConsoleInput(hin,&mouseRec,1,&res);

if (mouseRec.EventType==MOUSE_EVENT)

{

if (mouseRec.Event.MouseEvent.dwButtonState==FROM_LEFT_1ST_BUTTON_PRESSED)

{

pos=mouseRec.Event.MouseEvent.dwMousePosition;

return pos;

}

}

}

}

/*鼠标定位(功能选择)*/

inline int mouse_locate(COORD pos)

{

int x=pos.X,y=pos.Y;

if(y==0&&x>11&&x<16) return 1;//1表示点击的是存档键

if(y==0&&x>16&&x<21) return 2;//2表示点击的是读档键

if(y==0&&x>21&&x<26) return 3;//3表示点击的是悔棋

if(y==0&&x>26&&x<30) return 5;//5表示点击退出键

if(y==0&&x>30) return 6;//表示点击的是作弊键

if(y>2&&y<18&&y%2)

{

if(x>1&&x<34) return 4;//4表示点击的是落子区域

}

return 0;//0表示点击非法区域

}

/*复制棋盘*/

void copy(int org_board[9][9],int copy_board[9][9])//复制棋盘

{

for(int i=1;i<9;i++)

for(int j=1;j<9;j++)

copy_board[i][j]=org_board[i][j];

}

/*求棋子数*/

int sum(int now_board[9][9],int my_side)//求棋子数

{

int s=0;

for(int i=1;i<9;i++)

for(int j=1;j<9;j++)

{

if(now_board[i][j]==my_side) s++;

}

return s;

}

/*翻转棋盘*/

void change(int x,int y,int my_side){

board[y][x]=my_side;

for(int j=0;j<8;j++)//八个方向

{

int tempx=x+dir[j][0],tempy=y+dir[j][1],i=1;

while(tempx>0&&tempx<9&&tempy>0&&tempy<9)//不超过边界

{

if(board[tempy][tempx]==0) break;//遇到空位置跳出

else if(board[tempy][tempx]==my_side)

{

for(int k=1;k

board[y+k*dir[j][1]][x+k*dir[j][0]]=my_side;

break;

}

i++;tempx+=dir[j][0];tempy+=dir[j][1];

}

}

}

/*判断该位置是否合法*/

bool check(int x,int y,int my_side)

{

if(x==0||y==0||x>8||y>8) return 0;

if(board[y][x]!=0) return 0;

for(int j=0;j<8;j++)//八个方向

{

int tempx=x+dir[j][0],tempy=y+dir[j][1],i=1;

while(tempx>0&&tempx<9&&tempy>0&&tempy<9)//不超过边界

{

if(board[tempy][tempx]==0) break;//遇到空位置跳出

else if(board[tempy][tempx]==my_side)

{

if(i>1) return 1;//如果遇到己方子并且中间至少有一个对方子,说明可以下

break;//遇到己方子跳出

}

i++;tempx+=dir[j][0];tempy+=dir[j][1];

}

}

return 0;

}

/*---------------------------------------------界面函数----------------------------------------------*/

/*读档*/

int load_game()//0表示异常退出,1表示完成功能后退出

{

locate(0,21);cout<<"请选择读档位置:|存档一|存档二|存档三|退出读档| ";

int num;

COORD pos;

while(1)

{

pos=get_mouse();

if(pos.Y==21)

{

if(pos.X>16&&pos.X<23) {num=1;break;}

if(pos.X>23&&pos.X<30) {num=2;break;}

if(pos.X>30&&pos.X<37) {num=3;break;}

if(pos.X>37&&pos.X<46) {locate(0,21);cout<<" ";return 0;}

}

}

ifstream loadfile;

switch(num)

{

case 1:loadfile.open("save1.dat",ios::binary);break;

case 2:loadfile.open("save2.dat",ios::binary);break;

case 3:loadfile.open("save3.dat",ios::binary);break;

}

if(!loadfile)

{

locate(0,21);cout<<"读档失败,空存档或者文件损坏,请重新点击读档或其他";

return 0;

}

loadfile.read((char *)&(board[0][0]),sizeof(board));

loadfile.read((char *)&(former_board[0][0][0]),sizeof(former_board));

loadfile.read((char *)&(step),sizeof(step));

loadfile.read((char *)&(depth),sizeof(depth));

loadfile.read((char *)&(playerside),sizeof(playerside));

loadfile.read((char *)&(aput_x),sizeof(aput_x));

loadfile.read((char *)&(aput_y),sizeof(aput_y));

loadfile.read((char *)&(turn[0]),sizeof(turn));

loadfile.close();

locate(0,21);cout<<"读档成功,可继续下棋";

return 1;

}

/*存档*/

int save_game()//0表示异常退出,1表示完成功能后退出

{

locate(0,21);cout<<"请选择存档位置:|存档一|存档二|存档三|退出存档| ";

int num;//存档位置

COORD pos;

while(1)

{

pos=get_mouse();

if(pos.Y==21)

{

if(pos.X>16&&pos.X<23) {num=1;break;}

if(pos.X>23&&pos.X<30) {num=2;break;}

if(pos.X>30&&pos.X<37) {num=3;break;}

if(pos.X>37&&pos.X<46) return 0;//退出

}

}

ofstream savefile;

switch(num)

{

case 1:savefile.open("save1.dat",ios::binary);break;

case 2:savefile.open("save2.dat",ios::binary);break;

case 3:savefile.open("save3.dat",ios::binary);break;

}

if(!savefile)

{

locate(0,21);cout<<"无法存储,位置错误";

return 0;

}

savefile.write((char *)&(board[0][0]),sizeof(board));

savefile.write((char *)&(former_board[0][0][0]),sizeof(former_board));

savefile.write((char *)&(step),sizeof(step));

savefile.write((char *)&(depth),sizeof(depth));

savefile.write((char *)&(playerside),sizeof(playerside));

savefile.write((char *)&(aput_x),sizeof(aput_x));

savefile.write((char *)&(aput_y),sizeof(aput_y));

savefile.write((char *)&(turn[0]),sizeof(turn));

savefile.close();

locate(0,21);cout<<"存档成功,可继续下棋。(提示:存档位置为安装目录)";

return 1;

}

/*悔棋函数*/

void regret()

{

if(step>2)

{

copy(former_board[step-2],board);

step-=2;

locate(0,21);cout<<"悔棋成功";

}

else {locate(0,21);cout<<"已经无法悔棋啦~ ";}//已经悔棋到开始界面

/*游戏开始函数;输入游戏参数*/

int welcome(){

clear_screen();

hide();

cout<<"欢迎开始黑白棋游戏,使用鼠标点击"<

while(1)

{

COORD pos=get_mouse();

if(pos.Y==1&&pos.X<7) break;

if(pos.Y==1&&pos.X>8&&pos.X<17) return 0;

}

clear_screen();

cout<<"请选择[人人对战][人机对战]"<

int p_or_ai=1;

while(1)

{

COORD pos=get_mouse();

if(pos.Y==0&&pos.X>6&&pos.X<15) {p_or_ai=0;break;}

if(pos.Y==0&&pos.X>16&&pos.X<25) {p_or_ai=1;break;}

}

if(p_or_ai==1){

cout<<"请选择[先手执黑][后手执白]"<

while(1)

{

COORD pos=get_mouse();

if(pos.Y==1&&pos.X>6&&pos.X<15) {playerside=-1;break;}

if(pos.Y==1&&pos.X>16&&pos.X<25) {playerside=1;break;}

}

if(playerside==-1) {turn[0]=1;turn[1]=0;}

else {turn[1]=1;turn[0]=0;}

cout<<"请选择[初级][简单][中等][困难]"<

while(1)

{

COORD pos=get_mouse();

if(pos.Y==2&&pos.X>6&&pos.X<11) {depth=3;break;}

if(pos.Y==2&&pos.X>12&&pos.X<17) {depth=4;break;}

if(pos.Y==2&&pos.X>18&&pos.X<23) {depth=5;break;}

if(pos.Y==2&&pos.X>24&&pos.X<29) {depth=6;break;}

}

}

else {turn[1]=0;turn[0]=0;}

return 1;

/*打印棋盘*/

void printboard(int now_side)

{

clear_screen();

hide();//隐藏光标

int out_board[9][9];

copy(board,out_board);

for(int i=1;i<9;i++)

for(int j=1;j<9;j++)

if(check(j,i,now_side)) out_board[i][j]=2;//标记可以走的点

cout<<"黑白棋菜单:|存档|读档|悔棋|退出|作弊(电脑帮助你走一步棋)|"<

for(int y=1;y<8;y++){

cout<

for(int x=1;x<9;x++){

switch(out_board[y][x])

{case 0:cout<<" ┃";break;

case 1:cout<<"●┃";break;

case -1:cout<<"○┃";break;

case 2:cout<<"╳┃";break;

}

}

cout<

cout<<" ┣━╋━╋━╋━╋━╋━╋━╋━┫"<

}

cout<<8<<"┃";

for(int x=1;x<9;x++){

switch(out_board[8][x])

{case 0:cout<<" ┃";break;

case 1:cout<<"●┃";break;

case -1:cout<<"○┃";break;

case 2:cout<<"╳┃";break;

}

}

cout<<8<

}

/*变更棋盘,用于每局中间改变棋盘,避免反复刷屏*/

void putoutboard(int now_side)

{

int out_board[9][9];

copy(board,out_board);

for(int i=1;i<9;i++)

for(int j=1;j<9;j++)

if(check(j,i,now_side)) out_board[i][j]=2;

for(int i=1;i<9;i++)

{

for(int j=1;j<9;j++)

{

locate(j*4-1,i*2+1);

switch(out_board[i][j])

{

case 0:cout<<" ";break;

case 1:cout<<"●";break;

case -1:cout<<"○";break;

case 2:cout<<"╳";break;

}

}

}

locate(45,18);

cout<

locate(45,19);

cout<

locate(4,20);

cout<

}

/*---------------------------------------------AI部分----------------------------------------------*/ /*行动力*/

int couldput_point(int my_side)

{

int s=0;

for(int i=1;i<9;i++)

for(int j=1;j<9;j++)

if(check(j,i,my_side)) s++;

return s;

}

/*判断胜负*/

inline int checkwin(int my_side)

{

if(couldput_point(1)==0&&couldput_point(-1)==0)//两方均无子可走

{

int myscore=sum(board,my_side);

int youscore=sum(board,-my_side);

if(myscore>youscore) return 1;//胜

else if(myscore

else return 0;//平

}

return 2;//未结束

}

/*估价函数,考虑行动力和占角*/

inline int judge(int my_side,int now_side)

{

int mobility=now_side*my_side*couldput_point(now_side);

int judge_value=mobility;

judge_value+=(board[1][1]*my_side+board[8][8]*my_side+board[1][8]*my_side+board[8][1 ]*my_side)*30-(board[2][2]*my_side+board[7][7]*my_side+board[2][7]*my_side+board[7][2]*m y_side)*20;

return judge_value;

}

/*残局搜索,后8步时采取吃最多子的估值方法,并搜索到游戏结束为止*/

int final_chess_ai(int now_side,int now_depth,int alpha,int beta)//alpha最大值层的下界(超过了就不必再搜)beta最小值层的上界(超过了就不必搜)

{

if(checkwin(now_side)!=2)

{

if(depth%2==1)

return sum(board,now_side)-sum(board,-now_side);

else

return sum(board,-now_side)-sum(board,now_side);

}

else if(couldput_point(now_side)==0)

return (final_chess_ai(-now_side,now_depth+1,alpha,beta));

else{

int i,j;

int putx,puty;//要走的步

int s;

for(i=1;i<9;i++){

for(j=1;j<9;j++){

if(check(j,i,now_side)){//可下

int copyboard[9][9];//备份

copy(board,copyboard);

change(j,i,now_side);//翻转

int s1,s2;

switch(now_depth%2){

case 1:

s1=final_chess_ai(-now_side,now_depth+1,alpha,beta);

if(s1>alpha)

{alpha=s1;putx=j;puty=i;}

if(s1>beta)

{return s1;}

break;

case 0:

s2=final_chess_ai(-now_side,now_depth+1,alpha,beta);

if(s2

{beta=s2;putx=j;puty=i;}

if(s2

{return s2;}

break;

}

copy(copyboard,board);//恢复

}

}}

if(now_depth%2) s=alpha;

else s=beta;

if(now_depth==1)

{aput_x=putx;aput_y=puty;}

return s;

}

}

/*开局搜索*/

int chess_ai(int now_side,int now_depth,int alpha,int beta)//AI

{

int flag_win=checkwin(now_side);

if(flag_win==1)//如果赢了

{int s=(now_depth%2)*2000000000-1000000000;return s;}//如果当前是AI,返回10000000,如果是人返回-100000000

if(flag_win==-1)//如果输了

{int s=(1-now_depth%2)*2000000000-1000000000;return s;}

if(flag_win==0)//如果平局

return 0;

if(now_depth==depth+1)//如果到达深度

{

if(now_depth%2==1)

return judge(now_side,now_side);

else

return judge(-now_side,now_side);}

if(couldput_point(now_side)==0) return (chess_ai(-now_side,now_depth+1,alpha,beta));//如果当前轮次无棋可走

int s;//返回值

int queue[64][3];int quelen=0;//节点排序队列

for(int i=1;i<9;i++){

for(int j=1;j<9;j++){

if(check(j,i,now_side)){

int copyboard[9][9];//备份

copy(board,copyboard);

change(j,i,now_side);

queue[quelen][0]=judge(-playerside,now_side);

queue[quelen][1]=j;

queue[quelen][2]=i;

quelen++;

copy(copyboard,board);

}

}

}

for(int i=0;i

for(int j=0;j

if(queue[j][0]

{

int temp;

temp=queue[j][0];queue[j][0]=queue[j+1][0];queue[j+1][0]=temp;

temp=queue[j][1];queue[j][1]=queue[j+1][1];queue[j+1][1]=temp;

temp=queue[j][2];queue[j][2]=queue[j+1][2];queue[j+1][2]=temp;

}}}

int putx,puty;//要走的点

if(now_depth%2){

for(int j=0;j

int copyboard[9][9];//备份

copy(board,copyboard);

change(queue[j][1],queue[j][2],now_side);//翻转

int s1;

s1=chess_ai(-now_side,now_depth+1,alpha,beta);

if(s1>alpha)

{alpha=s1;putx=queue[j][1];puty=queue[j][2];}

if(s1>beta)

{return s1;}

copy(copyboard,board);//恢复

}

s=alpha;

}

else{

for(int j=quelen-1;j>=0;j--){

int copyboard[9][9];//备份

copy(board,copyboard);

change(queue[j][1],queue[j][2],now_side);//翻转

int s2;

s2=chess_ai(-now_side,now_depth+1,alpha,beta);

if(s2

{beta=s2;putx=queue[j][1];puty=queue[j][2];}

if(s2

{return s2;};

copy(copyboard,board);//恢复

}

s=beta;

}

if(now_depth==1)

{aput_x=putx;aput_y=puty;}

return s;

}

文件2”reversimain.cpp”

//黑白棋

//时间:2012.12.09

/*本文件为游戏主函数*/

#include"MyFunction.h"

using namespace std;

HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE),hin=GetStdHandle(STD_INPUT_HANDLE);//句柄

INPUT_RECORD mouseRec;//控制台输入信息

DWORD res;

string sidestr[3]={"黑"," ","白"};//输出字符

int turn_side[2]={1,-1};//表示走棋次序对应黑棋/白棋

int dir[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,1},{1,-1},{-1,-1}};//方向

int board[9][9]={{0}};//棋盘

int former_board[64][9][9];//记录历史棋盘

int step=1;//步数

int depth=3;//搜索深度

int playerside=1;//玩家的颜色

int aput_x,aput_y;//每次AI走的棋子

int turn[2]={0,0};//表示走棋次序对应玩家/AI

/*游戏函数*/

int game()

{

step=1;//初始化棋盘

for(int i=0;i<9;i++)

for(int j=0;j<9;j++)

board[i][j]=0;

board[4][4]=board[5][5]=1;

board[4][5]=board[5][4]=-1;

copy(board,former_board[0]);

while(1)

{

int flag=welcome();//开始菜单

if(flag==1)//新游戏

break;

if(flag==0)//读档

{

if(load_game())

{

printboard(turn_side[step%2]);

break;

}

else

{

locate(0,21);cout<<"读档失败,空存档或者文件损坏,请重新点击以继续";

get_mouse();

}

}

}

printboard(turn_side[step%2]);//打印初始棋盘

for(;step<=1000;step++)

{

copy(board,former_board[step]);

if(!turn[step%2]){//如果轮到人下棋

int now_side=turn_side[step%2];//当前是哪一方

if(couldput_point(now_side)==0)

{locate(0,21);cout<<"您无子可放,对手继续下棋点击鼠标继续";

get_mouse();

continue;}

else{

int px,py;

COORD pos;

int mouseflag;

while(1)

{

pos=get_mouse();

mouseflag=mouse_locate(pos);

if(mouseflag==0) continue;//未点击有效区域

else if(mouseflag==1)//存档

{

save_game();

}

else if(mouseflag==2)//读档

{

int flag=load_game();

if(flag==1) putoutboard(now_side);

}

else if(mouseflag==3)//悔棋

{

regret();

putoutboard(now_side);

continue;

}

else if(mouseflag==4)//下棋

{

px=(pos.X-2)/4+1;

py=(pos.Y-1)/2;

if(check(px,py,now_side)) break;

}

else if(mouseflag==5)//退出

return 0;

else if(mouseflag==6)//作弊

{

if(step>=52) final_chess_ai(now_side,1,-2147483647,2147483647);

else chess_ai(now_side,1,-2147483647,2147483647);

locate(0,21);cout<<"提示:AI帮你下棋的位置为("<

continue;

}

}

change(px,py,now_side);

putoutboard(-now_side);//刷新棋盘

int if_win=checkwin(now_side);//判断游戏是否结束

if(if_win==1){

locate(0,22);

cout<

if(turn[0]+turn[1]==1)

cout<<"恭喜你,你赢了^-^"<

break;}

else if(if_win==-1){

locate(0,22);

cout<

if(turn[0]+turn[1]==1)

cout<<"真杯具,你跪了:P"<

break;}

else if(if_win==0)

{locate(0,22);cout<<"平局==,再来一次吧?"<

}

}

else{

int now_side=turn_side[step%2];

if(couldput_point(now_side)==0)

{putoutboard(playerside);locate(0,21);cout<<"AI无子可放,您继续下棋";}

else{

locate(0,21);

cout<<"AI思考中……别着急";

if(step>=52) final_chess_ai(now_side,1,-2147483647,2147483647);//终局搜索

else chess_ai(now_side,1,-2147483647,2147483647);//开局搜索

change(aput_x,aput_y,now_side);

putoutboard(playerside);//更新棋盘

locate(0,21);//定位光标

cout<<"AI下棋位置为("<

int if_win=checkwin(now_side);

if(if_win==1)

{locate(0,22);cout<<"真杯具,你跪了:P"<

else if(if_win==-1)

{locate(0,22);cout<<"恭喜你,你赢了^-^"<

else if(if_win==0)

{locate(0,22);cout<<"平局==,再来一次吧?"<

}

}

}

locate(0,21);cout<<"点击鼠标继续";

get_mouse();

return 0;

}

/*主函数*/

int main()

{

hide();

while(1)

{

game();//游戏函数

clear_screen();//刷新屏幕

cout<<"是否再来一局?[退出|再来一局]"<

while(1)

{

COORD pos=get_mouse();

if(pos.Y==0&&pos.X>13&&pos.X<18) return 0;

if(pos.Y==0&&pos.X>18&&pos.X<27) break;

}

}

return 0;

}

相关主题
相关文档
最新文档