C - 需要帮助调试国际象棋功能

时间:2014-08-04 19:47:14

标签: c

我是C和编程的新手。我已经实现了C并且差不多完成了,但是看起来检查一块是否被攻击的函数是错误的。我很感激,如果有人可以看看,也许发现我不能发现的东西:

int isAttacked(game_t* game, int x, int y, int color)
{
    /*printf("entered IA");*/
    int i, j,m, curX, curY, range;
    int dx[] = { 0, 1, 0, -1 };
    int dy[] = { 1, 0, -1, 0 };
    char en = BLACK_N, eb = BLACK_B, er = BLACK_R, eq = BLACK_Q, ek = BLACK_K, ep = BLACK_P;
    if (!color)
    {
        en = WHITE_N;
        eb = WHITE_B;
        er = WHITE_R;
        eq = WHITE_Q;
        ek = WHITE_K;
        ep = WHITE_P;
    }

    for (i = -2; i <= 2; i++)  /* KNIGHT ATTACKING */
        for (j = -2; j <= 2; j++)
            if (ABS(i) + ABS(j) == 3 && isValidCoords(x + i, y + j) && game->board[x + i][y + j] == en)
                return 1;

    for (i = -1; i <= 1; i += 2)
    {
        for (j = -1; j <= 1; j += 2)
        {
            curX = x;
            curY = y;
            range = 0;
            while (isValidCoords(curX + i, curY + j) == 1)          
            {
                range++;
                curX += i;
                curY += j;
                if(game->board[curX][curY] != EMPTY)
                    break;
            }


            if (game->board[curX][curY] == eq) /*BISHOP OR QUEEN ATTACKING*/
                return 1;
            if(game->board[curX][curY] == eb)
            {
                return 1;
            }

            if (range == 1 && game->board[curX][curY] == ek) /*KING ATTACKING*/
                return 1;
            if (range == 1 && color && j == 1 && game->board[curX][curY] == ep)
            {
                return 1;
            }
            if (range == 1 && !color && j == -1 && game->board[curX][curY] == ep)
            {
                return 1;
            }


        }
    }

    for (m = 0; m<4; m++)
    {
        curX = x;
        curY = y;
        range = 0;
        while (isValidCoords(curX + dx[m], curY + dy[m]))
        {
            curX += dx[m];
            curY += dy[m];
            range++;
            if(game->board[curX][curY] != EMPTY)
                break;
        }

        if (game->board[curX][curY] == eq)
            return 1;
        if(game->board[curX][curY] == er) /*ROOK OR QUEEN ATTACKING*/
        {
            /*printf("x %d  y   %d\n",x,y);*/
            return 1;
        }
        if (range == 1 && game->board[curX][curY] == ek)
            return 1;


    }

    return 0;
}
转过来,我有一份动作清单。移动只能添加到该列表中,如果在移动完成后,玩家的国王没有受到攻击,即被攻击返回0.为了检查玩家的国王是否受到攻击,我收到国王的坐标(i,j)[这些是从0到7的数字]和颜色[0或1]。然后我检查棋盘内是否有敌人骑士(ek)(isValidCoords检查0&lt; = x,y&lt; = 7)可以攻击国王。然后我去对角线检查是否有一个可以攻击国王的敌人典当,主教,国王或王后。车道运动也是如此。后两者是错的......我想 - 检查未能检测到主教攻击国王的示例板:

 |-------------------------------|
8| R | N | B |   |  | B | N | R |
 |-------------------------------|
7| P | P | P |   | P | K | P | P |
 |-------------------------------|
6|   |   |   | Q |   |   |   |   |
 |-------------------------------|
5|   |   |   |   |   |   |   | |
 |-------------------------------|
4|   |   | b |   | P |   |   |   |
 |-------------------------------|
3|   |   |   |   |   |   |   |   |
 |-------------------------------|
2| p | p | p | p |   | p | p | p |
 |-------------------------------|
1| r | n | b |   | k |   | n | r |
 |-------------------------------|

