JXUFE紫书第四章习题 C 4-3


注意:
1.输出格式注意 程序结束的结尾换行是否有多 

2.输出黑白棋子数的时候数字%2d输出

3.边界值注意

4.打印所有合法点的时候两点之间有空格 最有一个点输出没有空格


#include <stdio.h>
#include <string.h> 

const int maxn=10;
char board[maxn][maxn];//棋盘信息
int legal[maxn][maxn]; //落子合法位置
int direction[maxn];//八个方向,"米"字形,重左横开始,顺时针方向。
void printdirection(){
    int i;
    for(i=1;i<=8;i++)
        printf("%d ",direction[i]);
    printf("\n");
}
void printlist(){//打印可能位置 
    int i,j;
    int count=0;
    
    for(i=1;i<=8;i++){
        for(j=1;j<=8;j++){
            if(legal[i][j]==1){
                count++;
                if(count==1)
                    printf("(%d,%d)",i,j);
                else//打印有效点的时候每个点之间都有空格,但是最后一个点后面不能有,果断修改,
                    printf(" (%d,%d)",i,j);
            }
        }
    }
    if(count==0)
        printf("No legal move.");
    printf("\n");
} 
void list(char c,int row,int col){//枚举当前棋子的合法位置 
    char other;
    int i,j;
    
    if(c=='B')//确定当前棋子,与对手棋子 
        other='W';
    else
        other='B';
    //“米”字形,八个方位,左横、上竖、右横、下竖、左上斜、右上斜、左下斜、右下斜
    // 左横
    i=row;
    j=col;
    while(j-1>=1&&board[i][j-1]==other)//趟过other棋子,有快速排序代码的一点痕迹 
        j--;
    if(j!=col&&j-1>=1&&board[i][j-1]=='-'){
        j--;
        legal[i][j]=1;
    }
    //右横
    i=row;
    j=col;
    while(j+1<=8&&board[i][j+1]==other)//趟过other棋子
        j++;
    if(j!=col&&j+1<=8&&board[i][j+1]=='-'){
        j++;
        legal[i][j]=1;
    } 
    //上竖
    i=row;
    j=col;
    while(i-1>=1&&board[i-1][j]==other)//趟过other棋子
        i--;
    if(i!=row&&i-1>=1&&board[i-1][j]=='-'){
        i--;
        legal[i][j]=1;
    }
    //下竖
    i=row;
    j=col;
    while(i+1>=1&&board[i+1][j]==other)//趟过other棋子
        i++;
    if(i!=row&&i+1<=8&&board[i+1][j]=='-'){
        i++;
        legal[i][j]=1;
    }
    //左上斜
    i=row;
    j=col;
    while(i-1>=1&&j-1>=1&&board[i-1][j-1]==other){//趟过other棋子
        i--;
        j--;
    }
    if(i!=row&&j!=col&&i-1>=1&&j-1>=1&&board[i-1][j-1]=='-'){
        i--;
        j--;
        legal[i][j]=1;
    }
    //右下斜
    i=row;
    j=col;
    while(i+1<=8&&j+1<=8&&board[i+1][j+1]==other){//趟过other棋子
        i++;
        j++;
    }
    if(i!=row&&j!=col&&i+1<=8&&j+1<=8&&board[i+1][j+1]=='-'){
        i++;
        j++;
        legal[i][j]=1;
    }
    //右上斜
    i=row;
    j=col;
    while(i-1>=1&&j+1<=8&&board[i-1][j+1]==other){
        i--;
        j++;
    }
    if(i!=row&&j!=col&&i-1>=1&&j+1<=8&&board[i-1][j+1]=='-'){
        i--;
        j++;
        legal[i][j]=1;
    }
    //左下斜
    i=row;
    j=col;
    while(i+1<=8&&j-1>=1&&board[i+1][j-1]==other){
        i++;
        j--;
    }
    if(i!=row&&j!=col&&i+1<=8&&j-1>=1&&board[i+1][j-1]=='-'){
        i++;
        j--;
        legal[i][j]=1;
    }
}

