首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要帮助调试象棋功能

需要帮助调试象棋功能
EN

Stack Overflow用户
提问于 2014-08-04 19:47:14
回答 3查看 161关注 0票数 1

我对C和一般编程都很陌生。我已经实现了C,并且几乎完成了,但是检查一个片段是否受到攻击的函数似乎是错误的。如果有人能看一看,也许能发现一些我找不到的东西,我会很感激的:

代码语言:javascript
复制
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;
}

非常转向,我有一个移动列表。只有在完成移动后,玩家的国王没有受到攻击,即isAttacked返回0时,移动才能添加到该列表中。为了检查玩家的国王是否受到攻击,我收到国王的坐标(i,j)然后,我去对角线,看看是否有敌人的棋子,主教,国王,或王后可以攻击国王。我对车的动作也是这样。后两个是错的.我想--一个例子

代码语言:javascript
复制
 |-------------------------------|
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表示。我在检测主教/车检查时遇到了问题,但我似乎找不到错误的地方。任何帮助都将不胜感激!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-04 21:30:55

我认为问题可能在输入到例程的坐标内,也可能是isValidCoords例程的问题所在。为了测试发布的代码,我提供了以下驱动程序:

代码语言:javascript
复制
#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;,我将其改为:

代码语言:javascript
复制
{
    printf("%c is attacking from (%d,%d)\n", 
           pieceabbrev[game->board[curX][curY]], curX, curY);
    return 1;
}

程序输出:

代码语言:javascript
复制
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  

正如你所看到的,你的例行公事正确地发现了攻击主教,所以我怀疑问题在别处。

此外,就其价值而言,提供一个最小但完整的示例(如我提供的代码)可能会使其他人更容易帮助您。

票数 4
EN

Stack Overflow用户

发布于 2014-08-04 21:40:17

正如泰勒所指出的,您的代码有些不正确,但这并不是您的示例不起作用的原因。我使用您的函数实现了一个最小的工作示例,它在您的测试用例中运行得很好。

代码语言:javascript
复制
#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;
}

输出:

代码语言:javascript
复制
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|
|---------------|

所以,你无法发现攻击主教的原因很可能是隐藏在周围的代码中。

您还应该将您的函数拆分为更小的函数,以方便调试。

编辑:爱德华击败了我,所以我同意他的观点。

票数 1
EN

Stack Overflow用户

发布于 2014-08-04 20:29:53

问题是如何处理以下循环中的退出条件:

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

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

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

代码语言:javascript
复制
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-循环的紧固支撑之前.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25126358

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档