0

程序在初始化板后应要求用户配置,然后使用用户配置打印板。然后它相应地打印“W”和“B”的可用移动。最后一步是询问已使用的移动,如果它与之前打印的可用移动匹配,则打印移动有效的消息,然后使用有效移动最后一次打印棋盘。我的代码工作正常,直到它打印配置的板,但之后我在这里得到一些奇怪的输出。请在这里帮忙,谢谢。在下面的程序中输入应该是:U-未占用,B-被黑色占用,W-被白色占用。这是一个示例输入和预期输出:示例

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void boardInitialize(char board[26][26], int n);
void printBoard(char board[26][26], int n);
void checkLegalMovesAvailable(char board[26][26], int N, char colour);
bool positionInBounds(int N, char row, char col);
void printMove(char board[26][26], int n);
void checkLegalInDirection(char board[26][26],int N,char row,char col,char colour,int deltaRow,int deltaCol);
bool checkLegalInMove(char board[26][26], int N, char row, char col, char colour);

int main(void){
    int n;
    char board[26][26];
    printf("Enter the board dimension: ");
    scanf("%d",&n);
    boardInitialize(board,n);
    printBoard(board,n);
    checkLegalMovesAvailable(board,n,'W');
    checkLegalMovesAvailable(board,n,'B');
    printMove(board,n);

    return (EXIT_SUCCESS);
}

//Function to initialize board
void boardInitialize(char board[26][26], int n){
    printf("  ");
    for(int i=0;i<n;i++){
        printf("%c",97+i);
    }
    printf("\n");
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            board[i][j]='U';
        }
    }
    board[(n/2)-1][(n/2)-1]='W';
    board[n/2][n/2]='W';
    board[(n/2)-1][n/2]='B';
    board[n/2][(n/2)-1]='B';
    for(int i=0;i<n;i++){
        printf("%c ",97+i);
        for(int j=0;j<n;j++){
            printf("%c",board[i][j]);
        }
        printf("\n");
    }
}

//Function to print board after configuration
void printBoard(char board[26][26], int n){
    printf("Enter board configuration:");
    printf("\n");
    char color,row,col;
    for(int i=0;(color!='!' && row!='!' && col!='!');i++){
        scanf(" %c%c%c",&color,&row,&col);
            board[row-'a'][col-'a']=color;
    }
    printf("  ");
    for(int i=0;i<n;i++){
        printf("%c",97+i);
    }
    printf("\n");
    for(int i=0;i<n;i++){
        printf("%c ",97+i);
        for(int j=0;j<n;j++){
            printf("%c",board[i][j]);
        }
        printf("\n");
    }   
}

//function to print available moves after configuration
void checkLegalMovesAvailable(char board[26][26], int N, char colour){
    printf("Available moves for %c:\n",colour);
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            if(board[i][j]==colour){
                for(int deltaRow=-1;deltaRow<=1;deltaRow++){
                    for(int deltaCol=-1;deltaCol<=1;deltaCol++){
                        if(deltaRow==0 && deltaCol==0)
                            ;
                        else
                            if(positionInBounds(N,('a'+i+deltaRow), ('a'+j+deltaCol)))
                                checkLegalInDirection(board,N,('a'+i+deltaRow),('a'+j+deltaCol),colour,deltaRow,deltaCol);
                        }
                    }
                }   
            }
        }
    }

//function to check if any move is legal in a specific direction
void checkLegalInDirection(char board[26][26],int N,char row,char col,char colour,int deltaRow,int deltaCol){
    int r=row-'a', c=col-'a',count=0;
    while((positionInBounds(N,'a'+r+(count*deltaRow),'a'+c+(count*deltaCol))) && (board[r+(count*deltaRow)][c+(count*deltaCol)]!=colour) && (board[r+(count*deltaRow)][c+(count*deltaCol)]!='U')){
        count++;
        if((positionInBounds(N,'a'+r+(count*deltaRow),'a'+c+(count*deltaCol))) && (board[r+(count*deltaRow)][c+(count*deltaCol)]=='U')){
        printf("%c%c\n",(row+(count*deltaRow)),(col+(count*deltaCol)));
        break;
        }
    }
}

//function to check if the specified row,col lies within the board dimensions
bool positionInBounds(int N, char row, char col){
    int p=row-'a',q=col-'a';
    if(p>=0 && q>=0 && p<N && q<N)
        return true;
    else
        return false;
}

