计蒜客——五子棋

五子棋

计蒜之道程序设计大赛已经迎来了第六届,蒜头君很开心,决定带上好友们一起下一把 五子棋,并由自己来担任裁判。五子棋的规则为:双方分别使用黑白两色的棋子,每次 落子(放置一个己方颜色的棋子),放在棋盘直线与横线的交叉点上,一方先形成至少五个己方颜色棋子连成一线者获胜。黑色棋子先手(第一个放置的棋子颜色一定是黑色)。

在这里,没有任何禁手的限制(如果你不清楚禁手是什么,可以忽略这句话)。也就意味着,当一方出现六子连珠或更多己方棋子连成一条线时,也算这方胜利。

当一方将要落子,且有至少一处落子后可让自己的 至少五个 棋子连成一线(横着、竖着或斜着),则说明一方 将要获胜。蒜头君作为裁判,需要时刻判断是否有一方 将要获胜,你能帮蒜头君借助编程解决这个问题吗?

五子棋盘的大小固定为 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值