五子棋
计蒜之道程序设计大赛已经迎来了第六届,蒜头君很开心,决定带上好友们一起下一把 五子棋,并由自己来担任裁判。五子棋的规则为:双方分别使用黑白两色的棋子,每次 落子(放置一个己方颜色的棋子),放在棋盘直线与横线的交叉点上,一方先形成至少五个己方颜色棋子连成一线者获胜。黑色棋子先手(第一个放置的棋子颜色一定是黑色)。
在这里,没有任何禁手的限制(如果你不清楚禁手是什么,可以忽略这句话)。也就意味着,当一方出现六子连珠或更多己方棋子连成一条线时,也算这方胜利。
当一方将要落子,且有至少一处落子后可让自己的 至少五个 棋子连成一线(横着、竖着或斜着),则说明一方 将要获胜。蒜头君作为裁判,需要时刻判断是否有一方 将要获胜,你能帮蒜头君借助编程解决这个问题吗?
五子棋盘的大小固定为 25 \times 2525×25,保证仍有可以落子的位置。
输入格式
输入 2525 行,每行 2525 个字符,其中 . 表示未落子(没有放置任何棋子),o 表示放置了白色棋子,x 表示放置了黑色棋子。
输出格式
输出若干行。如果当前要落子的一方没有将要获胜,则输出 tie;否则输出所有能使得当前要落子的一方将要获胜的落地位置,每行输出一个位置信息,坐标的两个值之间用一个空格分隔。
具体位置信息的表示方式可参考样例输出及样例说明,如有多个位置可使得当前要落子的一方即将获胜,则按照字典序依次输出。不要输出任何多余的内容。
样例输入1 复制
…
…
…
…
…
…
…o…
…o…
…x.o…
…x…o…
…x…
…x…
…
…
…
…
…
…
…
…
…
…
…
…
…
样例输出1 复制
7 10
12 5
样例解释1
黑子即将落子,此时将黑子落在 (7,10)(7,10) 和 (12,5)(12,5) 这两个位置可以使得黑方获胜。
棋盘左上角的坐标为 (0,0)(0,0),从左上开始数,第 xx 行 yy 列的坐标为 (x-1,y-1)(x−1,y−1)。
按照字典序输出,即意味着坐标第一个值更小的先输出;第一个值相同时,第二个值更小的先输出。
样例输入2 复制
…
…
…
…
…
…
…o…
…x.o…
…x.o…
…o…
…x…
…x…
…
…
…
…
…
…
…
…
…
…
…
…
…
样例输出2 复制
tie
样例解释2
虽然白方还有一个子就可以“五子连珠”,但此时该黑方落子,黑方并不即将获胜,因此输出 tie。
题目来源
2020 计蒜之道 预赛 第一场
将每种不同的连珠分开求解,函数中的重复代码有点多可能有方法简化。。。
#include<iostream>
#include<memory.h>
using namespace std;
const int n=25;
int map[n][n];
int a[n][n];
int chess=0;//指示要下黑棋还是白棋
struct Ans{
int x,y;
}ans[n*n];
int num=0;
void pushans(int x,int y)
{
for(int i=0;i<num;i++)
if(ans[i].x==x&&ans[i].y==y)
return;
ans[num].x=x;
ans[num].y=y;
num++;
}
void search_row()//寻找一行的合适点
{
memset(a,0,sizeof(a));
int temp=0;
for(int i=0;i<n;i++)
{
temp=0;
for(int j=0;j<n;j++)
{
if(map[i][j]==0){a[i][j]+=temp;temp=0;}
else if(map[i][j]==chess)temp++;
else temp=0;
}
temp=0;
for(int j=n-1;j>=0;j--)
{
if(map[i][j]==0){a[i][j]+=temp;temp=0;}
else if(map[i][j]==chess)temp++;
else temp=0;
if(a[i][j]>=4) pushans(i,j);
}
}
}
void search_col()//寻找一列的合适点
{
memset(a,0,sizeof(a));
int temp=0;
for(int j=0;j<n;j++)
{
temp=0;
for(int i=0;i<n;i++)
{
if(map[i][j]==0){a[i][j]+=temp;temp=0;}
else if(map[i][j]==chess)temp++;
else temp=0;
}
temp=0;
for(int i=n-1;i>=0;i--)
{
if(map[i][j]==0){a[i][j]+=temp;temp=0;}
else if(map[i][j]==chess)temp++;
else temp=0;
if(a[i][j]>=4) pushans(i,j);
}
}
}
void search_DR()//斜向右下
{
int temp=0;
memset(a,0,sizeof(a));
int x=0,y=0;
for(int i=-(n-1);i<n;i++)
{
temp=0;
for(int k=0;k<n;k++)
{
x=i+k;y=k;
if(x<0||y<0||x>=n||y>=n)continue;
if(map[x][y]==0){a[x][y]+=temp;temp=0;}
else if(map[x][y]==chess)temp++;
else temp=0;
}
temp=0;
for(int k=n-1;k>=0;k--)
{
x=i+k;y=k;
if(x<0||y<0||x>=n||y>=n)continue;
if(map[x][y]==0){a[x][y]+=temp;temp=0;}
else if(map[x][y]==chess)temp++;
else temp=0;
if(a[x][y]>=4) pushans(x,y);
}
}
}
void search_DL()//斜向左下
{
int temp=0;
memset(a,0,sizeof(a));
int x=0,y=0;
for(int i=-(n-1);i<n;i++)
{
temp=0;
for(int k=0;k<n;k++)
{
x=i+k;y=n-1-k;
if(x<0||y<0||x>=n||y>=n)continue;
if(map[x][y]==0){a[x][y]+=temp;temp=0;}
else if(map[x][y]==chess)temp++;
else temp=0;
}
temp=0;
for(int k=n-1;k>=0;k--)
{
x=i+k;y=n-1-k;
if(x<0||y<0||x>=n||y>=n)continue;
if(map[x][y]==0){a[x][y]+=temp;temp=0;}
else if(map[x][y]==chess)temp++;
else temp=0;
if(a[x][y]>=4) pushans(x,y);
}
}
}
int main()
{
char temp;
int black=0,white=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>temp;
if(temp=='.')map[i][j]=0;
else if(temp=='x'){map[i][j]=1;black++;}
else {map[i][j]=2;white++;}
}
}
if(black==white)chess=1;
else chess=2;
search_row();
search_col();
search_DR();
search_DL();
for(int i=0;i<num-1;i++)
{
for(int j=i+1;j<num;j++)
{
if(ans[i].x>ans[j].x){
int temp=ans[i].x;
ans[i].x=ans[j].x;
ans[j].x=temp;
temp=ans[i].y;
ans[i].y=ans[j].y;
ans[j].y=temp;
}
else if(ans[i].x==ans[j].x&&ans[i].y>ans[j].y)
{
int temp=ans[i].x;
ans[i].x=ans[j].x;
ans[j].x=temp;
temp=ans[i].y;
ans[i].y=ans[j].y;
ans[j].y=temp;
}
}
}
if(num){
for(int i=0;i<num;i++)
{
cout<<ans[i].x<<' '<<ans[i].y<<endl;
}
}
else cout<<"tie"<<endl;
return 0;
}