我的黑白棋

#include<stdio.h>
#include<conio.h>

/*程序用了很多的全局变量,也是没办法的,因为这些变量在程序运行时都占用,为了不必要的函数参数接口,就把许多变量设为全局变量*/
/*所有1表示player1,2表示player2,*/
/*程序增加了config,可以自己定义键位设置
config是相当独立的,
我用2个char存储一个键位,


默认键位设置: 0 1 2 3 4 5 6 7 8 9
功能 对方确认 上 左 下 右 己方悔棋 对方悔棋 己方认输 对方认输 己方确认
p1 + w a s d h - r * 回车
p2 回车 上 左 下 右 - h * r +

*/
/*关于全局变量的用途:
qp[][]:把需要打印的图象储存起来,方便打印
cmp[][]:存储键位设置
strdef[][]:默认键位设置
qps[][]:真实的棋盘,0 空 1 p1 2 p2
lsqp[][]:能下的地方 1 能下 0 不能下 用来计算是否结束 和 打印能下的地点
qpold[][][]储存旧的棋盘,悔棋用//可以做到无限悔棋,我觉得没意思,就只能悔一步
x[] y[] 光标要移动到的位置,比如说我下在5,5 当对方下时光标一开始在5,5
xold[] yold[] 储存旧的光标位置//好象没用,时间长了也不太好改
xn[]能下的数目,双方都为0时结束,统计棋子数目
m[]盘数
*/
/*程序显示能下的地方,如果觉得不好,删除有关refresh3()的语句就行了*/
char qp[25][26],cmp[3][21],strdef[3][21]={{0},{'+',0,'w',0,'a',0,'s',0,'d',0,'h',0,'-',0,'r',0,'*',0,'/r',0,0},{'/r',0,0,72,0,75,0,80,0,77,'-',0,'h',0,'*',0,'r',0,'+',0,0}};
int qps[10][10],lsqp[10][10],qpold[3][10][10],x[3],y[3],xold[3],yold[3],xn[3],m[3]={0,0,0};
int p,p1; /*p为当前player,p1为对方*/

void csqp(void) /*初始化棋盘*/
{int i,j;
for(i=0;i<25;i++)for(j=0;j<25;j++)qp[i][j]=' '; /*qp[][]外壳初始化*/
for(i=0;i<25;i++)qp[i][25]=0;
for(i=0;i<25;i+=3)
{for(j=0;j<24;j+=3)
{qp[i][j]='+';qp[i][j+1]='-';qp[i][j+2]='-';}
qp[i][j]='+';
}
for(i=1;i<23;i+=3)for(j=0;j<25;j+=3)qp[i][j]=qp[i+1][j]='|';
for(i=0;i<10;i++)for(j=0;j<10;j++){qps[i][j]=0;qpold[p][i][j]=0;}
qps[4][4]=qps[5][5]=p1; /*放上棋子*/
qps[4][5]=qps[5][4]=p;
qpold[p][4][4]=qpold[p][5][5]=p1; /*初始化悔棋的棋盘 //其实不用*/
qpold[p][4][5]=qpold[p][5][4]=p;
xold[p1]=6;yold[p1]=5;
x[1]=5;y[1]=4;
}

int refresh1(int player) /*计算给定player能下的棋子,放在lsqp[][]中,返回能下的数目*/
{ int i,j,m,n,a,b,aoplayer;
aoplayer=-player+3;
for(i=0;i<10;i++)
for(j=0;j<10;j++)
lsqp[i][j]=0;
for(i=1;i<9;i++)
for(j=1;j<9;j++)
{
if(qps[i][j])continue;
for(m=-1;m<2;m++)
for(n=-1;n<2;n++)
{
a=i+m;b=j+n;
if(qps[a][b]==aoplayer)
{
while(qps[a+=m][b+=n]==aoplayer);
if(qps[a][b]==player)lsqp[i][j]=1;
}
}
}
m=0;
for(i=1;i<9;i++)
for(j=1;j<9;j++)
m+=lsqp[i][j];
return m;
}


int hmq(int player) /*返回给定player棋子数目*/
{
int i,j,n=0;
for(i=1;i<9;i++)
for(j=1;j<9;j++)
if(qps[i][j]==player)
n++;
return n;
}


void refresh3() /*把当前player能下的地方放到qp[][]中,用来打印*/
{
int i,j,m,n;
for(i=1;i<9;i++)
for(j=1;j<9;j++)
{
if(!lsqp[i][j])
continue;
m=i*3-2;
n=j*3-2;
qp[m][n]=qp[m+1][n+1]='//';
qp[m+1][n]=qp[m][n+1]='/';
}
}


