五子棋判输赢
题目描述
在一个N×N的棋盘上下五子棋。给定对弈双方的落子序列 (x0, y0), (x1, y1), ..., (xn, yn),判断走到多少步时,哪方获胜。
关于输入
第一行有两个整数,棋盘的边长N和落子序列的长度n。
其余各行每行两个数字,分别为横、纵坐标,且第二、四、六……行为黑方落子的位置,第三、五、七……行为白方落子的位置。
输入一定是合理的,而且一定能分出输赢;但可能因为在满足输赢条件时,对弈双方没有看出输赢,而多行了数步。
关于输出
输出为一行,包含两个整数,第一个数是判断出输赢时行棋的步数,第二个数表示获胜方:0代表黑方获胜;1代表白方获胜。
例子输入
10 12 0 0 1 0 0 1 2 0 0 2 3 0 0 3 4 0 0 4 5 0 0 5 6 0
例子输出
9 0
提示信息
五子棋规则比较复杂,这里我们只要求黑棋先行,谁先连出5连子就算赢,不管是否出现规则约束的禁手。
解题分析
本题是一道对二维数组进行查询和操作的题目,并且引入了五子棋游戏的规则,较为新颖。一个比较直观的想法就是,我们每次都落子,每次落完子后,去看看这个落下的子的上下左右左上右上左下右下能不能连成一个五个同色的棋子,如果能,那么赢家就是这时落子的玩家,并且输出此时行棋的步数,然而,这个听起来容易,做起来却并不是那么简单,我们如何去模拟这个过程?其实,我们可以用dx,dy数组,通过两层循环来模拟这个过程(第一层用于判断我们要判断哪个方向;第二层用于这个方向上的遍历判断,这个也不难理解)。(此外还需注意一些数数的变量更新应该放在循环的内部)。
代码实现
#include <bits/stdc++.h>
using namespace std;
const int dx[4]={1,0,1,1};
const int dy[4]={0,1,1,-1};
bool check(vector<vector<int>> &board,int x,int y, int player,int N){
int nx,ny;
for(int i=0;i<4;i++){
int cnt=0;
for(int j=-4;j<=4;j++){
nx=x+dx[i]*j; ny=y+dy[i]*j;
if(nx>=0 && ny>=0 && nx<N && ny<N
&& board[nx][ny]==player){
cnt++;
if(cnt==5) return 1;
}
else{
cnt=0;
}
}
}
return 0;
}
int main(){
int N,n; cin>>N>>n; int x,y;
int step=-1,winner=-1;
vector<vector<int>> board(N,vector<int>(N,-1));
for(int i=0;i<n;i++){
cin>>x>>y;
board[x][y]=i%2;
if(check(board,x,y,i%2,N)){
winner=i%2; step=i+1;
break;
}
}
cout<<step<<" "<<winner<<endl;
}