Reversi Game - проверка легальности в C-программировании

Программа должна запросить конфигурацию пользователя, как только инициализирует плату, а затем распечатывает плату, используя конфигурацию пользователя. Затем он печатает доступные ходы для "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;
        }
    }
}

3 ответа

Хорошо, вот еще одно изменение для вас, которое должно решить несколько проблем. При поиске доступных ходов вы проверяете на доске квадраты, на которых уже есть фигура игрока, затем вы смотрите во всех направлениях, чтобы увидеть, есть ли движение в этом направлении. Это в обратном направлении от того, как обычно это делается, и это также вызовет проблемы (повторяющиеся движения).

Например, предположим, что вы ищете ходы для игрока X, и доска выглядит так:

*OOOX
O
X

Я отметил интересное открытое положение *, Как видите, эта позиция является двойным ходом, поскольку легальные захваты существуют в двух разных направлениях от одной и той же позиции.

Ваш текущий подход будет перечислять этот ход дважды. Сначала он найдет его, начиная с одной из позиций X, а затем снова найдет его, когда встретит вторую позицию X.

Мы можем исправить эту ошибку и решить вашу проблему с порядком перемещения, с помощью простого исправления, которое на самом деле может упростить вашу программу.

В настоящее время вы проверяете каждый квадрат на доске, чтобы увидеть цвет игрока. Если это так, то вы ищите соседние серии цвета противника, оканчивающиеся пустым квадратом, который затем распознается как законный ход.

Вместо этого вы должны поменять местами следующее: осмотрите каждый квадрат на доске, чтобы убедиться, что он пуст. Если это так, то ищите смежные пробежки цвета противника, оканчивающиеся квадратом вашего цвета. Если вы найдете его, то стартовый квадрат (пустой) станет вашим ходом.

Это изменение на самом деле очень просто, и оно решает две вещи: (1) вы больше не найдете повторяющиеся ходы (как в примере выше) и (2) ходы будут напечатаны по порядку.

Изменить: я должен добавить, что, как только вы найдете ход и распечатаете его, вы должны немедленно перейти к следующему пустому квадрату. В противном случае, если вы продолжаете смотреть в других направлениях, вы можете найти дубликаты. Хороший способ сделать это - разбить его на две функции. Первый просто перебирает все квадраты (строки, столбцы) и вызывает второй, чтобы проверить, есть ли законное движение там. Второй проверяет легальный ход. Если он найдет его, он сразу же перестает смотреть и возвращается.

Хорошо, вот одно простое наблюдение для вас. Похоже, ты изменился checkLegalMovesAvailable так что теперь всегда возвращается true, правильный? Итак, вот вам вопрос: имеет ли это смысл? Если так, то, возможно, он вообще ничего не должен возвращать, и его вызывающие всегда должны обращаться с ним так, как будто он вернулся true, Если нет, то, возможно, вам следует пересмотреть свою логику и выяснить, при каких обстоятельствах она должна вернуться true против false, Имеет ли это смысл?

Хорошо, вот еще несколько исправлений для вас:

(1) В positionInBoundsпроверяешь ли p<=N а также q<=N, Я считаю, что эти проверки должны быть p<N а также q<N, право? Так что они оба в диапазоне 0... (N-1).

(2) В checkLegalMovesAvailableВы должны пропустить звонок checkLegalInDirection если оба deltaRow а также deltaCol равны 0. Действительны только 8 из 9 комбинаций.

(3) В checkLegalMovesAvailable Вы проверяете, находится ли первый квадрат в нужном направлении в границах. Но тогда в checkLegalInDirectionВы продолжаете смотреть все дальше и дальше в том же направлении, даже не проверяя, не находитесь ли вы в пределах. Я подозреваю, что это вызывает некоторые реальные проблемы, которые вы видели.

(4) В checkLegalInDirectionвы продолжаете смотреть в этом направлении до тех пор, пока квадрат не пуст или ваш цвет, т.е. пока это цвет вашего оппонента. Это нормально, но в конце вам нужно проверить, что последний квадрат пуст, а не ваш собственный цвет. Эта проверка отсутствует.

Посмотрите, сможете ли вы добиться прогресса в этих исправлениях. Это должно занять вас немного. Если после этого у вас все еще будут проблемы, я мог бы посмотреть на них снова.

Другие вопросы по тегам