UVA 220 Othello(模拟)
输入:
第一行游戏场次
接下来八行输入8*8的棋盘 :-空 B黑子 W白子
输入当前是谁的回合
L显示当前回合玩家能够下的位置M表示下子
Q结束当前游戏
输出:
L:当前能下点的坐标
M:黑子白子的个数
Q:输出最后的棋局
1.当前能下的位置:
先确定当前是谁的回合,然后
每个点扫描,检查是否符合条件,如果符合条件把这个点的坐标输出:
检查是否符合条件(x,y,假设当前回合是B){//这个位置能否下子
当前位置是否是空白 如果不是直接返回false
检查8个方向是否有W子,如果没有肯定不符合,
如果有,沿着当前方向继续检查,直至遇到B,或者空白,或者出界:
如果是B return true;
else if(空白或者出界) return false;
else 沿这个方向继续检查
}
2.下子:
先确定当前位置是否能够下子,如果不能直接返回false
否则,沿着8个方向检查,如果当前方向可行,先打上标记,
8个方向都检查结束,然后一起改变颜色(检查完一个方向就改变,可能其他方向的检查就会出问题)
如果当前用户没有地方能够下子:
直接切换成另个一人,并且变为他下子(假定下一次是可以下子的)
每个人下完子之后都要换人。
注意:
1.输出格式 黑白子个数占两位
2.如果当前用户没有一个能下的位置,换人,并且还在这个位置下子(题目保证换人之后能下),
下完之后换人
3.如果当前用户能下,下完之后换人
4.模拟
#include <iostream> #include <cstdio> #include <cstring> using namespace std; char g[9][9];//下标从1开始 int dir[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};//8个探测的方向 int cur;//当前回合的玩家:0表示B 1表示W void print(){ for(int i=1;i<=8;i++){ for(int j=1;j<=8;j++){ cout<<g[i][j]; } cout<<endl; } } bool isOut(int x,int y){//检查当前点是否出界 return x<1||x>8||y<1||y>8; } bool check(int x,int y){//检查当前位置,对于当前玩家而言是否是合法的下子点 if(g[x][y]!='-') return false; int i; for(i=0;i<8;i++){ int nx = x+dir[i][0]; int ny = y+dir[i][1]; if(!isOut(nx,ny)&&(cur==0&&g[nx][ny]=='W'||cur==1&&g[nx][ny]=='B')){ while(true){//沿着当前方向检查能否遇到下一个子完成封闭 nx+=dir[i][0]; ny+=dir[i][1]; if(isOut(nx,ny)) break;//出界都没有遇到 if(g[nx][ny]=='-') break;//第一个遇到的是空白位置 if(cur==0&&g[nx][ny]=='W'||cur==1&&g[nx][ny]=='B') continue;//遇到的还是被封闭的子继续查找 if(cur==0&&g[nx][ny]=='B'||cur==1&&g[nx][ny]=='W') return true;//完成封闭 } }else{ continue; } } return false;//8个方向没有一个可以构成封闭 } bool noWay(){//检查当前玩家是否没有可下子的点 bool Find = false; int i,j; for(i=1;i<=8;i++){ for(j=1;j<=8;j++){ //cout<<i<<" "<<j<<" "<<check(i,j)<<endl; if(check(i,j)){ return false; } } } return true; } void ListAll(){//显示当前玩家所有可以下子的点 int first = 1; bool Find = false; int i,j; for(i=1;i<=8;i++){ for(j=1;j<=8;j++){ //cout<<i<<" "<<j<<" "<<check(i,j)<<endl; if(check(i,j)){ Find = true; if(first) first=0; else cout<<" "; cout<<"("<<i<<","<<j<<")"; } } } if(!Find) cout<<"No legal move."<<endl; else cout<<endl; } void change(int x,int y){//假定当前位置是能够下子的位置,然后修改所有被封闭的点 bool flag; int conv[9][9]; memset(conv,0,sizeof(conv)); int i,j; for(i=0;i<8;i++){ int nx = x+dir[i][0]; int ny = y+dir[i][1]; if(!isOut(nx,ny)&&(cur==0&&g[nx][ny]=='W'||cur==1&&g[nx][ny]=='B')){ flag = false; while(true){//沿着当前方向检查能否遇到下一个子完成封闭 nx+=dir[i][0]; ny+=dir[i][1]; if(isOut(nx,ny)) break;//出界都没有遇到 if(g[nx][ny]=='-') break;//第一个遇到的是空白位置 if(cur==0&&g[nx][ny]=='W'||cur==1&&g[nx][ny]=='B') continue;//遇到的还是被封闭的子继续查找 if(cur==0&&g[nx][ny]=='B'||cur==1&&g[nx][ny]=='W') {flag = true;break;}//完成封闭 } if(flag){ nx = x+dir[i][0]; ny = y+dir[i][1]; while(true){//添加修改标志 if(cur==0&&g[nx][ny]=='B'||cur==1&&g[nx][ny]=='W') break;//完成封闭 conv[nx][ny] = 1; nx+=dir[i][0]; ny+=dir[i][1]; } } } } for(i=1;i<=8;i++){ for(j=1;j<=8;j++){ if(conv[i][j]==1){ if(cur==0){ g[i][j] = 'B'; }else{ g[i][j] = 'W'; } } } } g[x][y]=cur==0?'B':'W';//下子 } int main() { char c; int Case; char order[5]; int i,j; int first = 1; cin>>Case; while(Case--){ if(first) first=0; else cout<<endl; for(i=1;i<=8;i++){ for(j=1;j<=8;j++){ cin>>g[i][j]; } } cin>>c; if(c=='B') cur = 0; else cur = 1; while(true){ cin>>order; if(order[0]=='Q'){ print(); break; }else if(order[0]=='L'){ ListAll(); }else{ int x = order[1]-48; int y = order[2]-48; if(noWay()){ cur = !cur;//如果没有地方可以下直接切换,变成另一个人在这个位置下子 change(x,y); cur = !cur; }else{ if(check(x,y)){ change(x,y); cur = !cur; }else{//有可以下子的地方,但是当前下子的地方是不合法的。 ; } } int bnum = 0; int wnum = 0; for(i=1;i<=8;i++){ for(j=1;j<=8;j++) if(g[i][j]=='B') bnum++; else if(g[i][j]=='W') wnum++; } printf("Black - %2d White - %2d\n",bnum,wnum);//输出格式 PE //cout<<"Black - "<<bnum<<" White - "<<wnum<<endl; } } } return 0; }