不能在国际象棋桌上做马的所有可能动作

时间:2014-11-16 12:33:37

标签: c visual-studio chess

更新:非常感谢M Oehm为您提供了很棒的答案,真的对我帮助很大。那个struct pos移动真的很有帮助,还没有在课堂上研究它。我正在努力完全解决我的代码问题,将你的代码骨架添加为骨骼。已经解决了更新fila和columna的问题,随机选择和从0到7的切换没有'',因为它们不是你和davidc指出的字符。我的程序在发布完全可操作的程序之前仍然存在一些问题。如果不是今天我明天会更新代码。感谢大家的意见和解决方案,感谢你们花时间做出精彩的答案。
---------------------------------------------- -------------------------------------------------- ------------------------------------
更新2:完成它,对M Oehm代码进行了一些小改动,而不是手动放置马的第一个位置我使用了我以前的PosicionCaballo()。不得不删除MoverCaballo()的代码,该代码有一个由8个可能的移动设置的Switch,由一个随机数设置,因为我无法使它工作(我猜主要的问题是那个部分,因为已经是一团糟)。

现在带有下面代码的程序应该询问用户马的初始位置,之后屏幕将打印一个填充0(自由空间)的10x10表,填充1(采取)使马随机移动的空间)以及当它完成时显示有关多少个位置的消息。

COORD cxy;
#define posicion(x,y) {(cxy.X)= (x);(cxy.Y)= (y); SetConsoleCursorPosition((GetStdHandle(STD_OUTPUT_HANDLE)), (cxy) );}

int ajedrez[10][10];
int fila, columna;

void GenerarTablero(int m[10][10]){
    int i, j;
    for (i = 0; i < 10; i++){
        for (j = 0; j < 10; j++){
            m[i][j] = 0;
        }
    }
}

GenerarTablero制作棋盘并用0填充它。
全球是ajedrez [10] [10]的部分的丝(行)和columna(列) ajedrez [10] [10]是10x10大小的国际象棋桌。

void PosicionCaballo(int m[10][10]){
    printf("Fila: ");
    scanf_s("%d", &fila);
    printf("Columna: ");
    scanf_s("%d", &columna);
    printf("\n");

    m[fila][columna] = 2;
    system("cls");

}

PosicionCaballo确实要求用户提供马的初始位置并将马放在桌子上。
示例:行:5列:5

int horse(int y, int x)
{
    int visited[SIZE][SIZE] = { { 0 } };
    int count = 0;

    if (on_board(y, x) == 0) return -1;

    /* Set starting position */
    visited[y][x] = 1;

    while (1) {             /* Infinite loop - must use break */
        int poss[8];        /* Possible moves */
        int nposs = 0;      /* Actual length of poss */
        int i, k = 1;

        for (i = 0; i < 8; i++) {
            int xx = x + moves[i].x;
            int yy = y + moves[i].y;

            if (on_board(yy, xx) && visited[yy][xx] == 0) {
                poss[nposs++] = i;
            }
        }

        /* No more valid moves: return */
        if (nposs == 0){
            posicion(0, 11);
            printf("El tablero se ha bloqueado con ");
            return count;
        }

        /* pick one of the valid moves */
        i = poss[rand() % nposs];
        x = x + moves[i].x;
        y = y + moves[i].y;

        /* update horse's position */
        visited[y][x] = 1;
        count++;

        /* print position */

        posicion(y, x);
        printf("1");

    }

    return -1;      /* Should never be reached */
}

void MostrarMapa(int m[10][10]){
    int i, j;
    for (i = 0; i < 10; i++){
        for (j = 0; j < 10; j++){
            printf("%d", ajedrez[i][j]);
        }
        printf("\n");
    }
}

MostrarMapa仅在屏幕上打印国际象棋桌。

int main(void){

    int n;

    srand(time(NULL));
    GenerarTablero(ajedrez);
    PosicionCaballo(ajedrez);
    MostrarMapa(ajedrez);
    n = horse(fila, columna);
    posicion(31, 11);
    printf("%d movimientos\n", n);



    getch();
    return 0;
}

然后我的主要使用所有上述功能 非常感谢您提供帮助的人:)。