void enumdirection(char c,int row,int col){//枚举枚举落子的作用范围 
    char other;
    int i,j;
    memset(direction,0,sizeof(direction));//初始化方向 
    if(c=='B')//确定当前棋子,与对手棋子 
        other='W';
    else
        other='B';
    //“米”字形,八个方位,左横、上竖、右横、下竖、左上斜、右上斜、左下斜、右下斜
    // 左横 米 direction[1]; 
    i=row;
    j=col;
    while(j-1>=1&&board[i][j-1]==other)//趟过other棋子,有快速排序代码的一点痕迹 
        j--;
    if(j!=col&&j-1>=1&&board[i][j-1]==c){
        j--;
        direction[1]=1;
    }
    //右横 米 dirction[5]
    i=row;
    j=col;
    while(j+1<=8&&board[i][j+1]==other)//趟过other棋子
        j++;
    if(j!=col&&j+1<=8&&board[i][j+1]==c){
        j++;
        direction[5]=1;
    } 
    //上竖 米 dirction[3]
    i=row;
    j=col;
    while(i-1>=1&&board[i-1][j]==other)//趟过other棋子
        i--;
    if(i!=row&&i-1>=1&&board[i-1][j]==c){
        i--;
        direction[3]=1;
    }
    //下竖 米 dirction[7] 
    i=row;
    j=col;
    while(i+1>=1&&board[i+1][j]==other)//趟过other棋子
        i++;
    if(i!=row&&i+1<=8&&board[i+1][j]==c){
        i++;
        direction[7]=1;
    }
    //左上斜 米 direction[2] 
    i=row;
    j=col;
    while(i-1>=1&&j-1>=1&&board[i-1][j-1]==other){//趟过other棋子
        i--;
        j--;
    }
    if(i!=row&&j!=col&&i-1>=1&&j-1>=1&&board[i-1][j-1]==c){
        i--;
        j--;
        direction[2]=1;
    }
    //右下斜 米 direction[6] 
    i=row;
    j=col;
    while(i+1<=8&&j+1<=8&&board[i+1][j+1]==other){//趟过other棋子
        i++;
        j++;
    }
    if(i!=row&&j!=col&&i+1<=8&&j+1<=8&&board[i+1][j+1]==c){
        i++;
        j++;
        direction[6]=1;
    }
    //右上斜 米 direction[4]
    i=row;
    j=col;
    while(i-1>=1&&j+1<=8&&board[i-1][j+1]==other){
        i--;
        j++;
    }
    if(i!=row&&j!=col&&i-1>=1&&j+1<=8&&board[i-1][j+1]==c){
        i--;
        j++;
        direction[4]=1;
    }
    //左下斜 米 direction[8] 
    i=row;
    j=col;
    while(i+1<=8&&j-1>=1&&board[i+1][j-1]==other){
        i++;
        j--;
    }
    if(i!=row&&j!=col&&i+1<=8&&j-1>=1&&board[i+1][j-1]==c){
        i++;
        j--;
        direction[8]=1;
    }
}

void setboard(char c,int row,int col){//根据落子布局棋盘 
    
    char other;
    int i,j;

    if(c=='B')//确定当前棋子,与对手棋子 
        other='W';
    else
        other='B';
    
    board[row][col]=c;//安放落子 
    //“米”字形,八个方位,左横、上竖、右横、下竖、左上斜、右上斜、左下斜、右下斜
    // 左横 米 direction[1]; 
    if(direction[1]==1){
        i=row;
        j=col;
        while(j-1>=1&&board[i][j-1]==other){//趟过other棋子,有快速排序代码的一点痕迹 
            j--;
            board[i][j]=c;
        }
        if(j!=col&&j-1>=1&&board[i][j-1]==c){
            j--;
        }
    }
    
    //右横 米 dirction[5]
    if(direction[5]==1){
        i=row;
        j=col;
        while(j+1<=8&&board[i][j+1]==other){//趟过other棋子
            j++;
            board[i][j]=c;
        }
        if(j!=col&&j+1<=8&&board[i][j+1]==c){
            j++;
        }
    }
     
    //上竖 米 dirction[3]
    if(direction[3]==1){
        i=row;
        j=col;
        while(i-1>=1&&board[i-1][j]==other){//趟过other棋子
            i--;
            board[i][j]=c;
        }
        if(i!=row&&i-1>=1&&board[i-1][j]==c){
            i--;
        }
    }
    
    //下竖 米 dirction[7]
    if(direction[7]==1){
        i=row;
        j=col;
        while(i+1>=1&&board[i+1][j]==other){//趟过other棋子
            i++;
            board[i][j]=c;
        }
        if(i!=row&&i+1<=8&&board[i+1][j]==c){
            i++;
        }
    } 
    
    //左上斜 米 direction[2] 
    if(direction[2]==1){
        i=row;
        j=col;
        while(i-1>=1&&j-1>=1&&board[i-1][j-1]==other){//趟过other棋子
            i--;
            j--;
            board[i][j]=c;
        }
        if(i!=row&&j!=col&&i-1>=1&&j-1>=1&&board[i-1][j-1]==c){
            i--;
            j--;
        }
    }
    
    //右下斜 米 direction[6] 
    if(direction[6]==1){
        i=row;
        j=col;
        while(i+1<=8&&j+1<=8&&board[i+1][j+1]==other){//趟过other棋子
            i++;
            j++;
            board[i][j]=c;
        }
        if(i!=row&&j!=col&&i+1<=8&&j+1<=8&&board[i+1][j+1]==c){
            i++;
            j++;
        }
    }
    
    //右上斜 米 direction[4]
    if(direction[4]==1){
        i=row;
        j=col;
        while(i-1>=1&&j+1<=8&&board[i-1][j+1]==other){
            i--;
            j++;
            board[i][j]=c;
        }
        if(i!=row&&j!=col&&i-1>=1&&j+1<=8&&board[i-1][j+1]==c){
            i--;
            j++;
        }
    }
    
    //左下斜 米 direction[8] 
    if(direction[8]==1){
        i=row;
        j=col;
        while(i+1<=8&&j-1>=1&&board[i+1][j-1]==other){
            i++;
            j--;
            board[i][j]=c;
        }
        if(i!=row&&j!=col&&i+1<=8&&j-1>=1&&board[i+1][j-1]==c){
            i++;
            j--;
        }
    }
    
}