void refresh2() /*把棋子打印,就是放到qp[][]中,要在refresh3()用,不然把打印能显示下的地方覆盖*/
{
int i,j,m,n;
for(i=1;i<9;i++)
for(j=1;j<9;j++)
{
m=i*3-2;
n=j*3-2;
qp[m][n]=qp[m][n+1]=qp[m+1][n]=qp[m+1][n+1]=qps[i][j]==1?'+':qps[i][j]?'o':' ';
}
}


void hq_(int *hq) /*悔棋处理,谁悔棋,当前player就是谁,把qpold[][][]拷到qps[][]中*/
{int i,j;
p=*hq;p1=-p+3;
*hq=0;
for(i=1;i<9;i++)for(j=1;j<9;j++)qps[i][j]=qpold[p][i][j];
x[p]=xold[p];y[p]=yold[p];
refresh1(p1);refresh1(p);
}

char tranf(char ch1,char ch2) /*把接受进来的字符与键位设置比较,返回字符0~9 出错返回数字0*/
{int i;

if(!ch1)
{for(i=0;i<10;i++)
{if(ch2==cmp[p][i*2+1]){ch1=i+48;break;}}
if(i==10)ch1=0;
}
else {for(i=0;i<10;i++)
{if(ch1==cmp[p][i*2]){ch1=i+48;break;}}
if(i==10)ch1=0;
}

return ch1;
}

char sure() /*认输确认,*/
{char ch1,ch2;
gotoxy(26,4);clreol();printf("Are you sure?");
ch1=getche();if(!ch1)ch2=getche();
ch1=tranf(ch1,ch2);
return ch1;
}

void play(int x1,int y1) /*在x1,y1下子 下子前经过确认能下*/
{int i,j,m,n,a,b,x2,y2;
x2=x1/3;y2=y1/3;x[p1]=x2;y[p1]=y2;

xold[p]=x[p];yold[p]=y[p];
for(i=1;i<9;i++)for(j=1;j<9;j++)qpold[p][i][j]=qps[i][j];
for(i=-1;i<2;i++)for(j=-1;j<2;j++)
{a=m=x2+i+1;b=n=y2+j+1;
if(qps[b][a]==p1)
{
while(qps[b+=j][a+=i]==p1);
if(qps[b][a]==p)for(;(m-a)||(n-b);m+=i,n+=j)qps[n][m]=p;
}
}
qps[y2+1][x2+1]=p;
}

void go() /*显示谁下子*/
{gotoxy(26,4);clreol();
printf("player%d go!",p);
}

void printhead() /*打印信息,有多少子,赢几盘等等*/
{
gotoxy(26,1);
printf("++ oo/n");
gotoxy(26,2);
printf("++ player1:%2d oo player2:%2d/n",hmq(1),hmq(2));
gotoxy(26,3);
printf("player1:player2 %d:%d/n",m[1],m[2]);
}

void unmake(char str[15],int player) /*config部件 从键位设置中提取player的设置*/
{int i;
for(i=0;i<7;i++)str[i]=cmp[player][i+2];
str[8]=cmp[player][10];
str[9]=cmp[player][11];
str[10]=cmp[player][14];
str[11]=cmp[player][15];
str[12]=cmp[player][18];
str[13]=cmp[player][19];
}

void make(char str[15],int player) /*config部件 player设置完了 把这些设置放到键位设置里,不然白设置*/
{int i,aoplayer;aoplayer=-player+3;
for(i=0;i<7;i++)cmp[player][i+2]=str[i];
cmp[player][10]=str[8];
cmp[player][11]=str[9];
cmp[player][14]=str[10];
cmp[player][15]=str[11];
cmp[player][18]=str[12];
cmp[player][19]=str[13];
cmp[aoplayer][0]=str[12];
cmp[aoplayer][1]=str[13];
cmp[aoplayer][12]=str[8];
cmp[aoplayer][13]=str[9];
cmp[aoplayer][16]=str[10];
cmp[aoplayer][17]=str[11];
}

void defconfig() /*config部件 如果用默认设置,用这个函数就行了*/
{int i;
for(i=0;i<21;i++)
{cmp[1][i]=strdef[1][i];cmp[2][i]=strdef[2][i];}
}

