C语言 Puzzle 15游戏/不可解的配置

dddzy1tm  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(126)

我正在和一些朋友做一个程序,但是我们在代码中遇到了一个问题,经常阻止我们测试它。我们正在制作一个Puzzle 15游戏,我们在单独的“functions.c”文件中制作了一个代码,在那里我们计算配置反转以检查初始板是否有解决方案。但由于某种原因,有时它仍然没有解决方案(我们检查所有这一切与一个单独的程序从互联网上解决游戏自动根据给定的董事会)。
我们尝试了几种替代方案来计算倒置和空白空间的位置,但它一直没有解决方案(注:这似乎是更有可能的程序,以给予董事会比无法解决的)。我希望你能帮助我找到错误,使代码只生成可解决的配置,从而促进开发时,测试游戏。下面是尽可能简化的代码:

// functions.c

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

#define ROWS 4
#define COLUMNS 4

// Print the matrix.
void printMatrix(int matrix[ROWS][COLUMNS]) {
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLUMNS; j++) {
            if (matrix[i][j] == 16) {
                printf("   ");  // Number 16 it's the empty space.
            } else {
                printf("%2d ", matrix[i][j]);
            }
        }
        printf("\n\n");
    }
}

// Function to count the inversions on the board.
int countInversions(int matrix[ROWS][COLUMNS]) {
    int inversions = 0;
    int elements[ROWS * COLUMNS];

    // Copy the matrix elements to a one-dimensional array.
    int k = 0;
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLUMNS; j++) {
            elements[k++] = matrix[i][j];
        }
    }

    // Count the inversions
    for (int i = 0; i < ROWS * COLUMNS - 1; i++) {
        for (int j = i + 1; j < ROWS * COLUMNS; j++) {
            if (elements[j] && elements[i] && elements[i] > elements[j]) {
                inversions++;
            }
        }
    }

    return inversions;
}

// Function to verify if the initial board configuration is resolvable.
bool itsSolvableConfiguration(int matrix[ROWS][COLUMNS]) {
    int inversions = countInversions(matrix);

    // Get the row containing the empty space.
    int rowEmptySpace = -1;
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLUMNS; j++) {
            if (matrix[i][j] == 16) {
                rowEmptySpace = i;
                break;
            }
        }
        if (rowEmptySpace != -1) {
            break;
        }
    }

    // Verify resolvability based on the position of the empty space and the number of inversions.
    return (rowEmptySpace % 2 == 0 && inversions % 2 == 0) || (rowEmptySpace % 2 != 0 && inversions % 2 != 0);
}

// Function to verify if the button entered by the user is valid.
bool itsValidChar(char button) {
    return (button == 'Y' || button == 'y' || button == 'S' || button == 's');
}


// main.c 

#include "functions.c"

int main(void) {
    int matrix[ROWS][COLUMNS];
    int numbers[16];
    int i, j, k, randomPivot;
    char answer;

    srand(getpid());

    printf("Puzzle 15\n\n");
    printf("CONTROLS:-Enter the number that is adjacent to the empty space to move it to the square.\n-Enter the key (Y) to restart or start the game.\n-Enter the key (S) to exit the game.");

    // Game start control - Board update.
    while (1) {
        printf("Load new game (Y to start / S to exit): ");
        scanf(" %c", &answer);
        for (int i = 0; i < 8; i++) {
                printf("\n");
        }

        if (!itsValidChar(answer)) {
            printf("\nInvalid key. Please choose a valid option.\n\n");
            continue;
        }

        if (answer == 'S' || answer == 's') {
            printf("\nThanks for playing!\n");
            break;
        }

        for (i = 0; i < 16; i++) {
            numbers[i] = i + 1;
        }

        // Randomizing positions with the Fisher-Yates algorithm.
        for (i = 16 - 1; i >= 0; i--) {
            j = rand() % (i + 1);
            randomPivot = numbers[i];
            numbers[i] = numbers[j];
            numbers[j] = randomPivot;
        }

        // The matrix is filled with random numbers.
        k = 0;
        for (i = 0; i < ROWS; i++) {
            for (j = 0; j < COLUMNS; j++) {
                matrix[i][j] = numbers[k++];
            }
        }

        // Verify if the initial board configuration is resolvable.
        if (!itsSolvableConfiguration(matrix)) {
            for (int i = 0; i < 15; i++) {
                printf("\n");
            }
            printf("The initial board configuration is not resolvable. Restart the game \nto obtain a valid configuration.");
            for (int i = 0; i < 12; i++) {
                printf("\n");
            }
        continue;
        }

        printf("Game started\n\n");

        for (int i = 0; i < 8; i++) {
                printf("\n");
        }

        // Function call to print the initial matrix.
        printMatrix(matrix);
        break;
    }

    return 0;
}

字符串

voase2hg

voase2hg1#

我不能说这是否是你的问题,但我查了一下规则,以确定是否一个谜15配置是可解的,只是为了确保。

  • 如果空白空间在从底部开始计数的奇数行上,并且反转的数量是偶数,则该配置是可解的。
  • 如果空白空间在从底部开始计数的偶数行上,并且反转的数量是奇数,则该配置是可解的。

这两个条件的关键点是“从底部计数”。在函数itsSolvableConfiguration中,for循环从矩阵的顶部开始。因此,如果空白空间位于顶部,则rowEmptySpace = 0。如果它位于第二行,则rowEmptySpace = 1。然后是2,然后是3。
反转循环行为的最简单方法是在它后面添加一行,就在函数返回之前。这将有效地将视角切换到从底部计数。

...
        break;
        }
    }
    // We count rows from the bottom, not from the top.
    rowEmptySpace = ROWS - rowEmptySpace;

    // Verify resolvability...
    return(rowEmptySpace...

字符串
我不能说这是否能解决你的问题,但我看到了一个问题。希望对你有帮助。

相关问题