看前须知
第二次上机题汇总
题目内容
问题描述
已知两人分别执白棋和黑棋在一个围棋棋盘上下五子棋,若同一颜色的棋子在同一条横行、纵行或斜线上连成5个棋子,则执该颜色棋子的人获胜。编写程序读入某一时刻下棋的状态,并判断是否有人即将获胜,即:同一颜色的棋子在同一条横行、纵列或斜线上连成4个棋子,且该4个棋子的两端至少有一端为空位置。
输入的棋盘大小是19×19,用数字0表示空位置(即没有棋子),用数字1表示该位置下了一白色棋子,用数字2表示该位置下了一黑色棋子。假设同一颜色的棋子在同一条横行、纵列或斜线上连成的棋子个数不会超过4个,并且最多有一人连成线的棋子个数为4。
输入形式
从控制台输入用来表示棋盘状态的数字0、1或2;每行输入19个数字,各数字之间以一个空格分隔,每行最后一个数字后没有空格;共输入19行表示棋盘状态的数字。
输出形式
若有人即将获胜,则先输出即将获胜人的棋子颜色(1表示白色棋子,2表示黑色棋子),然后输出英文冒号:,最后输出连成4个棋子连线的起始位置(棋盘横行自上往下、纵列自左往右从1开始计数,横行最小的棋子在棋盘上的横行数和纵列数作为连线的起始位置,若在同一行上,则纵列数最小的棋子位置作为起始位置,两数字之间以一个英文逗号,作为分隔符)。
若没有人获胜,则输出英文字符串:No。
无论输出什么结果,最后都要有回车换行符。
样例
【输入样例1】
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 0 1 1 2 0 0 0 0 0 0 0
0 0 0 0 0 2 1 1 1 1 2 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 2 2 0 0 0 0 0 0 0 0
0 0 0 0 0 2 0 1 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
【输出样例1】
1:9,8
【输入样例2】
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
【输出样例2】
No
样例说明
在输入的样例1中,执白棋(数字1表示)的人即将获胜,连成4个棋子且有一端为空的起始位置在第9行第8列,所以输出1:9,8。
在输入的样例2中,还没有同一颜色的棋子连成4个,所以无人即将获胜,直接输出No。
题解
易错点和难点
这道题就是在考察简单的搜索算法。根据题意,在一般情况我们需要对一个棋子的右,右下,下,左下四个方向进行搜索,一旦有一个是满足的立刻break出来。但是要特殊处理棋子在最左边和左右边的情况,因为在此刻只需要对三个方向甚至只有两个方向进行搜索,否则会因为数组越界而WA。
参考代码
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>
#define right 3 //宏定义方向
#define right_down 4
#define down 5
#define left_down 6
int q[30][30]; //棋盘
int i=0,j=0;
int flag=0; //判断标志
void search(int q[][30]); //搜索函数
void move(int m,int num); //搜索方向
int main()
{
for(i=1;i<=19;i++)
{
for(j=1;j<=19;j++)
{
scanf("%d",&q[i][j]);//输入当前棋盘
}
}
i=1,j=1;
search(q); //开始搜索
if(flag==1)
{
printf("%d:%d,%d",flag,i,j);
}
else if(flag==2)
{
printf("%d:%d,%d",flag,i,j);
}
else
{
printf("No");
}
return 0;
}
void move(int m,int num)
{
if(m==3) //right
{
if(q[i][j+1]==num && q[i][j+2]==num && q[i][j+3]==num && (q[i][j+4]==0 || q[i][j-1]==0)) //0表示有可以下棋的位置
{
flag=num;
}
}
else if(m==4) //right_down
{
if(q[i+1][j+1]==num && q[i+2][j+2]==num && q[i+3][j+3]==num && (q[i+4][j+4]==0 || q[i-1][j-1]==0))//0表示有可以下棋的位置
{
flag=num;
}
}
else if(m==5) //down
{
if(q[i+1][j]==num && q[i+2][j]==num && q[i+3][j]==num && (q[i+4][j]==0 || q[i-1][j]==0))//0表示有可以下棋的位置
{
flag=num;
}
}
else if(m==6) //left_down
{
if(q[i+1][j-1]==num && q[i+2][j-2]==num && q[i+3][j-3]==num && (q[i+4][j-4]==0 || q[i-1][j+1]==0))//0表示有可以下棋的位置
{
flag=num;
}
}
}
void search(int q[][30])
{
for(i=1;i<=19;i++)
{
for(j=1;j<=19;j++)
{
if(q[i][j]==1)
{
if(j==1) //如果在最左边
{
move(right,1);
move(right_down,1);
move(down,1);
if(flag!=0) break;
}
else if(j==19) //如果在最右边
{
move(left_down,1);
move(down,1);
if(flag!=0) break;
}
else //其余情况
{
move(right,1);
move(right_down,1);
move(down,1);
move(left_down,1);
if(flag!=0) break;
}
}
if(q[i][j]==2) //与重复上面步骤
{
if(j==1)
{
move(right,2);
move(right_down,2);
move(down,2);
if(flag!=0) break;
}
else if(j==19)
{
move(left_down,2);
move(down,2);
if(flag!=0) break;
}
else
{
move(right,2);
move(right_down,2);
move(down,2);
move(left_down,2);
if(flag!=0) break;
}
}
}
if(flag!=0) break;
}
}
补充测试的数据
输入
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
输出
2:1,19