反转游戏–在C程序中进行合法性检查



一旦初始化电路板,程序就应该请求用户配置,然后使用用户配置打印电路板。然后它打印"W"one_answers"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%cn",(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;
        }
    }
}

好的,这里有另一个变化,应该可以解决几个问题。在搜索可用的移动时,你要检查棋盘上是否有已经有玩家棋子的方块,然后你要向各个方向看是否有移动。这与通常的做法相反,也会造成问题(重复移动)。

例如,假设你正在为玩家X寻找移动,棋盘看起来像:

*OOOX
O
X

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

你目前的做法会列出两次这一举措。它会首先从X位置中的一个开始找到它,然后当它遇到第二个X位置时会再次找到它。

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

目前,你会检查棋盘上的每个方块,看看它是否是玩家的颜色。如果是,那么你会寻找对手颜色的相邻跑动,以一个空正方形结束,然后这被认为是合法的移动。

相反,你应该颠倒这一点:检查板上的每个方块,看看它是否是空的。如果是,那么寻找对手颜色的相邻跑动,以你的颜色的正方形结束。如果你找到了,那么起始方块(空方块)就变成了你的移动。

这个更改实际上非常简单,它解决了两件事:(1)您将不再发现重复的移动(如上面的示例),以及(2)移动将按顺序打印。

编辑:我应该补充一点,一旦你找到一个移动并打印出来,你应该立即移动到下一个空方块。否则,如果你一直往其他方向看,你可能会发现重复的。一个很好的方法是将它分解为两个函数。第一个只是在所有正方形(行、列)上迭代,并调用第二个来检查是否有合法的移动。第二个检查是否合法。如果它找到一个,它会立即停止寻找并返回。

好的,这里有一个简单的观察结果。看起来您更改了checkLegalMovesAvailable,所以它现在总是返回true,对吗?所以这里有一个问题要问你:这有意义吗?如果是这样,那么也许它根本不应该返回任何内容,并且它的调用者应该始终将其视为返回了true。如果没有,那么也许您应该重新思考您的逻辑,并弄清楚在什么情况下它应该返回truefalse。这有道理吗?

好的,这里还有一些修复程序:

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

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

(3) 在checkLegalMovesAvailable中,检查所需方向上的第一个正方形是否在边界内。但在checkLegalInDirection中,你会朝着同一个方向看得越来越远,而不会检查自己是否仍在边界内。我怀疑这造成了你所看到的一些真正的问题。

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

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

相关内容

  • 没有找到相关文章

最新更新