黑色部分是大写字母,白色部分是小写字母。

颜色用黑色表示 - 0和白色 - 1.我在检测主教/车检查时遇到问题,但我似乎无法查明错误。任何帮助都将不胜感激!

3 个答案:

答案 0 :(得分:4)

我认为问题可能在于您正在为例程提供的坐标,或者您的isValidCoords例程可能存在问题。为了测试你发布的代码,我提供了这个驱动程序:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char board[8][8];
} game_t;

int isValidCoords(int x, int y)
{
    return (x >= 0) && (y >= 0) && (x < 8) && (y < 8);
}

enum pieces { EMPTY, 
              BLACK_N, BLACK_B, BLACK_R, BLACK_Q, BLACK_K, BLACK_P, 
              WHITE_N, WHITE_B, WHITE_R, WHITE_Q, WHITE_K, WHITE_P };

const char pieceabbrev[] = " NBRQKPnbrqkp";

#define BLACK 0
#define WHITE 1

int ABS(int i)
{
    return i < 0 ? -i : i;
}
void showboard(game_t *game)
{
    const char hline[] ="\n |-------------------------------|";

    puts(hline);
    for (int y=7; y>=0; --y) {
        printf("%d|", y);
        for (int x=0; x < 8; ++x) {
            printf(" %c |", pieceabbrev[game->board[x][y]]);
        }   
        puts(hline);
    }   
    printf("  ");
    for (int x=0; x < 8; ++x) {
        printf(" %d  ", x);
    }
    printf("\n");
}

/*
Y
 |-------------------------------|
7| R | N | B |   |   | B | N | R |
 |-------------------------------|
6| P | P | P |   | P | K | P | P |
 |-------------------------------|
5|   |   |   | Q |   |   |   |   |
 |-------------------------------|
4|   |   |   |   |   |   |   |   |
 |-------------------------------|
3|   |   | b |   | P |   |   |   |
 |-------------------------------|
2|   |   |   |   |   |   |   |   |
 |-------------------------------|
1| p | p | p | p |   | p | p | p |
 |-------------------------------|
0| r | n | b |   | k |   | n | r |
 |-------------------------------|
   0   1   2   3   4   5   6   7     X
 lowercase is white
 Uppercase is Black
*/
int main()
{
    game_t game;
    for (int i=0; i < 8; ++i)
        for (int j=0; j < 8; ++j)
            game.board[i][j] = EMPTY;

    game.board[0][7] = BLACK_R;
    game.board[1][7] = BLACK_N;
    game.board[2][7] = BLACK_B;
    game.board[3][7] = EMPTY;
    game.board[4][7] = EMPTY;
    game.board[5][7] = BLACK_B;
    game.board[6][7] = BLACK_N;
    game.board[7][7] = BLACK_R;

    game.board[0][6] = BLACK_P;
    game.board[1][6] = BLACK_P;
    game.board[2][6] = BLACK_P;
    game.board[3][6] = EMPTY;
    game.board[4][6] = BLACK_P;
    game.board[5][6] = BLACK_K;
    game.board[6][6] = BLACK_P;
    game.board[7][6] = BLACK_P;

    game.board[3][5] = BLACK_Q;

    game.board[2][3] = WHITE_B;
    game.board[4][3] = WHITE_P;

    game.board[0][1] = WHITE_P;
    game.board[1][1] = WHITE_P;
    game.board[2][1] = WHITE_P;
    game.board[3][1] = WHITE_P;
    game.board[4][1] = EMPTY;
    game.board[5][1] = WHITE_P;
    game.board[6][1] = WHITE_P;
    game.board[7][1] = WHITE_P;

    game.board[0][0] = WHITE_R;
    game.board[1][0] = WHITE_N;
    game.board[2][0] = WHITE_B;
    game.board[3][0] = EMPTY;
    game.board[4][0] = WHITE_K;
    game.board[5][0] = EMPTY;
    game.board[6][0] = WHITE_N;
    game.board[7][0] = WHITE_R;

    printf("attacked = %d\n", isAttacked(&game, 5, 6, BLACK));

    showboard(&game);
}