void config(int player) /*config部件 设置 不知道怎么回事,右好象不能打印*/
{char ch1,ch2,str[15],a[]="about";
int i,j,flag=1;
char pr[7][11]={{"/n/030 "},{"/n/033 "},{"/n/031 "},{"/n/032 "},{"/nhui qi "},{"/nren shu "},{"/nque ding "}};
unmake(str,player);
printf("/nplayer%d",player);
for(i=0;i<7;i++)
{printf(pr[i]);
ch1=getche();if(!ch1)ch2=getche();else ch2=0;

if(ch1==27)break;
str[i*2]=ch1;str[i*2+1]=ch2;
if(i==4) /* 彩蛋 设置键位时敲about就看到了 */
{
for(j=0;j<5;j++)
if(str[j*2]!=a[j]){flag=0;break;}
if(flag){defconfig();
clrscr();
printf("progammed by GW/n");
getche();break;
}
}
}
make(str,player);
}

void rc() /*config部件 reconfig() 除了方向键,别的不可以重复,否则就要用这个函数了*/
{printf("/nsorry,you must reconfig/n");
config(1);config(2);
}

int check(int *flag) /*config部件 检查有没有重复键*/
{char str[3][15];
int i,j,k,l;
unmake(str[1],1);unmake(str[2],2);
printf("/nchecking....../n");
for(k=1,l=2;k<3;k++,l--)
for(i=8;i<14;i+=2)for(j=0;j<14;j+=2)
{if(str[k][i]==str[l][j]&&str[k][i+1]==str[l][j+i])
{rc();*flag=0;return;}
if(i==j)continue;
if(str[k][i]==str[k][j]&&str[k][i+1]==str[k][j+i])
{rc();*flag=0;return;}
}
printf("pass/n");
}

void isconfig() /*config部件 config主要函数主界面*/
{char ch;
int flag=1;
defconfig();
if(flag){printf("Do you want to config?/nPress y to config/n");
ch=getche();if(!ch)getche();
if(ch=='y'){config(1);config(2);flag=0;}
}
while(!flag)
{printf("/nDo you want to reconfig?/nPress y to reconfig/nPress d to use default config/nPress any other key to exit config/n");
ch=getche();if(!ch)getche();
flag=1;
if(ch=='d'){defconfig();flag=0;}
if(ch=='y'){config(1);config(2);flag=0;}
check(&flag);
}
}

void pgo(int *hq,int *rs) /*玩家主界面*/
{int i,j,x1,y1,n;
char ch1,ch2;

if(!xn[p])
{xn[p]=refresh1(p);xn[p1]=refresh1(p1);p=p1;p1=-p+3;return;}
clrscr();printhead();go();refresh2();refresh3();

x1=x[p]*3;y1=y[p]*3;n=hmq(1)+hmq(2);
for(;;)
{
gotoxy(1,1);
for(i=0;i<25;i++)
{printf("%s",qp[i]);
if(i!=24)printf("/n");
}

gotoxy(x1+2,y1+3);
ch1=getche();if(!ch1)ch2=getche();
ch1=tranf(ch1,ch2);


switch(ch1)
{case '1':y1=(y1+21)%24;go();break;
case '2':x1=(x1+21)%24;go();break;
case '3':y1=(y1+3)%24;go();break;
case '4':x1=(x1+3)%24;go();break;
case '5':if(n<6)break;*hq=p;return;
case '6':if(n<6)break;*hq=p1;return;
case '7':{ch2=sure();
if(ch2=='9'){*rs=p;return;}
else{go();break;}
}
case '8':{ch2=sure();
if(ch2=='0'){*rs=p1;return;}
else{go();break;}
}
case '9':{
if(!lsqp[y1/3+1][x1/3+1])
{gotoxy(26,4);clreol();printf("It's impossible!");break;}
play(x1,y1);
xn[p]=refresh1(p);xn[p1]=refresh1(p1);
p=p1;p1=-p+3;return;
}

}
}
}

void main()
{
char ch;
int hq,tag=2,rs;
int n[2];
isconfig();
for(;;)
{if(m[2]||m[1])
{clrscr();
printf("more again?/nPress Enter to continue/n");
ch=getche();if(ch-13)break;}
p=-tag+3;p1=-p+3;clrscr();csqp();rs=0;hq=0;

xn[p1]=refresh1(p1);xn[p]=refresh1(p);
for(;(xn[2]||xn[1])&&!rs;)
{pgo(&hq,&rs);if(hq)hq_(&hq);}
n[1]=hmq(1);n[0]=hmq(2);clrscr();
if(rs==2||(rs==0&&n[1]>n[0]))
{m[1]++;printf("player1 win!/n");}
if(rs==1||(rs==0&&n[0]>n[1]))
{m[2]++;printf("player2 win!/n");}
if(rs==0&&n[0]==n[1])
printf("draw!/n");
printf("player1:player2 %d:%d/n",n[1],n[0]);
printf("player1:player2 %d:%d/n",m[1],m[2]);
printf("Press any key to continue/n");
ch=getche();if(!ch)getche();
tag=-tag+3;
}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值