五子棋游戏程序记录和复盘功能设置
大家都玩过手机的小游戏吧。我是编程爱好者,喜欢动脑筋研究一些算法,编程做出小游戏程序,很有趣很有成就感。在学习VB6编程时就编制过钻石棋和伤脑筋十二块那样的游戏,都是标准Windows图形界面的。现在有空闲时就玩手机上编译手机游戏。
前些天我在站内发布了一款双人对弈版的五子棋游戏程序。接下来在研究人机对战的电脑智能应子算法,参阅很多五子棋书籍棋谱和五子棋竞赛的对抗棋谱。为了摆谱,就在此游戏程序上添加了复盘功能。程序没关闭就能复现出上一次的盘面。另外还加了记录功能和显示下子序号,每盘棋都打印黑白双方下子记录,界面上也显示记录。有一点就是程序关闭记录也就没了。解决的方法是把记录存为文本文件,需要时可作为复盘数据。
复盘数据和记录数据添加方法:在下子时记录下子序号,所下子点位,代码如下
加变量声明:
int fudat[100] ; //复盘数据组
int fusum ; //复盘黑白下子总数
string cordp ; //每条记录字串
black_do (){ //黑棋下子
pn[n]=1;
s6="白棋选子";
cordp=" B "+intToString (n); //走子记录,B 黑子,n 下子
if (cordp != ss2) { //不重复记录
dn=dn+1; print dn; //打印下子序号 dn
print cordp; ss2=cordp; //打印记录
dwn[dn]=n ; //print play number 保留记录
fudat[dn]=n; fusum=dn; //复盘数据,复盘总子数
}
board ();
testAI (); //电脑下子测试
}//black_do ()
white_do (){ //白棋下子
pn[n]=2;
s6="黑棋选子";
cordp="W "+intToString (n); //走子记录
if (cordp != ss2) {
dn=dn+1; print dn;
print cordp; ss2=cordp;
dwn[dn]=n ; //print play number
fudat[dn]=n; fusum=dn; //复盘
}
}//white_do ()
//复盘功能设置为replay ( ) ,命令按钮调用即可。
//也可改为按步逐子显示复盘,i= 1- fusum
replay (){ //复盘功能设计
gamestart (); //棋盘重绘
setDisplay (1); //显示
print "fusum= " ,fusum; //测试
for (i=1;i<=fusum;i++){
//draw chess pieces 画出复盘黑子白子
kn=fudat[i] ; //取得数据
sd=i-i/2*2 ; //mod 序号,单数=白子,双数=黑子
dx=(kn-(kn/15*15))*40; //转坐标
dy=(kn/15)*40+40;
if (dx==0){ dx=15*40; dy=dy-40; }
if ( sd==0){ //white 画白子
print i, " W ",kn ; //打印记录
ss=intToString (kn);
cordp="W "+ss; //界面记录
cs.SetColor (255,140,80,40); //piecesW
cs.DrawCircle(dx+2,dy+2,15);
cs.SetColor (255,220,220,220); //pieceW
cs.DrawCircle(dx,dy,15);
cs.SetColor (255,250,250,250); //pieceW
cs.DrawCircle(dx-5,dy-5,2); }
if ( sd==1){ //black 画黑子
print i, " B ",kn ; //打印记录
ss=intToString (kn);
cordp="B "+ss; //界面记录
cs.SetColor (255,220,100,40); //piecesB
cs.DrawCircle(dx+1,dy+1,15);
cs.SetColor (255,0,0,0); //pieceB
cs.DrawCircle(dx,dy,15);
cs.SetColor (255,200,200,200); //pieceB
cs.DrawCircle(dx-5,dy-5,2); }
if (i==fusum){ //最后一子
cs.SetColor (255,0,250,0); //标志最末胜子点
cs.DrawCircle(dx,dy,5);
cs.SetTextSize (60);
cs.SetColor (255,200,100,50);
cs.DrawText ("复 盘",253, 553) ;
cs.SetColor (255,20,250,0);
cs.DrawText ("复 盘",250, 550) ; }
cs.SetTextSize (16);
s=intToString (i); //标记序号
cs.SetColor (255,250,0,0);
cs.DrawText (s,dx-2,dy+5);
//界面显示记录
cs.SetTextStyle (0);
cs.SetTextSize (16);
cs.SetColor(255,255,250,250);
cs.DrawText (cordp,665,i*16); //写记录
cs.Update ();
sleep (1000);
} //draw replay chess pieces
}//replay ()
下面的游戏代码是用MySpringC写的,v2.7是目前最新版本。我是在安卓手机上编写的,可制作成安卓手机桌面app应用程序。此样例可复制黏贴到编译器直接使用,亦可用 VB ,VC, java 改写。
以下是完整的源码:
// 最简单的 C 语言编程
// myspringc v2.7 可编译安卓本机 app 应用
// 此样例可复制黏贴到 myspringc 编译
// 此文档可用 VB,VC , java 改写
//**********************************
//**** 五子棋 Gobang AI ********
//**** 人机对战 双人对奕 ********
//**********************************
Canvas cs; //画布
string sBarDes[10];
int nBarId[10];
string sMenu[50];
int nMenu[50];
float src[4]; //ClearDraw (cls) clear screen
int size[2]; //load picture size
string s1,s2,s3,s4,s5,s6,s7; //显示
string s,ss,ss1,ss2,ss3;
int dx,dy; //draw X, Y
FileInput filebox; //file Input box
string fname; //filename
int i,j,t,kn; //t = times 计算时间
int pn[300]; // pn 0=" " , 1=black , 2=white
int n; // 225 棋子编码号, 容错下标加大
int px,py; // piece x,y
int context; //canvasProc 触控
int obj;
int id;
int event;
int dn; //下子计数
int isDo; //游戏操作控制 1=可下子,0=不可下
int B,W,k; //detect win Black White
string cordp; //record 记录字串
int cord; //record switch
int mode; //0=人人,1=人机
int wn;
int sn;
int dwn[100]; //记录下子点位号,打印界面序号码
int cn; //AI record num
int gn ; //game round number
int fudat[100]; //复盘数据
int fusum; //复盘记录总数
int sd; //复盘
//**********
main(){
setDisplay(1);
cs.SetBackground(200,200,200);
cs.Active();
sBarDes[0]="开始游戏";
nBarId[0]=100;
sBarDes[1]="选择模式";
nBarId[1]=101;
sBarDes[2]="悔 棋";
nBarId[2]=102;
sBarDes[3]="复 盘";
nBarId[3]=103;
sBarDes[4]="退出程序";
nBarId[4]=104;
sBarDes[5]="记录";
nBarId[5]=105;
setToolBarHeight(6);
setButtonTextSize(13);
setToolBarBackgroundColor(255,220,220,220);
setButtonColor(255,0,0,240);
setButtonTextColor(255,255,255,0);
setToolBar(100,myToolBarProc,sBarDes,nBarId,6);
setTitle("五子棋 (双人对奕) V.1.0.5 ");
//**********
cs.SetProc (context, mycanvasProc);
mode=0 ;
s7="游戏模式:双人对奕";
gn=0;
gamestart (); //游戏初始界面
//draw title ****
ss3="五子棋 (双人对奕)";
cs.SetTextSize (60);
cs.SetTextStyle (1);
cs.SetFillMode (1);//0不填色,1填色
cs.SetColor(255,180,90,40);
cs.DrawText (ss3,104,504);
cs.SetColor(255,0,250,0);
cs.DrawText (ss3,100,500);
cs.SetFillMode (0);//0不填色,1填色
cs.SetColor(255,250,250,0);
cs.DrawText (ss3,100,500);
cs.Update();
while (){}
}//main ()
mycanvasProc (int context,int obj,int id,int event,float x,float y){
// board (); //redraw board
if (isDo==0) return ; //结束标志
kn=kn+1; //延时, 减少闪屏
if ((kn-kn/2*2)==0){ kn=0; }else{ return; }
board (); //redraw board
//** get chess piece position X Y
if (x>40&&x<610&&y>40&&y<610){
px=(int)(x/40)*40; //取整数,选子坐标
py=(int)(y/40)*40;
s=intToString (px);
s1= "px = "+s;
s=intToString (py);
s2= "py = "+s;
dx=px/40; dy=py/40;
s=intToString (dx);
s3= "dx = "+s;
s=intToString (dy);
s4= "dy = "+s;
n=(dy-1)*15+dx; //pn number 转棋子编码
s5="选定落子位 >> "+intToString (n);
cs.SetFillMode (0);//0不填色,1填色
cs.SetColor (255,250,0,0); //chess flag选子标记
cs.DrawRect (px-20,py-20,px+20,py+20);
}
//选子后落子缓冲按钮
if (isDo==1){ //可下子
if (x>100&&x<300&&y>900&&y<960){
if (mode==0) black_do (); //双人对弈
if (mode==1) {
black_do (); //人机,黑棋下子
// chessAI (); } //人机,机下子
testAI (); } //人机,机下子测试
} //黑已下
if (x>400&&x<600&&y>900&&y<960){
white_do ();
} //白棋已下
} //isDo==1
cs.SetFillMode (1);//0不填色,1填色
cs.SetColor (255,230,230,230); //clear n
cs.DrawRect (525,770,600,810);
// cs.SetColor(255,255,0,0);
// cs.SetTextSize (24);
//cs.DrawText (s1,50,700); //测试
//cs.DrawText (s2,50,740);
//cs.DrawText (s3,200,700);
//cs.DrawText (s4,200,740);
cs.SetColor(255,0,0,180);
cs.SetTextSize (30);
cs.DrawText (s5,330,800);
cs.Update ();
}//mycanvasProc
testAI (){
//正在研究电脑下子智能算法********
//求解方案
//**** AI 走子 **********************
return;
do_white:
//print " sn= ",sn ," k= ",k ;
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 ();
dwn[dn+1]=sn; //存储白下子信息供打印
}//testAI ()
chessAI (){ //人机模式 AI下子
if (isDo==0) return ; //结束标志
//**** AI 走子 **********************
return;
put_white:
pn[wn]=2;
s6="黑棋选子";
cordp="w "+intToString (n); //走子记录
if (cordp != ss2&&n<260) {
dn=dn+1; print dn;
print cordp; ss2=cordp; }
board ();
}//chessAI ()
black_do (){ //黑棋下子
pn[n]=1;
s6="白棋选子";
cordp=" B "+intToString (n); //走子记录
if (cordp != ss2) { //不重复记录
dn=dn+1; print dn;
print cordp; ss2=cordp;
dwn[dn]=n ; //print play number
fudat[dn]=n; fusum=dn; //复盘
}
board ();
testAI (); //test AI
}//black_do ()
white_do (){ //白棋下子
pn[n]=2;
s6="黑棋选子";
cordp="W "+intToString (n); //走子记录
if (cordp != ss2) {
dn=dn+1; print dn;
print cordp; ss2=cordp;
dwn[dn]=n ; //print play number
fudat[dn]=n; fusum=dn; //复盘
}
}//white_do ()
board (){ //初始棋盘,更新棋盘
// draw board grids 棋盘方格
cs.SetFillMode (1);//0不填色,1填色
cs.SetColor (255,250,250,250); //backcolor
cs.DrawRect (0,0,650,850); //底板
cs.SetColor (255,110,110,110);
cs.DrawRect (10,10,637,638);
cs.SetColor (255,220,150,50);
cs.DrawRect (8,8,632,632);
cs.SetColor (255,250,180,100);
cs.DrawRect (20,20,620,620);
cs.SetFillMode (0);//0不填色,1填色
for (i=1;i<15;i++){ //draw grids
for (j=1;j<15;j++){
cs.SetColor (255,150,150,150); //grid color
cs.DrawRect(i*40-1,j*40-1,i*40+39,j*40+39);
cs.SetColor (255,250,250,250); //grid color
cs.DrawRect(i*40,j*40,i*40+40,j*40+40);
} }
cs.SetColor (255,0,0,0); // 框线
cs.DrawRect (21,21,620,620);
cs.DrawRect (20,20,620,620);
//draw flag points
cs.SetFillMode (1);//0不填色,1填色
cs.SetColor (255,240,240,240); //pieces
cs.DrawCircle(160,160,5); //星
cs.DrawCircle(480,160,5);
cs.DrawCircle(160,480,5);
cs.DrawCircle(480,480,5);
cs.DrawCircle(320,320,5); //中元
//draw button 绘制按钮
cs.SetColor (255,250,250,250);
cs.DrawRect (100,900,301,960);
cs.DrawRect (400,900,601,960);
cs.SetColor (255,250,0,0);
for (i=1;i<60;i++){ //按钮渐变色
cs.SetColor (255,240-i*4,240-i*3,250-i*4);
cs.DrawLine (101,900+i,300,900+i);
cs.DrawLine (401,900+i,600,900+i);
}
cs.SetColor (255,0,120,0);
cs.DrawCircle (141,931,15);
cs.SetColor (255,0,0,0);
cs.DrawCircle (140,930,15);
cs.SetColor (255,220,220,220);
cs.DrawCircle (135,925,2);
cs.SetColor (255,0,120,0);
cs.DrawCircle (442,932,15);
cs.SetColor (255,220,220,220);
cs.DrawCircle (440,930,15);
cs.SetColor (255,250,250,250);
cs.DrawCircle (435,925,2);
cs.SetColor(255,255,250,0);
cs.SetTextStyle (1);
cs.SetTextSize (32);
cs.DrawText ("黑子下",178,940);
cs.DrawText ("白子下",478,940);
//print title 界面文字
cs.SetTextSize (80);
cs.SetTextStyle (1);
cs.SetColor (255,100,100,100);
cs.DrawText ("五子棋",50,770);
cs.DrawText ("Gobang",50,870);
cs.SetColor (255,220,220,220);
cs.DrawText ("五子棋",52,772);
cs.DrawText ("Gobang",52,872);
for (i=1;i<=225;i++){
//draw chess pieces 画出已下黑白子
dx=(i-(i/15*15))*40;
dy=(i/15)*40+40;
if (dx==0){ dx=15*40; dy=dy-40; }
if ( pn[i]==2){ //white
cs.SetColor (255,140,80,40); //piecesW
cs.DrawCircle(dx+2,dy+2,15);
cs.SetColor (255,220,220,220); //pieceW
cs.DrawCircle(dx,dy,15);
cs.SetColor (255,250,250,250); //pieceW
cs.DrawCircle(dx-5,dy-5,2); }
if (pn[i]==1){ //black
cs.SetColor (255,220,100,40); //piecesB
cs.DrawCircle(dx+1,dy+1,15);
cs.SetColor (255,0,0,0); //pieceB
cs.DrawCircle(dx,dy,15);
cs.SetColor (255,200,200,200); //pieceB
cs.DrawCircle(dx-5,dy-5,2); }
} //draw chess pieces
cs.SetColor (255,240,0,0); //刚落子标记
cs.DrawCircle(px,py,5);
//提示选子
cs.SetTextSize (42);
cs.SetColor(255,255,120,250);
cs.DrawRect (390,670,600,740);
cs.SetColor(255,255,250,0);
cs.DrawText (s6,415,720); //pn num
cs.SetTextSize (36);
if (mode==0) cs.SetColor(255,205,200,80);
if (mode==1) cs.SetColor(255,250,150,0);
cs.DrawText (s7,20,680); //mode
cs.SetTextStyle (0);
cs.SetTextSize (16);
cs.SetColor(255,255,250,250);
cs.DrawText (cordp,665,dn*16); //record
//draw pieces number 画出下子序号*****
for (i=1;i<=dn;i++){ //到已下子总数
cn=i ;
s=intToString(cn) ;
kn=dwn[i] ; //读取下子点位号转为坐标 dx,dy
dx=(kn-(kn/15*15))*40;
dy=(kn/15)*40+40;
if (dx==0){ dx=15*40; dy=dy-40; }
cs.SetTextSize (16);
cs.SetColor (255,0,160,0);
cs.DrawText (s,dx-5,dy+11);
}
cs.Update ();
detect ();
}//board ()
detect (){
//detect Black chess 判胜 ******
for (i=1;i<16;i++){ // B 黑子
for (j=1;j<12;j++){
k=(i-1)*15+j ; //pn(B) number
if (pn[k]==1){
if ( pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==1&&pn[k+4]==1){ goto showwin ; } //右
} } }
for (i=1;i<12;i++){ // B 黑子
for (j=1;j<16;j++){
k=(i-1)*15+j ; //pn(B) number
if (pn[k]==1){
if ( pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==1&&pn[k+60]==1){ goto showwin ; } //下
} } }
for (i=1;i<12;i++){ // B 黑子
for (j=1;j<12;j++){
k=(i-1)*15+j ; //pn(B) number
if (pn[k]==1){
if ( pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==1&&pn[k+64]==1){ goto showwin ; } //右斜
} } }
for (i=1;i<12;i++){ // B 黑子
for (j=5;j<16;j++){
k=(i-1)*15+j ; //pn(B) number
if (pn[k]==1){
if ( pn[k+14]==1&&pn[k+28]==1&&pn[k+42]==1&&pn[k+56]==1){ goto showwin ; } //斜左
} } }
//********************************
//detect White chess 判胜 ******
for (i=1;i<16;i++){ // W 白子
for (j=1;j<12;j++){
k=(i-1)*15+j ; //pn(W) number
if (pn[k]==2){
if ( pn[k+1]==2&&pn[k+2]==2&&pn[k+3]==2&&pn[k+4]==2){ goto showwin ; } //右
} } }
for (i=1;i<12;i++){ // W 白子
for (j=1;j<16;j++){
k=(i-1)*15+j ; //pn(W) number
if (pn[k]==2){
if ( pn[k+15]==2&&pn[k+30]==2&&pn[k+45]==2&&pn[k+60]==2){ goto showwin ; } //下
} } }
for (i=1;i<12;i++){ // W 白子
for (j=1;j<12;j++){
k=(i-1)*15+j ; //pn(W) number
if (pn[k]==2){
if ( pn[k+16]==2&&pn[k+32]==2&&pn[k+48]==2&&pn[k+64]==2){ goto showwin ; } //右斜
} } }
for (i=1;i<12;i++){ // W 白子
for (j=5;j<16;j++){
k=(i-1)*15+j ; //pn(W) number
if (pn[k]==2){
if ( pn[k+14]==2&&pn[k+28]==2&&pn[k+42]==2&&pn[k+56]==2){ goto showwin ; } //斜左
} } }
//*****************************
if (dn>100) {
ss="( 和 棋 )"; goto showwin; }
return;
//show win flag 判胜负
showwin:
cs.SetTextSize (60);
if (pn[k]==1) { ss="黑棋胜 ! !"; print ss; }
if (pn[k]==2) { ss="白棋胜 ! !"; print ss; }
cs.SetTextStyle (1);
cs.SetFillMode (1);//0不填色,1填色
cs.SetColor(255,180,90,40);
cs.DrawText (ss,204,504);
cs.SetColor(255,255,0,0);
cs.DrawText (ss,200,500);
cs.SetFillMode (0);//0不填色,1填色
cs.SetColor(255,250,250,0);
cs.DrawText (ss,200,500);
cs.Update ();
isDo=0; //结束标志
}//detect ()
gamestart (){
setDisplay (1);
cord=1 ; //记录开关
for (i=1;i<226;i++){ pn[i]=0; } //init pn (n)
for (i=0;i<=90;i++){ dwn[i]=0; } //init dwn (n)
isDo=1; //游戏操作控制
s6="黑棋选子"; //init
px=320 ; py=320 ; //标记
// mode=0 ; s7="游戏模式:双人对奕";
dn=0; //计数清零
gn=gn+1; //game round + 1
clearOutput(); //清除记录
cs.SetBackground(200,200,200); //清记录
board (); //绘出棋板
}//gamestart ()
undo(){ //悔棋,可选子连续清除
if (isDo==1) {
pn[n]=0; fudat[dn]=0;
print "悔 "+intToString (n);
cs.SetTextStyle (0);
cs.SetTextSize (16);
cs.SetColor(255,250,0,0);
cs.DrawText ("悔",652,dn*16);
dn=dn-1 ; //序号减 1
cs.Update ();
board (); }
}//undo ()
replay (){ //复盘功能设计
gamestart (); //棋盘重绘
setDisplay (1); //显示
print "fusum= " ,fusum; //测试
for (i=1;i<=fusum;i++){
//draw chess pieces 画出复盘黑子白子
kn=fudat[i] ; //取得数据
sd=i-i/2*2 ; //mod 序号,单数=白子,双数=黑子
dx=(kn-(kn/15*15))*40; //转坐标
dy=(kn/15)*40+40;
if (dx==0){ dx=15*40; dy=dy-40; }
if ( sd==0){ //white 画白子
print i, " W ",kn ; //打印记录
ss=intToString (kn);
cordp="W "+ss; //界面记录
cs.SetColor (255,140,80,40); //piecesW
cs.DrawCircle(dx+2,dy+2,15);
cs.SetColor (255,220,220,220); //pieceW
cs.DrawCircle(dx,dy,15);
cs.SetColor (255,250,250,250); //pieceW
cs.DrawCircle(dx-5,dy-5,2); }
if ( sd==1){ //black 画黑子
print i, " B ",kn ; //打印记录
ss=intToString (kn);
cordp="B "+ss; //界面记录
cs.SetColor (255,220,100,40); //piecesB
cs.DrawCircle(dx+1,dy+1,15);
cs.SetColor (255,0,0,0); //pieceB
cs.DrawCircle(dx,dy,15);
cs.SetColor (255,200,200,200); //pieceB
cs.DrawCircle(dx-5,dy-5,2); }
if (i==fusum){ //最后一子
cs.SetColor (255,0,250,0); //标志最末胜子点
cs.DrawCircle(dx,dy,5);
cs.SetTextSize (60);
cs.SetColor (255,200,100,50);
cs.DrawText ("复 盘",253, 553) ;
cs.SetColor (255,20,250,0);
cs.DrawText ("复 盘",250, 550) ; }
cs.SetTextSize (16);
s=intToString (i); //标记序号
cs.SetColor (255,250,0,0);
cs.DrawText (s,dx-2,dy+5);
//界面显示记录
cs.SetTextStyle (0);
cs.SetTextSize (16);
cs.SetColor(255,255,250,250);
cs.DrawText (cordp,665,i*16); //写记录
cs.Update ();
sleep (1000);
} //draw replay chess pieces
}//replay ()
myToolBarProc(int nBtn,int nContext){
if(nBtn==100){//开始游戏
gamestart ();
}
if(nBtn==101){//选择模式
mode=mode+1; //0=人人, 1= 人机
if (mode>1) mode=0 ;
if (mode==0) s7="游戏模式:双人对弈 ";
if (mode==1) s7="游戏模式:人机模式 ";
gamestart ();
}
if(nBtn==102){//悔棋
undo () ;
}
if(nBtn==103){//显示图板,复盘
replay ();
}
if(nBtn==104){//退出程序
clearOutput();
cs.ClearDraw (0,src);
setDisplay (0);
exit (0);
}
if(nBtn==105){//查看记录
cord=cord+1;
if (cord>1) cord=0 ;
if (cord==0) setDisplay (0); //查看记录
if (cord==1) setDisplay (1); //显示棋板
}
}//myToolBar ()
loadpic (){ //可用于装载预设棋盘底图
//use filebox open a file and load a picture
filebox.SetTitle("装载图片(*.bmp;*.jpg;*.png)");
filebox.SetFilter(".bmp;.jpg;.png");
filebox.Show();
if(filebox.GetCount()==1){
fname=filebox.GetFileName(0);
if(getPicSize(fname,size)<0){
return; }
cs.ClearDraw (0,src);
cs.DrawBitmap(fname,0,2);
cs.Update ();
}
}//loadpic ()
//**** End ********