然后我检测了你的代码。它最初有一个return 1;的地方我把它改成了这个:

{
    printf("%c is attacking from (%d,%d)\n", 
           pieceabbrev[game->board[curX][curY]], curX, curY);
    return 1;
}

节目输出:

b is attacking from (2,3)
attacked = 1

 |-------------------------------|
7| R | N | B |   |   | B | N | R |
 |-------------------------------|
6| P | P | P |   | P | K | P | P |
 |-------------------------------|
5|   |   |   | Q |   |   |   |   |
 |-------------------------------|
4|   |   |   |   |   |   |   |   |
 |-------------------------------|
3|   |   | b |   | p |   |   |   |
 |-------------------------------|
2|   |   |   |   |   |   |   |   |
 |-------------------------------|
1| p | p | p | p |   | p | p | p |
 |-------------------------------|
0| r | n | b |   | k |   | n | r |
 |-------------------------------|
   0   1   2   3   4   5   6   7  

正如你所看到的,你的例程正确地检测到攻击主教,所以我怀疑问题出在其他地方。

此外,对于它的价值,提供一个最小但完整的示例(与我提供的代码一样)可能会让其他人更容易帮助您。

答案 1 :(得分:1)

正如Tyler指出的那样,你的代码有点不正确,但这不是你的例子不起作用的原因。 我使用您的函数实现了一个最小的工作示例,它在您的测试用例中运行良好。

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

typedef struct game_s {
     char board[8][8];
} game_t;

#define EMPTY 0x20
#define BLACK_N 'N'
#define BLACK_B 'B'
#define BLACK_R 'R'
#define BLACK_Q 'Q'
#define BLACK_K 'K'
#define BLACK_P 'P'
#define WHITE_N 'n'
#define WHITE_B 'b'
#define WHITE_R 'r'
#define WHITE_Q 'q'
#define WHITE_K 'k'
#define WHITE_P 'p'

void print_board(game_t *game) {
    int i,j;
    for(j=7;j>=0;j--) {
        printf("|---------------|\n|");
        for(i=0;i<8;i++) {
            printf("%c|", game->board[i][j]);
        }
        printf("\n");
    }
    printf("|---------------|\n");
}

int ABS(int x) {
    return (x > 0 ? x : x*-1);
}

int isValidCoords(int x, int y) {
    return (x >= 0 && y>=0 && x<8 && y<8);
}

int isAttacked(game_t *game, int x, int y, int color)
{
    /*printf("entered IA");*/
    int i, j,m, curX, curY, range;
    int dx[] = { 0, 1, 0, -1 };
    int dy[] = { 1, 0, -1, 0 };
    char en = BLACK_N, eb = BLACK_B, er = BLACK_R, eq = BLACK_Q, ek = BLACK_K, ep = BLACK_P;
    if (!color)
    {
        en = WHITE_N;
        eb = WHITE_B;
        er = WHITE_R;
        eq = WHITE_Q;
        ek = WHITE_K;
        ep = WHITE_P;
    }

    for (i = -2; i <= 2; i++)  /* KNIGHT ATTACKING */
        for (j = -2; j <= 2; j++)
            if (ABS(i) + ABS(j) == 3 && isValidCoords(x + i, y + j) && game->board[x + i][y + j] == en) {
                return 1;
            }

    for (i = -1; i <= 1; i += 2)
    {
        for (j = -1; j <= 1; j += 2)
        {
            curX = x;
            curY = y;
            range = 0;
            while (isValidCoords(curX + i, curY + j) == 1)
            {
                range++;
                curX += i;
                curY += j;
                if(game->board[curX][curY] != EMPTY)
                    break;
            }


            if (game->board[curX][curY] == eq) { /*BISHOP OR QUEEN ATTACKING*/
                return 1;
            }
            if(game->board[curX][curY] == eb)
            {
            printf("ATTACK from %s Bishop at %c%c\n", color ? "black" : "white", curX+'A', curY+'1');
                return 1;
            }

            if (range == 1 && game->board[curX][curY] == ek) { /*KING ATTACKING*/
                return 1;
            }
            if (range == 1 && color && j == 1 && game->board[curX][curY] == ep)
            {
                return 1;
            }
            if (range == 1 && !color && j == -1 && game->board[curX][curY] == ep)
            {
                return 1;
            }


        }
    }

    for (m = 0; m<4; m++)
    {
        curX = x;
        curY = y;
        range = 0;
        while (isValidCoords(curX + dx[m], curY + dy[m]))
        {
            curX += dx[m];
            curY += dy[m];
            range++;
            if(game->board[curX][curY] != EMPTY)
                break;
        }

        if (game->board[curX][curY] == eq)
            return 1;
        if(game->board[curX][curY] == er) /*ROOK OR QUEEN ATTACKING*/
        {
            /*printf("x %d  y   %d\n",x,y);*/
            return 1;
        }
        if (range == 1 && game->board[curX][curY] == ek)
            return 1;


    }

    return 0;
}

