这道题需要好好总结一下:因为虽然一开始我的思路是正确的,但是实现的方法却极其的复杂
先贴上我的代码
//之前的思路是没有问题的,但是在实现上缺乏一点灵活性,没有做到足够的抽象 //需求: //输入 //list当前棋方所有合法的位置(只要有一个方向合法就可以) //move,先判断这个位置+方向是不是合法,如果合法就更新棋盘 //如果想要判断和更新同时进行 //退出这个游戏,并推出棋盘 #include<cstdio> #include<cstring> using namespace std; int kase; int board[10][10]; int flag_W_B;//0是白色,1是黑色 char convert[2]={'W','B'}; int cnt[2]; void print_board() { for(int i=1;i<=8;i++) { for(int j=1;j<=8;j++) { printf("%c",board[i][j]); } printf("\n"); } } void initial() { memset(cnt,0,sizeof(cnt)); char s[10]; for(int i=1;i<=8;i++) { scanf("%s",s); //printf("%s\n",s); for(int j=1;j<=8;j++) { board[i][j]=s[j-1]; if(s[j-1]=='B') { cnt[1]++; } if(s[j-1]=='W') { cnt[0]++; } } } //print_board(); scanf("%s",s); if(s[0]=='W') { flag_W_B=0; } else { flag_W_B=1; } } bool is_in_board(int row,int col) { if(row>=1&&row<=8&&col>=1&&col<=8) return true; return false; } bool is_valid(int turn ,int row,int col,int flag)//flag是0就只需要判断是不是合法就可以,是1就需要更新棋盘 { if(turn==1)//往上走 { row=row-1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);row--)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { board[row][col]=convert[flag_W_B]; cnt[flag_W_B]++; cnt[!flag_W_B]--; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==5)//往下走 { row=row+1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);row++)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==3)//往右走 { col=col+1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);col++)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==7)//往左走 { col=col-1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);col--)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==8)//往左上走 { col=col-1; row=row-1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);col--,row--)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==4)//往右下走 { col=col+1; row=row+1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);col++,row++)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==2)//往右上走 { col=col+1; row=row-1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);col++,row--)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } if(turn==6)//往右上走 { col=col-1; row=row+1; if(!(is_in_board(row,col)&&board[row][col]==convert[!flag_W_B]))//开始的第一个必须是当前的反方,否则就退出 { return false;//如果开始的第一个不满足要求,就说明不满足条件 } for(;is_in_board(row,col);col--,row++)//这里还是从第一个开始的 { if(board[row][col]==convert[!flag_W_B]) { if(flag==1) { cnt[flag_W_B]++; cnt[!flag_W_B]--; board[row][col]=convert[flag_W_B]; } continue;//判断下一个地方 } if(board[row][col]=='-')//如果遇到了'-'说明这个地方不合适 { return false; } if(board[row][col]==convert[flag_W_B])//如果找到了当前的 { return true; } } } return false;//走到这里说明这个方向上全是另外一种颜色 } bool Comd() { char comd[5]; scanf("%s",comd); //printf("comd=%s\n",comd); if(comd[0]=='Q') { print_board(); return false; } if(comd[0]=='L') { int valid=0; for(int i=1;i<=8;i++) { for(int j=1;j<=8;j++) { if(board[i][j]=='-') { for(int turn=1;turn<=8;turn++) { if(is_valid(turn,i,j,0)) { if(valid) printf(" "); printf("(%d,%d)",i,j); valid=1; break;//只要有一个位置合法就退出 } } } } } if(valid==0) { printf("No legal move.\n"); } else { printf("\n"); } } if(comd[0]=='M') { //printf("要开始move\n"); int valid=0; //printf("%d%d\n",comd[1],comd[2]); ///printf("%c\n",board[comd[1]-'0'][comd[2]-'0']); if(board[comd[1]-'0'][comd[2]-'0']) { for(int turn=1;turn<=8;turn++) { //printf("turn=%d\n",turn); if(is_valid(turn,comd[1]-'0',comd[2]-'0',0)) { valid=1; board[comd[1]-'0'][comd[2]-'0']=convert[flag_W_B]; is_valid(turn,comd[1]-'0',comd[2]-'0',1); //print_board(); } } } if(!valid)//八个方向都不是valid的话,就应该换下棋的一方 { flag_W_B=!flag_W_B; for(int turn=1;turn<=8;turn++) { //printf("turn=%d\n",turn); if(is_valid(turn,comd[1]-'0',comd[2]-'0',0)) { board[comd[1]-'0'][comd[2]-'0']=convert[flag_W_B]; is_valid(turn,comd[1]-'0',comd[2]-'0',1); //print_board(); } } } cnt[flag_W_B]++; flag_W_B=!flag_W_B;//最后不管是谁下完,都要交换; printf("Black -%3d White -%3d\n",cnt[1],cnt[0]); } return true; } int main() { #ifdef local freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif scanf("%d",&kase); for(int i=0;i<kase;i++) { if(i) printf("\n"); initial(); while(Comd()); } return 0; }
先来分析一下这个问题:
首先输入这个没有什么好说的
接下来就是三个命令:
第一个是Q,这个最简单,直接把棋盘输出就可以了
第二个是L, 这个是要列出所有合法的位置
第三个是m,即要在棋盘上面走。
我一开始的确想到了要把第二个和第三个结合起来,但是并没有把他们抽象到turn row col的这个程度,所以导致程序不仅长,而且逻辑异常的复杂
这就要求我在接下来的题目中,要好好的抽象出各个函数来,并且抽象的越底层越好。
这道题遇到的bug并不多,基本上是debug才能检查出来的bug