2 个答案:

答案 0 :(得分:1)

我猜你的任务是找到一个访问所有方块的有效路径。您的代码试图找到一个随机路径。

您的代码有几个错误:

  • 当您测试ajedrez[fila - 2][columna - 1]时,您不会检查fila - 2columna - 1是否是您棋盘的真正有效索引。如果访问无效索引,方式为-1或11,则调用未定义的行为。
  • 您不会更新filacolumna,即:您不会移动您的马。
  • 你两次覆盖董事会。这不是错误,但你的代码不应该做双重任务。
  • 你的随机选择被打破了。你有八个可能的动作,所以你想要rand() % 8,这会产生从0到7的数字。(David已经在评论中指出了这一点。)
  • 您的案例标签是特征常数,而不是数字。使用case 0:,而不是case '0':
  • 你只是跳过无效的动作。当没有更多有效的移动时,这将导致无限循环。您应检查此情况并在发生循环时终止循环。
  • 根据我的理解,'seicion`宏只是为了表明马是在哪里。也许你现在应该跳过它,只打印新的坐标,这不是那么漂亮,而是直截了当。

你的八个开关盒显示出另一个缺陷:你有八次相同的重复代码。唯一的区别是跳跃模式。这样的设置适合​​于编写一个函数来传递行和列的距离来跳转或者使用一组可能的跳转模式。

您的代码应该为每次移动执行类似的操作:

  • 遍历所有八种跳跃模式。如果马会从棋盘上跳下,或者马会访问已经访问过的瓷砖,请跳过这种可能性。否则,将移动添加到辅助阵列。
  • 如果可能性的数量为零,则终止循环 - 马无处可去。
  • 选择一个有效的举动。
  • 移动马,标记当前访问过的瓷砖。
  • 如果需要,报告跳转:打印新位置或放置光标,无论如何。

下面是一个使用跳转模式数组的示例实现。它将给出一个随机路径。您可以根据您的问题调整此代码。

#include <stdlib.h>
#include <stdio.h>
#include <time.h>       /* for time() */

#define SIZE 10         /* Fixed board size */

struct pos {
    int x, y;
};

struct pos moves[8] = {     /* Jump patterns */
    {1, 2}, 
    {2, 1}, 
    {2, -1},
    {1, -2},
    {-1, -2},
    {-2, -1}, 
    {-2, 1},
    {-1, 2}
};

/*  
 *      Is position (y, x) a valid board coordinate?
 */ 
int on_board(int y, int x)
{
    if (x < 0 || x >= SIZE) return 0;
    if (y < 0 || y >= SIZE) return 0;
    return 1;
}

/*
 *      Move the horse randomly, starting from (y, x). Print the
 *      visited fields and return the number of moves made or
 *      -1 if an error occurs.
 */
int horse(int y, int x)
{
    int visited[SIZE][SIZE] = {{0}};
    int count = 0;

    if (on_board(y, x) == 0) return -1;

    /* Set starting position */
    visited[y][x] = 1;
    printf("%c%d, ", 'A' + y, x + 1);

    while (1) {             /* Infinite loop - must use break */
        int poss[8];        /* Possible moves */
        int nposs = 0;      /* Actual length of poss */
        int i;

        for (i = 0; i < 8; i++) {
            int xx = x + moves[i].x;
            int yy = y + moves[i].y;

            if (on_board(yy, xx) && visited[yy][xx] == 0) {
                poss[nposs++] = i;
            }
        }

        /* No more valid moves: return */
        if (nposs == 0){
            printf("whoa!\n");
            return count;
        }

        /* pick one of the valid moves */
        i = poss[rand() % nposs];
        x = x + moves[i].x;
        y = y + moves[i].y;

        /* update horse's position */
        visited[y][x] = 1;
        count++; 

        /* print position */
        printf("%c%d, ", 'A' + y, x + 1);
    }

    return -1;      /* Should never be reached */
}

int main()
{
    int n;

    srand(time(NULL));

    n = horse(3, 6);    
    printf("%d moves\n", n);

    return 0;
}

答案 1 :(得分:0)

您似乎使用posicion()更新位置,但不更新fila和columna