前言
有了上次编写井字棋游戏的经验,一个多礼拜后终于编写出了这个五子棋游戏。内容完全原创,但不乏冗长繁琐,运行效果也有不足之处,还望批评指正。
编写
1 界面
出于编写方便的需要,将棋盘定义为一个二维数组;打印棋盘是对应行列打印数字,便于清晰地找到落子位置。
//打印界面
void prtface_1()
{
for(i=0;i<Row;i++)
{
if(i==0) printf("\n");
printf("*");
if(i==Row-1) printf("\n");
}
}
void prtface_2()
{
for(i=0;i<5;i++) printf(" ");
}
void prtface()
{
prtface_1();
prtface_2();
printf(" 五子棋 ");
prtface_2();
printf("\n");
prtface_2();
printf("1. 开始游戏");
prtface_2();
printf("\n");
prtface_2();
printf("2. 结束游戏");
prtface_2();
prtface_1();
}
//初始化棋盘
void inibrd()
{
for(i=0;i<Row;i++)
for(j=0;j<Col;j++)
if(i==0) board[i][j]='-';
else if(j==0) board[i][j]='|';
else board[i][j]='+';
}
//打印棋盘
void prtbrd()
{
for(i=0;i<Row+1;i++)
{
if(i==0)
for(j=0;j<Col+1;j++)
{
if(j==0) printf(" ");
else printf("%-3d",j-1);
if(j==Col) printf("\n");
}
else
for(j=0;j<Col+1;j++)
{
if(j==0) printf("%-3d",i-1);
else printf("%-3c",board[i-1][j-1]);
if(j==Col) printf("\n");
}
}
}
2 相关函数
依照井字棋,需要编写胜负判断函数和落子函数等函数。起初只编写了玩家落子和电脑落子函数且电脑落子时采用随机落子,由*rand()*控制,*srand(time(NULL))*作种子。后面补充了双人模式的落子以及电脑落子的优化(这一部分写得很多,但和人相比还是有差距)。
//电脑落子判断
void comchs()
{
int rper=0,cper=0,chstime=0;
rper=r;
cper=c;
srand(time(NULL));
if(count>=6)
{
for(r=1;r<Row-1;r++)
{
for(c=1;c<Col-1;c++)
{
if(r>16&&c>16 ) continue;
else
{
if(board[r][c]==board[r][c+1]&&board[r][c+1]==board[r][c+2]&&board[r][c+2]==chsper&&c+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r][c+3]=='+'&&c+3<=19&&board[r][c-1]=='+'&&c-1>=1)
{
c+=3;
mark=1;
}
else if(board[r][c+3]=='+'&&c+3<=19&&board[r][c-1]=='+'&&c-1>=1)
{
c-=1;
mark=1;
}
else if(board[r][c+3]==chsper&&board[r][c+4]=='+'&&c+4<=19)
{
c+=4;
mark=1;
}
else if(board[r][c+3]==chsper&&board[r][c-1]=='+'&&board[r][c+4]!=chsper&&c-1>=1&&c+3<=19)
{
c-=1;
mark=1;
}
}
else if(board[r][c]==board[r+1][c]&&board[r+1][c]==board[r+2][c]&&board[r+2][c]==chsper&&r+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r+3][c]=='+'&&r+3<=19&&board[r-1][c]=='+'&&r-1>=1)
{
r+=3;
mark=1;
}
else if(board[r+3][c]=='+'&&r+3<=19&&board[r-1][c]=='+'&&r-1>=1)
{
r-=1;
mark=1;
}
else if(board[r+3][c]==chsper&&board[r+4][c]=='+'&&r+4<=19)
{
r+=4;
mark=1;
}
else if(board[r+3][c]==chsper&&board[r-1][c]=='+'&&board[r+4][c]!=chsper&&r-1>=1&&r+3<=19)
{
r-=1;
mark=1;
}
}
else if(board[r][c]==board[r+1][c+1]&&board[r+1][c+1]==board[r+2][c+2]&&board[r+2][c+2]==chsper&&r+2<=19&&c+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r+3][c+3]=='+'&&c+3<=19&&r+3<=19&&board[r-1][c-1]=='+'&&c-1>=1&&r-1>=1)
{
r+=3;
c+=3;
mark=1;
}
else if(board[r+3][c+3]=='+'&&c+3<=19&&r+3<=19&&board[r-1][c-1]=='+'&&c-1>=1&&r-1>=1)
{
r-=1;
c-=1;
mark=1;
}
else if(board[r+3][c+3]==chsper&&board[r+4][c+4]=='+'&&r+4<=19&&c+3<=19)
{
r+=4;
c+=4;
mark=1;
}
else if(board[r+3][c+3]==chsper&&board[r-1][c-1]=='+'&&board[r+4][c+4]!=chsper&&r+3<=19&&c+3<=19&&r-1>=1&&c-1>=1)
{
r-=1;
c-=1;
mark=1;
}
}
else if(board[r+2][c]==board[r+1][c+1]&&board[r+1][c+1]==board[r][c+2]&&board[r][c+2]==chsper&&r+2<=19&&c+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r-1][c+3]=='+'&&r-1>=1&&c+3<=19&&board[r+3][c-1]=='+'&&c-1>=1&&r+3<=19)
{
r-=1;
c+=3;
mark=1;
}
else if(board[r-1][c+3]=='+'&&r-1>=1&&c+3<=19&&board[r+3][c-1]=='+'&&c-1>=1&&r+3<=19)
{
r+=3;
c-=1;
mark=1;
}
else if(board[r-1][c+3]==chsper&&board[r-2][c+4]=='+'&&r-2>=1&&c+4<=19)
{
r-=2;
c+=4;
mark=1;
}
else if(board[r+3][c-1]==chsper&&board[r-1][c+3]=='+'&&board[r-2][c+4]!=chsper&&r+3<=19&&c+3<=19&&r-1>=1&&c-1>=1)
{
r-=1;
c+=3;
mark=1;
}
}
}
if(mark==1) break;
}
if(mark==1) break;
}
if(mark==0)
{
do
{
r=rand()%19+1;
c=rand()%19+1;
}while(board[r][c]!='+'||((r-rper>5||rper-r>5)||(c-cper>5||cper-c>5)));
}
else mark=0;
}
else
{
do
{
r=rand()%19+1;
c=rand()%19+1;
}while(board[r][c]!='+'||((r-rper>5||rper-r>5)||(c-cper>5||cper-c>5)));
}
}
3 主函数
在主函数中要控制游戏是否开始、模式选择等。同井字棋游戏一样,将落子函数等嵌套其中。还可以用system(“pause”)和system(“cls”)进行冻屏和清屏,使输出更加有序而简洁。
int main()
{
int start=0,pattern=0;
prtface();
inibrd();
prtbrd();
printf("请选择(1或2):");
while(scanf("%d",&start))
{
if(start==2)
{
printf("游戏结束!\n");
flag=0;
}
else if(start==1)
{
printf(" 1.人机对战\n 2.双人对战\n请选择模式(1或2):");
scanf("%d",&pattern);
if(pattern==1)
{
printf(" 1. C 2. o\n请选择棋子(1或2):");
scanf("%d",&chsnum);
if(chsnum==1)
{
printf("获得先手\n");
chsper=chs_1;
chscom=chs_2;
while(flag==0)
{
game_per();
if(flag!=0) break;
system("cls");
game_com();
}
}
else if(chsnum==2)
{
printf("获得后手\n");
system("pause");
chsper=chs_2;
chscom=chs_1;
while(flag==0)
{
if(count==0)
{
srand(time(NULL));
do
{
r=rand()%19+1;
c=rand()%19+1;
}while(board[r][c]!='+');
}
game_com();
if(flag!=0) break;
system("cls");
game_per();
}
}
if(flag==1)
{
system("cls");
prtbrd();
printf("获胜!\n游戏结束!\n");
flag=0;
count=0;
}
else if(flag==-1)
{
system("cls");
prtbrd();
printf("失败!\n游戏结束!\n");
flag=0;
count=0;
}
}
else if(pattern==2)
{
chsper=chs_1;
chscom=chs_2;
while(flag==0)
{
gamep_p_1();
if(flag!=0) break;
gamep_p_2();
}
if(flag==1)
{
system("cls");
prtbrd();
printf("玩家 1 获胜!\n游戏结束!\n");
flag=0;
count=0;
}
else if(flag==-1)
{
system("cls");
prtbrd();
printf("玩家 2 获胜!\n游戏结束!\n");
flag=0;
count=0;
}
}
}
system("pause");
system("cls");
prtface();
inibrd();
prtbrd();
printf("请选择(1或2):");
}
return 0;
}
编译运行
编译运行结果视频链接:
https://b23.tv/tEamCN
源代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define Row 20
#define Col 20
int i,j,r,c,flag=0,chsnum=0,count=0,mark=0;
char chs_1='C',chs_2='O',chsper,chscom,chs='\0';
char board[Row][Col];
//打印界面
void prtface_1()
{
for(i=0;i<Row;i++)
{
if(i==0) printf("\n");
printf("*");
if(i==Row-1) printf("\n");
}
}
void prtface_2()
{
for(i=0;i<5;i++) printf(" ");
}
void prtface()
{
prtface_1();
prtface_2();
printf(" 五子棋 ");
prtface_2();
printf("\n");
prtface_2();
printf("1. 开始游戏");
prtface_2();
printf("\n");
prtface_2();
printf("2. 结束游戏");
prtface_2();
prtface_1();
}
//初始化棋盘
void inibrd()
{
for(i=0;i<Row;i++)
for(j=0;j<Col;j++)
if(i==0) board[i][j]='-';
else if(j==0) board[i][j]='|';
else board[i][j]='+';
}
//打印棋盘
void prtbrd()
{
for(i=0;i<Row+1;i++)
{
if(i==0)
for(j=0;j<Col+1;j++)
{
if(j==0) printf(" ");
else printf("%-3d",j-1);
if(j==Col) printf("\n");
}
else
for(j=0;j<Col+1;j++)
{
if(j==0) printf("%-3d",i-1);
else printf("%-3c",board[i-1][j-1]);
if(j==Col) printf("\n");
}
}
}
//判断胜负
void judge()
{
int row=0,col=0,rflag=0,cflag=0;
rflag=r;
cflag=c;
for(r=1;r<Row-1;r++)
{
for(c=1;c<Col-1;c++)
{
if(r>15&&c>15) continue;
else
{
row=r;
col=c;
if(board[row][col]==chs_1||board[row][col]==chs_2)
{
chs=board[row][col];
for(i=0,j=0;i<4;i++)
if (board[r][++c]==chs&&c<=19) j++;
if (j==4&&chs==chsper) flag=1;
else if(j==4&&chs==chscom) flag=-1;
r=row;
c=col;
for(i=0,j=0;i<4;i++)
if (board[++r][c]==chs&&r<=19) j++;
if(j==4&&chs==chsper) flag=1;
else if(j==4&&chs==chscom) flag=-1;
r=row;
c=col;
for(i=0,j=0;i<4;i++)
if (board[++r][++c]==chs&&r<=19&&c<=19) j++;
if (j==4&&chs==chsper) flag=1;
else if(j==4&&chs==chscom) flag=-1;
}
if(board[row+4][col]==chs_1||board[row+4][col]==chs_2)
{
r=row+4;
c=col;
chs=board[row+4][col];
for(i=0,j=0;i<4;i++)
if (board[--r][++c]==chs&&r>=1&&c<=19) j++;
if (j==4&&chs==chsper) flag=1;
else if(j==4&&chs==chscom) flag=-1;
}
r=row;
c=col;
}
}
}
r=rflag;
c=cflag;
}
//开始游戏
//玩家落子
void game_per()
{
int rcom=0,ccom=0;
rcom=r;
ccom=c;
count++;
if(chsnum==2)
{
prtbrd();
printf("电脑落子(r,c)%c:%d %d\n",chscom,rcom,ccom);
}
printf("请落子(r,c) %c:",chsper);
scanf("%d%d",&r,&c);
while(r>19||c>19||board[r][c]!='+')
{
printf("输入错误!\n请落子(r,c) %c:",chsper);
scanf("%d%d",&r,&c);
}
board[r][c]=chsper;
prtbrd();
judge();
}
//电脑落子判断
void comchs()
{
int rper=0,cper=0,chstime=0;
rper=r;
cper=c;
srand(time(NULL));
if(count>=6)
{
for(r=1;r<Row-1;r++)
{
for(c=1;c<Col-1;c++)
{
if(r>16&&c>16 ) continue;
else
{
if(board[r][c]==board[r][c+1]&&board[r][c+1]==board[r][c+2]&&board[r][c+2]==chsper&&c+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r][c+3]=='+'&&c+3<=19&&board[r][c-1]=='+'&&c-1>=1)
{
c+=3;
mark=1;
}
else if(board[r][c+3]=='+'&&c+3<=19&&board[r][c-1]=='+'&&c-1>=1)
{
c-=1;
mark=1;
}
else if(board[r][c+3]==chsper&&board[r][c+4]=='+'&&c+4<=19)
{
c+=4;
mark=1;
}
else if(board[r][c+3]==chsper&&board[r][c-1]=='+'&&board[r][c+4]!=chsper&&c-1>=1&&c+3<=19)
{
c-=1;
mark=1;
}
}
else if(board[r][c]==board[r+1][c]&&board[r+1][c]==board[r+2][c]&&board[r+2][c]==chsper&&r+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r+3][c]=='+'&&r+3<=19&&board[r-1][c]=='+'&&r-1>=1)
{
r+=3;
mark=1;
}
else if(board[r+3][c]=='+'&&r+3<=19&&board[r-1][c]=='+'&&r-1>=1)
{
r-=1;
mark=1;
}
else if(board[r+3][c]==chsper&&board[r+4][c]=='+'&&r+4<=19)
{
r+=4;
mark=1;
}
else if(board[r+3][c]==chsper&&board[r-1][c]=='+'&&board[r+4][c]!=chsper&&r-1>=1&&r+3<=19)
{
r-=1;
mark=1;
}
}
else if(board[r][c]==board[r+1][c+1]&&board[r+1][c+1]==board[r+2][c+2]&&board[r+2][c+2]==chsper&&r+2<=19&&c+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r+3][c+3]=='+'&&c+3<=19&&r+3<=19&&board[r-1][c-1]=='+'&&c-1>=1&&r-1>=1)
{
r+=3;
c+=3;
mark=1;
}
else if(board[r+3][c+3]=='+'&&c+3<=19&&r+3<=19&&board[r-1][c-1]=='+'&&c-1>=1&&r-1>=1)
{
r-=1;
c-=1;
mark=1;
}
else if(board[r+3][c+3]==chsper&&board[r+4][c+4]=='+'&&r+4<=19&&c+3<=19)
{
r+=4;
c+=4;
mark=1;
}
else if(board[r+3][c+3]==chsper&&board[r-1][c-1]=='+'&&board[r+4][c+4]!=chsper&&r+3<=19&&c+3<=19&&r-1>=1&&c-1>=1)
{
r-=1;
c-=1;
mark=1;
}
}
else if(board[r+2][c]==board[r+1][c+1]&&board[r+1][c+1]==board[r][c+2]&&board[r][c+2]==chsper&&r+2<=19&&c+2<=19)
{
chstime=rand()%2+1;
if(chstime==1&&board[r-1][c+3]=='+'&&r-1>=1&&c+3<=19&&board[r+3][c-1]=='+'&&c-1>=1&&r+3<=19)
{
r-=1;
c+=3;
mark=1;
}
else if(board[r-1][c+3]=='+'&&r-1>=1&&c+3<=19&&board[r+3][c-1]=='+'&&c-1>=1&&r+3<=19)
{
r+=3;
c-=1;
mark=1;
}
else if(board[r-1][c+3]==chsper&&board[r-2][c+4]=='+'&&r-2>=1&&c+4<=19)
{
r-=2;
c+=4;
mark=1;
}
else if(board[r+3][c-1]==chsper&&board[r-1][c+3]=='+'&&board[r-2][c+4]!=chsper&&r+3<=19&&c+3<=19&&r-1>=1&&c-1>=1)
{
r-=1;
c+=3;
mark=1;
}
}
}
if(mark==1) break;
}
if(mark==1) break;
}
if(mark==0)
{
do
{
r=rand()%19+1;
c=rand()%19+1;
}while(board[r][c]!='+'||((r-rper>5||rper-r>5)||(c-cper>5||cper-c>5)));
}
else mark=0;
}
else
{
do
{
r=rand()%19+1;
c=rand()%19+1;
}while(board[r][c]!='+'||((r-rper>5||rper-r>5)||(c-cper>5||cper-c>5)));
}
}
//电脑落子
void game_com()
{
int rper=0,cper=0;
rper=r;
cper=c;
count++;
comchs();
board[r][c]=chscom;
prtbrd();
if(chsnum==1) printf("您落子(r,c) %c:%d %d\n",chsper,rper,cper);
printf("电脑落子(r,c)%c:%d %d\n",chscom,r,c);
printf("落子数:%d\n",count);
judge();
}
//双人落子
void gamep_p_1()
{
prtbrd();
printf("落子数:%d\n",count);
printf("玩家 1 落子(r,c)%c:",chsper);
scanf("%d %d",&r,&c);
count++;
while(r>19||c>19||board[r][c]!='+')
{
printf("输入错误!\n玩家 1 落子(r,c) %c:",chsper);
scanf("%d%d",&r,&c);
}
board[r][c]=chsper;
judge();
system("cls");
printf("玩家 1 落子(r,c)%c: %d %d\n",chsper,r,c);
}
void gamep_p_2()
{
prtbrd();
printf("落子数:%d\n",count);
printf("玩家 2 落子(r,c)%c:",chscom);
scanf("%d %d",&r,&c);
count++;
while(r>19||c>19||board[r][c]!='+')
{
printf("输入错误!\n玩家 2 落子(r,c) %c:",chsper);
scanf("%d%d",&r,&c);
}
board[r][c]=chscom;
judge();
system("cls");
printf("玩家 2 落子(r,c)%c: %d %d\n",chscom,r,c);
}
int main()
{
int start=0,pattern=0;
prtface();
inibrd();
prtbrd();
printf("请选择(1或2):");
while(scanf("%d",&start))
{
if(start==2)
{
printf("游戏结束!\n");
flag=0;
}
else if(start==1)
{
printf(" 1.人机对战\n 2.双人对战\n请选择模式(1或2):");
scanf("%d",&pattern);
if(pattern==1)
{
printf(" 1. C 2. o\n请选择棋子(1或2):");
scanf("%d",&chsnum);
if(chsnum==1)
{
printf("获得先手\n");
chsper=chs_1;
chscom=chs_2;
while(flag==0)
{
game_per();
if(flag!=0) break;
system("cls");
game_com();
}
}
else if(chsnum==2)
{
printf("获得后手\n");
system("pause");
chsper=chs_2;
chscom=chs_1;
while(flag==0)
{
if(count==0)
{
srand(time(NULL));
do
{
r=rand()%19+1;
c=rand()%19+1;
}while(board[r][c]!='+');
}
game_com();
if(flag!=0) break;
system("cls");
game_per();
}
}
if(flag==1)
{
system("cls");
prtbrd();
printf("获胜!\n游戏结束!\n");
flag=0;
count=0;
}
else if(flag==-1)
{
system("cls");
prtbrd();
printf("失败!\n游戏结束!\n");
flag=0;
count=0;
}
}
else if(pattern==2)
{
chsper=chs_1;
chscom=chs_2;
while(flag==0)
{
gamep_p_1();
if(flag!=0) break;
gamep_p_2();
}
if(flag==1)
{
system("cls");
prtbrd();
printf("玩家 1 获胜!\n游戏结束!\n");
flag=0;
count=0;
}
else if(flag==-1)
{
system("cls");
prtbrd();
printf("玩家 2 获胜!\n游戏结束!\n");
flag=0;
count=0;
}
}
}
system("pause");
system("cls");
prtface();
inibrd();
prtbrd();
printf("请选择(1或2):");
}
return 0;
}
总结
1、运行结果较清晰也较理想,但仍有瑕疵。视频中可以看出该算法是有bug的,也很难和真人下棋相比较。
2、代码颇为冗长,目前能力有限,只能如此。