void countboard(){
    int i,j;
    int Bcount=0,Wcount=0;
    for(i=1;i<=8;i++){
        for(j=1;j<=8;j++){
            if(board[i][j]=='B')
                Bcount++;
            if(board[i][j]=='W')
                Wcount++;
        }
    }
    printf("Black - %2d White - %2d\n",Bcount,Wcount);
}
void setlegal(char player){//设置当前颜色棋子可行区域 
    int i,j;
    memset(legal,0,sizeof(legal));//初始化合法区域,设置为0 
    for(i=1;i<=8;i++){//扫描字符为player的棋子 
        for(j=1;j<=8;j++){
            if(board[i][j]==player)
                list(player,i,j);
        }
    }
}

void printboard(){
    int i,j;
    for(i=1;i<=8;i++){
        for(j=1;j<=8;j++){
            printf("%c",board[i][j]);
        }
        printf("\n");
    }
}
int main(){
    int T;
    char line[10];
    int i,j;
    int row,col;
    int blank=0;
    char s[10];
    char player;
    scanf("%d",&T);
    while(T--){//事例次数 
        if(blank>0)//打印例子间空行 
            printf("\n");
        blank++;
        memset(board,0,sizeof(board));
        for(i=1;i<=8;i++){//读取棋盘信息 
            scanf("%s",line);
            for(j=1;j<=8;j++){
                board[i][j]=line[j-1];
            }
        }
        scanf("%s",s);//读取当前落子颜色 
        player=s[0];
        while(1){    
            scanf("%s",s);//读取当前棋盘操作 
            if(s[0]=='L'){
                setlegal(player);
                printlist();//打印可能位置 
            }else if(s[0]=='M'){//每次移动后,需要增加board数据,需要重设legal值 
                row=s[1]-'0';
                col=s[2]-'0';
                setlegal(player);//每次移动前,总要先查找合法放置区域,该句漏了,整整查了两天11.3-11.4,终于AC了,想到都是泪
                if(legal[row][col]==1){//合法放置 
                    enumdirection(player,row,col);//枚举可能放置方向 
                    setboard(player,row,col);//根据落子,重新布局棋盘 
                    countboard();//统计棋盘黑白棋个数 
                }else{//非法放置,另一种颜色棋子先走,从题意看,另一种颜色棋子一定能走成功 
                    player=player=='B'?'W':'B';//改变当前落子颜色,第一次用三目运算符
                    setlegal(player);
                    enumdirection(player,row,col);//枚举可能放置方向 
                    setboard(player,row,col);//根据落子,重新布局棋盘 
                    countboard();//统计棋盘黑白棋个数
                }
                //每次移动后,先手自动交换颜色
                player=player=='B'?'W':'B'; 
            }else if(s[0]=='Q'){//退出当前事例 
                printboard();
                break;
            }
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/jxufe_acmer/article/details/80328447