五子棋游戏AI智能算法设计
五子棋游戏C语言AI智能算法设计
近来发现编制五子棋游戏很有趣,尤其是AI智能算法很烧脑。网上介绍有什么贪心算法,剪枝算法,博弈树算法等等,不一而足。
对于人机对战的电脑智能应子算法,参阅很多五子棋书籍棋谱和五子棋竞赛的对抗棋谱。我感到白棋的后手防御算法很难取胜,棋界有黑棋高手先手必胜一说。算法么想了很多,既然是人工智能下棋就得按人的思路来算计。棋书阐述有许多思路和棋局解说。如活四冲四,嵌五,活三嵌四,活二嵌二。这些是高级棋手的总结。我就按此思路用加权计权方法来表现此类各种情况。
下面程序代码写出了基本算法。代码是function testAIq()。另外代码中有一算法测试的方法autotest()可供参考。此测试黑白双方用同一算法互斗难分胜负,这就像周伯通双手互搏,难分高下。想来要另写白棋防守算法,设置白棋VS黑棋才可看出哪个算法好。我的思路是博弈双方的白棋后手防守点也就是黑棋的加权高分点,白棋加权高分点就是进攻点。我就以计算的高分点为AI下子点。
还有一种说法五子棋博弈要算杀,算杀就是计算必杀之局,如嵌四加活三,冲四加活三,嵌五加活三,嵌五加冲四,这些就是必杀局,就是必胜法宝。算杀的最高境界是做杀,预判算出必杀点提前几子做出必杀局。此谓奕道高手中的高手,乃高高手也。此种算法也就是编程界的高手,是谓大咖也。我望之有些高仰,自感境界还没到。锲而不舍,持之以恒,努力吧。
为了摆谱,就在游戏程序上添加了复盘功能。程序没退出就能复现出上一次的盘面。另外还加了记录功能和显示下子序号,每盘棋都打印黑白双方下子记录,界面上也显示记录。有一点就是程序退出记录也就没了。解决的方法是把记录存为文本文件,需要时可作为复盘数据。也可以采用截屏方法保存棋局图片,以便以后复盘研究。
完整的源码可参阅我在本站的博文《五子棋游戏程序禁手设置算法》。此博文是有禁手设置算法的完整的游戏程序源码。
还有精彩的AI对战演示功能设计autotest(){} 用于测试算法。
//**************************************//**** 五子棋Gobang AI //**** 人机对战AI设计 //**************************************Canvascs; //画布 intdx,dy; //drawX,Yinti,j,t,a; //t=timesintpn[225]; //pn 0="",1=black,2=whiteintn; //225棋子编码号intpx,py; //piecex,yintdn,dn1; //下子计数 intisDo; //游戏操作控制1=可下子,0=不可下intB,W,k; //detectwinBlackWhitestringcordp,cordp1; //recordpn&G9intcord; //recordswitchintmode; //0=人人,1=人机intwn; intsn; intdwn[120]; //记录,下子60回合120子为和棋intcol,row;intcn,kn; //showrecordnumintgn; //gameroundnumber intfudat[200]; //复盘数据intfusum; //复盘记录总数intsd; //复盘 intjqn[255]; //计权数intjqf,jqfn; //计权分,优选点位码intjs[255]; //禁手设置intjsset; //s8showrestrictmark//**********
//AI智能下子算法求解方案://(一)四连情况,黑棋下子,黑冲四嵌五,白必应子,若白无活四022220冲四2222002222和嵌五220222220220222则必应,有则先着取胜
//(二)三连情况,黑棋下子,黑成活三嵌四,// 若白无活三02220嵌四20222202则必应,// 有则先着下子成活四
//(三)二连情况,黑棋下子, // 有活二01100 嵌三01010 基本都是这样,// 二连应子:抢先手原则,白棋先找自己的活二嵌三 // 先下子成活三嵌四
//(四)开局应首子,定标黑子pn113,白应首子// 大多棋 谱是应上pn98,上右pn99,暂定此// 白应起首三子:按棋谱法
//黑白双方博弈,加权计分,黑攻方进攻点就是白守方//防守点。计分累加标记此点,乃此算法要点。
//将下面testAIq()算法分二部分,来测试一下
autotest(){ //用于检测AI智能下子算法testAIq() //黑白棋用同一个算法下子很难区分算法的优劣, //要设计二种算法分别以黑棋VS白棋才能显示出 //算法的优劣。下面代码只可检测算法的可行性。 s7="游戏模式:对战演示"; if(isDo==0||dn>120)return;//结束标志,测试120子 if(mode==1)return;//双人模式可演示 wn=wn+1; if(dn==0){ //设定首子黑先天元位 n=113; black_do(); n=82; wn=0; //变换n加以检测 white_do(); cs.Update(); } testAIq(); //智能计权取得下子点位 if(wn>1)wn=0; //轮流下子 if(wn==1)white_do(); //白棋下子 if(wn==0)black_do(); //黑棋下子 detect();}//autotest()
testAIq(){ //人机对战AI选子,加权计算 for(i=1;i if(pn[k-1]==0)jqn[k-1]=jqn[k-1]+20; if(pn[k+1]==0)jqn[k+1]=jqn[k+1]+20; if(pn[k-15]==0)jqn[k-15]=jqn[k-15]+20; if(pn[k+15]==0)jqn[k+15]=jqn[k+15]+20; if(pn[k+14]==0)jqn[k+14]=jqn[k+14]+20; if(pn[k+16]==0)jqn[k+16]=jqn[k+16]+20; if(pn[k-14]==0)jqn[k-14]=jqn[k-14]+20; if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+20; }//pn //连二 if(pn[k]==2&&pn[k+1]==2){ //左右 if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+520; if(pn[k+2]==0) jqn[k+2]=jqn[k+2]+520; }
if(pn[k]==2&&pn[k+15]==2){ //上下 if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+520; if(pn[k+30]==0) jqn[k+30]=jqn[k+30]+520; }
if(pn[k]==2&&pn[k+14]==2){ //左对角 if(pn[k-14]==0) jqn[k-14]=jqn[k-14]+520; if(pn[k+28]==0) jqn[k+28]=jqn[k+28]+520; }
if(pn[k]==2&&pn[k+16]==2){ //右对角 if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+520; if(pn[k+32]==0)jqn[k+32]=jqn[k+32]+520; }
//嵌三 02020 +1020为活三冲四进攻点 if(pn[k]==2&&pn[k+1]==0&&pn[k+2]==2){ //左右 jqn[k+1]=jqn[k+1]+520; if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+1020; if(pn[k+3]==0) jqn[k+3]=jqn[k+3]+1020;}
if(pn[k]==2&&pn[k+15]==0&&pn[k+30]==2){ //上下 jqn[k+15]=jqn[k+15]+520; if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+1020; if(pn[k+45]==0) jqn[k+45]=jqn[k+45]+1020;}
if(pn[k]==2&&pn[k-14]==0&&pn[k-28]==2){//左对角 jqn[k-14]=jqn[k-14]+520; if(pn[k+14]==0) jqn[k+14]=jqn[k+14]+1020; if(pn[k-42]==0) jqn[k-42]=jqn[k-42]+1020;}
if(pn[k]==2&&pn[k+16]==0&&pn[k+32]==2){//右对角 jqn[k+16]=jqn[k+16]+520; if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+1020; if(pn[k+48]==0) jqn[k+48]=jqn[k+48]+1020;}
//三连,眠三抢冲四 12220 02221 if(pn[k]==2&&pn[k+1]==2&&pn[k+2]==2){ //左右 if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+2320; if(pn[k+3]==0) jqn[k+3]=jqn[k+3]+2320; } if(pn[k]==2&&pn[k+15]==2&&pn[k+30]==2){ //上下 if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+2320; if(pn[k+45]==0) jqn[k+45]=jqn[k+45]+2320; } if(pn[k]==2&&pn[k-14]==2&&pn[k-28]==2){//左对角 if(pn[k+14]==0) jqn[k+14]=jqn[k+14]+2320; if(pn[k-42]==0) jqn[k-42]=jqn[k-42]+2320; } if(pn[k]==2&&pn[k+16]==2&&pn[k+32]==2){//右对角 if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+2320; if(pn[k+48]==0) jqn[k+48]=jqn[k+48]+2320; }
//三连,活三变活四,必杀 0022200 +2000 if(pn[k-2]==0&&pn[k-1]==0&&pn[k]==2&&pn[k+1]==2&&pn[k+2]==2&&pn[k+3]==0&&pn[k+4]==0){ //左右 jqn[k-1]=jqn[k-1]+3500; jqn[k+3]=jqn[k+3]+3500; }
if(pn[k-30]==0&&pn[k-15]==0&&pn[k]==2&&pn[k+15]==2&&pn[k+30]==2&&pn[k+45]==0&&pn[k+60]==0){ //上下 jqn[k-15]=jqn[k-15]+3500; jqn[k+45]=jqn[k+45]+3500; } if(pn[k-28]==0&&pn[k-14]==0&&pn[k]==2&&pn[k+14]==2&&pn[k+28]==2&&pn[k+42]==0&&pn[k+56]==0){//左对角 jqn[k-14]=jqn[k-14]+3500; jqn[k+42]=jqn[k+42]+3500; }
if(pn[k-32]==0&&pn[k-16]==0&&pn[k]==2&&pn[k+16]==2&&pn[k+32]==2&&pn[k+48]==0&&pn[k+64]==0){//右对角 jqn[k-16]=jqn[k-16]+3500; jqn[k+48]=jqn[k+48]+3500; }//*********//白子算杀,做杀,找活三嵌四交点+2500
//嵌四类做冲四2022 2202 布杀点+1800//120220 122020020221022021 if(j if(pn[k]==2&&pn[k+15]==0&&pn[k+30]==2&&pn[k+45]==2){ //上下 if(pn[k-15]==0||pn[k+60]==0){ jqn[k+15]=jqn[k+15]+1800; } } if(pn[k]==2&&pn[k+15]==2&&pn[k+30]==0&&pn[k+45]==2){ //上下 if(pn[k-15]==0||pn[k+60]==0){ jqn[k+30]=jqn[k+30]+1800; } } }//i4&&i if(pn[k]==2&&pn[k+16]==0&&pn[k+32]==2&&pn[k+48]==2){ //右斜 if(pn[k-16]==0||pn[k+64]==0){jqn[k+16]=jqn[k+16]+1800; } } if(pn[k]==2&&pn[k+16]==2&&pn[k+32]==0&&pn[k+48]==2){ //右斜 if(pn[k-16]==0||pn[k+64]==0){ jqn[k+32]=jqn[k+32]+1800; } } }//i if(pn[k-15]==0&&pn[k]==2&&pn[k+15]==0&&pn[k+30]==2&&pn[k+45]==2&&pn[k+60]==0){ //上下 jqn[k+15]=jqn[k+15]+3500; } if(pn[k-15]==0&&pn[k]==2&&pn[k+15]==2&&pn[k+30]==0&&pn[k+45]==2&&pn[k+60]==0){ //上下 jqn[k+30]=jqn[k+30]+3500; } }
if(j>4&&i if(pn[k-16]==0&&pn[k]==2&&pn[k+16]==0&&pn[k+32]==2&&pn[k+48]==2&&pn[k+64]==0){ //右斜 jqn[k+16]=jqn[k+16]+3500; } if(pn[k-16]==0&&pn[k]==2&&pn[k+16]==2&&pn[k+32]==0&&pn[k+48]==2&&pn[k+64]==0){ //右斜 jqn[k+32]=jqn[k+32]+3500; } }
//活四冲四022220 122220 022221 //此是必杀点 +9000 j1&&pn[k-1]==0) jqn[k-1]=jqn[k-1]+9000; if(j1&&pn[k-15]==0) jqn[k-15]=jqn[k-15]+9000; if(i4&&j1&&i if(pn[k]==2&&pn[k+14]==0&&pn[k+28]==2&&pn[k+42]==2&&pn[k+56]==2){ //斜左20222 jqn[k+14]=jqn[k+14]+9000; } if(pn[k]==2&&pn[k+14]==2&&pn[k+28]==0&&pn[k+42]==2&&pn[k+56]==2){ //斜左22022 jqn[k+28]=jqn[k+28]+9000; } if(pn[k]==2&&pn[k+14]==2&&pn[k+28]==2&&pn[k+42]==0&&pn[k+56]==2){ //斜左22202 jqn[k+42]=jqn[k+42]+9000; } }
if(j if(pn[k-1]==0)jqn[k-1]=jqn[k-1]+20; if(pn[k+1]==0)jqn[k+1]=jqn[k+1]+20; if(pn[k-15]==0)jqn[k-15]=jqn[k-15]+20; if(pn[k+15]==0)jqn[k+15]=jqn[k+15]+20; if(pn[k+14]==0)jqn[k+14]=jqn[k+14]+20; if(pn[k+16]==0)jqn[k+16]=jqn[k+16]+20; if(pn[k-14]==0)jqn[k-14]=jqn[k-14]+20; if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+20; }//pn //连二 if(pn[k]==1&&pn[k+1]==1){ //左右 if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+500; if(pn[k+2]==0) jqn[k+2]=jqn[k+2]+500; } if(pn[k]==1&&pn[k+15]==1){ //上下 if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+500; if(pn[k+30]==0) jqn[k+30]=jqn[k+30]+500; } if(pn[k]==1&&pn[k+14]==1){ //左对角 if(pn[k-14]==0) jqn[k-14]=jqn[k-14]+500; if(pn[k+28]==0) jqn[k+28]=jqn[k+28]+500; } if(pn[k]==1&&pn[k+16]==1){ //右对角 if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+500; if(pn[k+32]==0)jqn[k+32]=jqn[k+32]+500; }//嵌三 02020 if(pn[k]==1&&pn[k+1]==0&&pn[k+2]==1){ //左右 jqn[k+1]=jqn[k+1]+500; } if(pn[k]==1&&pn[k+15]==0&&pn[k+30]==1){ //上下 jqn[k+15]=jqn[k+15]+500; } if(pn[k]==1&&pn[k+14]==0&&pn[k+28]==1){//左对角 jqn[k+14]=jqn[k+14]+500; } if(pn[k]==1&&pn[k+16]==0&&pn[k+32]==1){//右对角 jqn[k+16]=jqn[k+16]+500; }
//三连,眠三12220 02221逢三必堵 if(pn[k]==1&&pn[k+1]==1&&pn[k+2]==1){ //左右 if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+3000; if(pn[k+3]==0) jqn[k+3]=jqn[k+3]+3000; } if(pn[k]==1&&pn[k+15]==1&&pn[k+30]==1){ //上下 if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+3000; if(pn[k+45]==0) jqn[k+45]=jqn[k+45]+3000; }
if(pn[k]==1&&pn[k-14]==1&&pn[k-28]==1){//左对角 if(pn[k+14]==0) jqn[k+14]=jqn[k+14]+3000; if(pn[k-42]==0) jqn[k-42]=jqn[k-42]+3000; if(pn[k+2]==0) jqn[k+2]=jqn[k+2]+3050; if(pn[k-30]==0) jqn[k-30]=jqn[k-30]+3050; } //破梅花阵 if(pn[k]==1&&pn[k+16]==1&&pn[k+32]==1){//右对角 if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+3000; if(pn[k+48]==0) jqn[k+48]=jqn[k+48]+3000; if(pn[k+2]==0) jqn[k+2]=jqn[k+2]+3050; if(pn[k+30]==0) jqn[k+30]=jqn[k+30]+3050; } //破梅花阵
//三连,活三 01110 逢三必堵 if(pn[k-1]==0&&pn[k]==1&&pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==0){ //左右 if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+3300; if(pn[k+3]==0) jqn[k+3]=jqn[k+3]+3300; }
if(pn[k-15]==0&&pn[k]==1&&pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==0){ //上下 if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+3300; if(pn[k+45]==0) jqn[k+45]=jqn[k+45]+3300; }
if(pn[k-14]==0&&pn[k]==1&&pn[k+14]==1&&pn[k+28]==1&&pn[k+42]==0){//左对角 if(pn[k-14]==0) jqn[k-14]=jqn[k-14]+3300; if(pn[k+42]==0) jqn[k+42]=jqn[k+42]+3300; }
if(pn[k-16]==0&&pn[k]==1&&pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==0){//右对角 if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+3300; if(pn[k+48]==0) jqn[k+48]=jqn[k+48]+3300; }
//嵌四010110 011010 必杀点+3500 if(pn[k-1]==0&&pn[k]==1&&pn[k+1]==0&&pn[k+2]==1&&pn[k+3]==1&&pn[k+4]==0){ //左右 jqn[k+1]=jqn[k+1]+3500; } if(pn[k-1]==0&&pn[k]==1&&pn[k+1]==1&&pn[k+2]==0&&pn[k+3]==1&&pn[k+4]==0){ //左右 jqn[k+2]=jqn[k+2]+3500; }
if(pn[k-15]==0&&pn[k]==1&&pn[k+15]==0&&pn[k+30]==1&&pn[k+45]==1&&pn[k+60]==0){ //上下 jqn[k+15]=jqn[k+15]+3500; } if(pn[k-15]==0&&pn[k]==1&&pn[k+15]==1&&pn[k+30]==0&&pn[k+45]==1&&pn[k+60]==0){ //上下 jqn[k+30]=jqn[k+30]+3500; }
if(pn[k-14]==0&&pn[k]==1&&pn[k+14]==0&&pn[k+28]==1&&pn[k+42]==1&&pn[k+56]==0){ //斜左 jqn[k+14]=jqn[k+14]+3500; } if(pn[k-14]==0&&pn[k]==1&&pn[k+14]==1&&pn[k+28]==0&&pn[k+42]==1&&pn[k+56]==0){ //斜左 jqn[k+28]=jqn[k+28]+3500; }
if(pn[k-16]==0&&pn[k]==1&&pn[k+16]==0&&pn[k+32]==1&&pn[k+48]==1&&pn[k+64]==0){ //右斜 jqn[k+16]=jqn[k+16]+3500; } if(pn[k-16]==0&&pn[k]==1&&pn[k+16]==1&&pn[k+32]==0&&pn[k+48]==1&&pn[k+64]==0){ //右斜 jqn[k+32]=jqn[k+32]+3500; }
//活四冲四此是必杀点211110 011112 +6000//黑有此白必堵,此是必杀点如白无连五则必应 if(pn[k]==1&&pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==1){ //左右 if(pn[k-1]==0) jqn[k-1]=jqn[k-1]+7000; if(pn[k+4]==0) jqn[k+4]=jqn[k+4]+7000; }
if(pn[k]==1&&pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==1){ //上下 if(pn[k-15]==0) jqn[k-15]=jqn[k-15]+7000; if(pn[k+60]==0) jqn[k+60]=jqn[k+60]+7000; } if(pn[k]==1&&pn[k-14]==1&&pn[k-28]==1&&pn[k-42]==1){//左对角 if(pn[k+14]==0) jqn[k+14]=jqn[k+14]+7000; if(pn[k-56]==0) jqn[k-56]=jqn[k-56]+7000; }
if(pn[k]==1&&pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==1){//右对角 if(pn[k-16]==0) jqn[k-16]=jqn[k-16]+7000; if(pn[k+64]==0) jqn[k+64]=jqn[k+64]+7000; }
//嵌五10111 11011 11101 +6000//此是必杀点如白无连五则必应 if(pn[k]==1&&pn[k+1]==0&&pn[k+2]==1&&pn[k+3]==1&&pn[k+4]==1){ //左右10111 jqn[k+1]=jqn[k+1]+7000; } if(pn[k]==1&&pn[k+1]==1&&pn[k+2]==0&&pn[k+3]==1&&pn[k+4]==1){ //左右11011 jqn[k+2]=jqn[k+2]+7000; } if(pn[k]==1&&pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==0&&pn[k+4]==1){ //左右11101 jqn[k+3]=jqn[k+3]+7000; }
if(pn[k]==1&&pn[k+15]==0&&pn[k+30]==1&&pn[k+45]==1&&pn[k+60]==1){ //上下10111 jqn[k+15]=jqn[k+15]+7000; } if(pn[k]==1&&pn[k+15]==1&&pn[k+30]==0&&pn[k+45]==1&&pn[k+60]==1){ //上下11011 jqn[k+30]=jqn[k+30]+7000; } if(pn[k]==1&&pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==0&&pn[k+60]==1){ //上下11101 jqn[k+45]=jqn[k+45]+7000; }
if(pn[k]==1&&pn[k+14]==0&&pn[k+28]==1&&pn[k+42]==1&&pn[k+56]==1){ //斜左10111 jqn[k+14]=jqn[k+14]+7000; } if(pn[k]==1&&pn[k+14]==1&&pn[k+28]==0&&pn[k+42]==1&&pn[k+56]==1){ //斜左11011 jqn[k+28]=jqn[k+28]+7000; } if(pn[k]==1&&pn[k+14]==1&&pn[k+28]==1&&pn[k+42]==0&&pn[k+56]==1){ //斜左11101 jqn[k+42]=jqn[k+42]+7000; }
if(pn[k]==1&&pn[k+16]==0&&pn[k+32]==1&&pn[k+48]==1&&pn[k+64]==1){ //右斜10111 jqn[k+16]=jqn[k+16]+7000; } if(pn[k]==1&&pn[k+16]==1&&pn[k+32]==0&&pn[k+48]==1&&pn[k+64]==1){ //右斜11011 jqn[k+32]=jqn[k+32]+7000; } if(pn[k]==1&&pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==0&&pn[k+64]==1){ //右斜11101 jqn[k+48]=jqn[k+48]+7000; }
} } //testi,j pn(225)棋盘点位
//******************************//测试:显示加权计分情况,最高分白下子 if(isDo==0)return; cs.SetTextSize(16); cs.SetTextStyle(0); cs.SetColor(255,0,150,0); for(i=1;i if(gn==1)sn=98; if(gn==2)sn=97; if(gn==3)sn=99; } // print"sn=",jqfn,"jqf=",jqf; dx=(sn-(sn/15*15))*40; dy=(sn/15)*40+40; if(dx==0){dx=15*40; dy=dy-40; } cs.SetColor(255,250,250,0); cs.DrawCircle(dx,dy,5); //标记下子点 cs.Update(); // sleep(500); n=sn; //下子点号sn转换为n, drawboard px=dx; py=dy; //board()标记下子点 //****AI走子********************** }//testAIq()
black_do(){ //黑棋下子 pn[n]=1; s6="白棋选子"; row=15-(n/15); col=(n-(n/15*15)); if(col==0){col=15; row=row+1; } swapabc(); //returnss cordp="B "+intToString(n); //走子记录 cordp1="B "+ss+intToString(row); if(cordp!=ss2){ //不重复记录 dn=dn+1; //printdn; printdn,"",cordp," ",ss,row; //打印记录 ss2=cordp; dwn[dn]=n; //printplaynumber fudat[dn]=n; fusum=dn; //复盘数据 board(); } testAIq(); //testAI计权白子点位下子** if(mode==1){ //人机模式下子 white_do(); } //AIDo 白下子}//black_do()
white_do(){ //白棋下子 if(isDo==0)return; pn[n]=2; s6="黑棋选子"; row=15-(n/15); col=(n-(n/15*15)); if(col==0){col=15; row=row+1; } swapabc(); //returnss cordp="W "+intToString(n); //走子记录 cordp1="W "+ss+intToString(row); if(cordp!=ss2){ dn=dn+1; printdn,"",cordp," ",ss,row; //打印记录 ss2=cordp; dwn[dn]=n; //printplaynumber fudat[dn]=n; fusum=dn; //复盘数据 board(); } if(jsset==1) restrict_move(); //禁手设置 //scanrestrictedmoveanddrawmark }//white_do()