Reversi游戏 - 移动合法性检查C编程

时间:2015-11-05 12:44:19

标签: c arrays function for-loop reversi

程序初始化电路板后应询问用户配置,然后使用用户配置打印电路板。然后它会打印“W' W' &安培; ' B'因此。最后一步是要求从已使用的移动,如果它与打印的可用移动匹配,然后它打印移动的消息有效,然后它使用有效移动最后一次打印板。我的代码工作正常,直到它打印配置的板,但在那之后我得到一些奇怪的输出。请帮忙,谢谢。 在下面的程序中,输入应该是以下形式:U-未占用,B-由黑色占用,W占用白色。这是一个示例输入和预期输出:Example

#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;
        }
    }
}

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

好的,这里还有一些修复方法:

(1)在positionInBounds,您正在核对p<=Nq<=N。我相信这些支票应该是p<Nq<N,对吗?所以他们都在0 ...(N-1)范围内。

(2)在checkLegalMovesAvailable中,如果checkLegalInDirectiondeltaRow都为0,则应跳过对deltaCol的调用.9种组合中只有8种有效。< / p>

(3)在checkLegalMovesAvailable中,检查所需方向的第一个方格是否在边界内。但是在checkLegalInDirection中,你继续朝着同一个方向寻找,而不是检查你是否仍在界限内。我怀疑这会引起你一直看到的一些实际问题。

(4)在checkLegalInDirection中,只要广场不是空或你的颜色,你就会继续向那个方向看,即只要它是对手的颜色。这很好,但最后,你需要检查最后的方块是否为空,而不是你自己的颜色。那张支票丢失了。

看看您是否可以在这些修复方面取得一些进展。那会让你忙个不停。如果你之后仍然遇到问题,我可能会再次看一下。

答案 2 :(得分:0)

好的,这是你的另一个改变,它可以解决几个问题。在搜索可用的移动时,您需要检查棋盘上是否有已经有玩家的棋子,然后您可以向所有方向查看,看看是否有移动方向。这是人们通常会这样做的倒退,也会导致问题(重复移动)。

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

*OOOX
O
X

我用*标记了有趣的开放位置。正如您所看到的那样,该位置是双重移动,因为合法捕获存在于同一位置的两个不同方向。

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

我们可以修复此错误,并通过简单的修复解决您的移动订购问题,这可能会简化您的程序。

目前,您检查棋盘上的每个方块,看它是否是玩家的颜色。如果是,那么你会寻找对手的颜色的相邻运行,由空方块终止,然后被认为是合法的移动。

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

此更改实际上非常简单,它解决了两件事:(1)您将不再找到重复的动作(如上例所示),以及(2)动作将按顺序打印。

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