题意:五子棋,在一个10*10的棋盘上下一个棋子,看是否能连成五个。
思路:先写一个遍历棋盘的双循环,如果发现不是“O”,就进入深搜,每进入一次将标记数组清零。然后八个方向去找是否能连起来,找到一个就加1,找不到就返回。最后等于5时就输出“YES”,反之,输出“No”。
注意:和一般搜索不一样的是遍历的方向。在判断条件里判断此次的方向是否和上次的相同。
代码:
#include<stdio.h>
#include<string.h>
int a[8]= {-1,-1,0,1,1,1,0,-1},b[8]= {0,1,1,1,0,-1,-1,-1},k;
int lu[11][11];
char Map[11][11];
int range(int x,int y)//判断是否在范围内。
{
if(x>=0&&x<10&&y<10&&y>=0)return 1;
else return 0;
}
void dfs(int x,int y,int direction_x,int direction_y,int chessman,int play)
{
int w;
lu[x][y]=1;//标记走过的路。
if(Map[x][y]=='.')//进入后发现为‘.’是,将play的值变为1;
play=1;
if(chessman>=4)//相连的棋子够5个后,标记并返回。
{
//printf("***\n");
k=1;
return ;
}
if(direction_x==0&&direction_y==0)//第一次进入方向定义为0,0,这时用w来标记。
w=1;
else w=0;
if(k)return ;
for(int i=0; i<8; i++)//八个方向,也可以定义到一个二维数组里。
{
int dx=x+a[i];
int dy=y+b[i];
if(w)direction_x=a[i],direction_y=b[i];//如果是第一次让方向和找的方向相同。
if(range(dx,dy)&&!lu[dx][dy]&&direction_x==a[i]&&direction_y==b[i]&&Map[dx][dy]=='X')
//判断是否在范围内,是否被标记过,这次的方向是否和上次的一样,以及是否是‘X’。
//符合条件的话,chessman加一。
dfs(dx,dy,a[i],b[i],chessman+1,play);
else if(range(dx,dy)&&!lu[dx][dy]&&direction_x==a[i]&&direction_y==b[i]&&Map[dx][dy]=='.'&&!play)
//判断是否在范围内,是否被标记过,这次的方向是否和上次的一样,以及是否是‘.’。
//符合条件的话,play=1,chessman加一。
dfs(dx,dy,a[i],b[i],chessman+1,play+1);
}
}
int main()
{
int i,j;
while(~scanf("%s",Map[0]))
{
for(i=1; i<10; i++)
scanf("%s",Map[i]);
for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
if(Map[i][j]=='X'||Map[i][j]=='.')
{
k=0;
memset(lu,0,sizeof(lu));//每找一次就把标记数组清零。
dfs(i,j,0,0,0,0);
}
if(k)break;
}
if(k)break;
}
if(k)printf("YES\n");
else printf("NO\n");
}
}