int main(int argc, char *argv[]) {
    char my_board[8][8] = { {WHITE_R, WHITE_P, EMPTY, EMPTY, EMPTY, EMPTY, BLACK_P, BLACK_R},
            {WHITE_N, WHITE_P, EMPTY, EMPTY, EMPTY, EMPTY, BLACK_P, BLACK_N},
            {WHITE_B, WHITE_P, EMPTY, WHITE_B, EMPTY, EMPTY, BLACK_P, BLACK_B},
            {EMPTY, WHITE_P, EMPTY, EMPTY, EMPTY, BLACK_Q, EMPTY, EMPTY},
            {WHITE_K, EMPTY, EMPTY, BLACK_P, EMPTY, EMPTY, BLACK_P, EMPTY},
            {EMPTY, WHITE_P, EMPTY, EMPTY, EMPTY, EMPTY, BLACK_K, BLACK_B},
            {WHITE_N, WHITE_P, EMPTY, EMPTY, EMPTY, EMPTY, BLACK_P, BLACK_N},
            {WHITE_R, WHITE_P, EMPTY, EMPTY, EMPTY, EMPTY, BLACK_P, BLACK_R}};
    game_t my_game;
    memcpy(my_game.board, my_board, 64);

    isAttacked(&my_game, 5, 6, 0);

    print_board(&my_game);

    return 0;
}

输出:

ATTACK from white Bishop at C4
|---------------|
|R|N|B| | |B|N|R|
|---------------|
|P|P|P| |P|K|P|P|
|---------------|
| | | |Q| | | | |
|---------------|
| | | | | | | | |
|---------------|
| | |b| |P| | | |
|---------------|
| | | | | | | | |
|---------------|
|p|p|p|p| |p|p|p|
|---------------|
|r|n|b| |k| |n|r|
|---------------|

所以看起来你无法检测到攻击主教的原因很可能隐藏在周围的代码中。

您还应该将功能拆分为较小的功能,以便于调试。

编辑:爱德华打败了我,所以我同意他的意见

答案 2 :(得分:0)

问题是从以下循环处理退出条件:

while (isValidCoords(curX + i, curY + j) == 1)

如果isValidCoords返回false(0),则循环退出并使用curXcurY的无效值继续该过程。

换句话说,这个循环有两个可能的退出条件:(1)坐标不在板上,或者(2)坐标表示的方块上有一个块。你以同样的方式对待这两种情况。解决此问题的一种方法如下:

while ( true ){
    if( isValidCoords(curX + i, curY + j) == 1 ) goto NextAttackCheck;
    range++;
    curX += i;
    curY += j;
    if( game->board[curX][curY] != EMPTY ) break;
}

标签NextAttackCheck:应位于j循环的闭括号之前。