//function to print board after a legal move 
void printMove(char board[26][26], int n){
    char color,row,col,temp;
    printf("Enter a move:\n");
    scanf(" %c%c%c",&color,&row,&col);
    temp=board[row-'a'][col-'a'];
    board[row-'a'][col-'a']=color;
    if(checkLegalInMove(board,n,row,col,color)){
        printf("  ");
        for(int i=0;i<n;i++){
            printf("%c",97+i);
        }
        printf("\n");
        for(int i=0;i<n;i++){
            printf("%c ",97+i);
            for(int j=0;j<n;j++){
                printf("%c",board[i][j]);
            }
            printf("\n");
        }
    }
    else{
        board[row-'a'][col-'a']=temp;
        printf("  ");
        for(int i=0;i<n;i++){
            printf("%c",97+i);
        }
        printf("\n");
        for(int i=0;i<n;i++){
            printf("%c ",97+i);
            for(int j=0;j<n;j++){
                printf("%c",board[i][j]);
            }
            printf("\n");
        }
    }
}

//function to check if any specific move is legal
bool checkLegalInMove(char board[26][26], int N, char row, char col, char colour){
    int r=row-'a',c=col-'a';
    for(int deltaRow=-1;deltaRow<=1;deltaRow++){
        for(int deltaCol=-1;deltaCol<=1;deltaCol++){
            if(positionInBounds(N,row,col)){
                checkLegalInDirection(board,N,('a'+r),('a'+c),colour,deltaRow,deltaCol);
                printf("Valid move.\n");
                return true;
            }
            else
                printf("Invalid move.\n");
            return false;
        }
    }
}
4

3 回答 3

0

好的,这是另一个可以解决几个问题的更改。在搜索可用移动时,您正在检查棋盘上已经有玩家棋子的方格,然后您正在查看各个方向以查看该方向是否有移动。这与人们通常的做法相反,它也会导致问题(重复移动)。

例如,假设您正在寻找玩家 X 的移动,并且棋盘看起来像:

*OOOX
O
X

我用 标记了有趣的空缺职位*。如您所见,该位置是一个双重移动,因为合法捕获存在于同一位置的两个不同方向。

您当前的方法将两次列出此动作。它会首先从其中一个 X 位置开始找到它,然后在遇到第二个 X 位置时再次找到它。

我们可以修复这个错误,并解决您的移动排序问题,通过简单的修复可能实际上简化您的程序。

目前,您检查板上的每个方格以查看它是否是玩家的颜色。如果是,那么您寻找对手颜色的相邻运行,以空方格终止,然后将其视为合法移动。

相反,你应该反过来:检查棋盘上的每个方格,看它是否是的。如果是,则寻找对手颜色的相邻运行,以颜色的正方形终止。如果你找到它,那么起始方格(空方格)将成为你的移动。

这个改变其实很简单,它解决了两件事:(1)你将不再发现重复的动作(如上例所示),以及(2)这些动作将按顺序打印。

编辑:我应该补充一点,一旦你找到一个移动并打印它,你应该立即移动到下一个空方格。否则,如果您继续寻找其他方向,您可能会发现重复项。一个很好的方法是把它分成两个函数。第一个只是遍历所有正方形(行、列),然后调用第二个来检查那里是否有合法的移动。第二个检查合法的举动。如果它找到一个,它会立即停止寻找并返回。

于 2015-11-14T16:51:40.837 回答
0

好的,这是一个简单的观察。看起来你改变checkLegalMovesAvailable了,所以它现在总是返回true,对吗?所以这里有一个问题要问你:这有意义吗?如果是这样,那么它可能根本不应该返回任何东西,并且它的调用者应该总是把它当作返回true。如果不是,那么也许你应该重新考虑你的逻辑,并弄清楚在什么情况下它应该返回truefalse. 那有意义吗?

于 2015-11-05T13:08:54.633 回答
0

好的,这里为您提供更多修复:

(1) 在positionInBounds中,您正在检查 ifp<=Nq<=N。我相信这些支票应该是p<Nand q<N,对吧?所以它们都在 0...(N-1) 的范围内。

(2) 在中,如果和都为 0 checkLegalMovesAvailable,则应跳过对 的调用。9 个组合中只有 8 个有效。checkLegalInDirectiondeltaRowdeltaCol

(3) 在checkLegalMovesAvailable您检查所需方向的第一个方格是否在边界内。但是在 中checkLegalInDirection,您继续朝着同一个方向越走越远,而从未检查您是否仍在界限内。我怀疑这会导致您看到的一些实际问题。

(4) 在checkLegalInDirection中,只要方块不是空的或你的颜色,即只要它是你对手的颜色,你就一直朝那个方向看。这很好,但最后,您需要检查最后一个方格是否为空,而不是您自己的颜色。那张支票不见了。

看看你是否可以在这些修复上取得一些进展。这应该会让你忙一阵子。如果在那之后你仍然有问题,我也许可以再看看它。

于 2015-11-05T19:14:56.127 回答