C-如何检查谁赢得了Ox的NxN游戏?

时间:2018-07-14 20:26:10

标签: c arrays

我正在打井字游戏。

我有一个功能,可以在每步动作之后寻找赢家...

功能如下 int won(char sym) 其中char sym是玩家字母,例如X或O。

我的游戏可以在3-8的任何尺寸的木板上进行,例如(3z3-8x8) 并基于名为 S [] [] 的二维数组 大小也由用户选择,并存储在可验证的 int Scale 中。(全局可验证)

我如何检查玩家是否获胜?(如果行,列或对角线全都相同) 我只是惊艳,因为我不知道如何使它适用于任何尺寸的桌子。

请帮助!!!!!!

2 个答案:

答案 0 :(得分:0)

您可以检查水平,垂直和对角线。此行与数组的大小无关。

答案 1 :(得分:-1)

您应该能够在O(n)中进行操作,其中n是平方数,而不是传统的3x3,而不是O(1),并且只需对结构进行任何修改通过检查每个正方形。您只需要检查一个方向,因为它是可交换的。像这样的东西

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

struct Tic {
    unsigned size;
    char board[65];
};

static const char is_valid[] = "XO ";

/** This is a strict parser.
 @param tic Overwriten with stdin on success. On failure, is corrupted.
 @return Success.
 @throws EDOM if the file is not correct, fgets, getc. */
static int load(struct Tic *const tic) {
    char s[10];
    size_t s_len, row = 0;
    int is_size = 0;
    assert(tic);
    errno = 0;
    tic->board[0] = '\0';
    do {
        if(!fgets(s, sizeof s, stdin)) return errno ? 0 : (errno = EDOM, 0);
        if(s_len = strcspn(s, "\n\r\f"), s_len != strspn(s, is_valid))
            return errno = EDOM, 0;
        if(is_size) {
            if(s_len != (size_t)tic->size) return errno = EDOM, 0;
        } else {
            if(s_len < 3 || s_len > 8) return errno = EDOM, 0;
            tic->size = (unsigned)s_len;
            is_size = 1;
        }
        s[s_len] = '\0';
        strcat(tic->board, s);
    } while(++row < tic->size);
    /* Enforce EOF. */
    if(getc(stdin) != EOF) return errno = EDOM, 0; else if(errno) return 0;
    return 1;
}

/** Doesn't do bounds checks; should be inlined. */
static int is_owned(const struct Tic *const tic,
    const size_t x, const size_t y, const char sym) {
    return tic->board[y * tic->size + x] == sym;
}

/** @param tic A valid tic-tac-toe.
 @param sym Either X or O.
 @return Whether sym has won the game. */
static int won(const struct Tic *const tic, const char sym) {
    const size_t size = tic->size;
    size_t x, y;
    int is_x, is_y;
    assert(tic && (sym == 'X' || sym == 'O'));
    for(y = 0; y < size; y++) {
        for(x = 0; x < size; x++) {
            if(!is_owned(tic, x, y, sym)) continue;
            is_x = x < size - 2 ? 1 : 0;
            is_y = y < size - 2 ? 1 : 0;
            /* There are 3 cases. */
            if(is_x && is_owned(tic, y, x + 1, sym)
                && is_owned(tic, y, x + 2, sym)) return 1;
            if(is_y && is_owned(tic, y + 1, x, sym)
                && is_owned(tic, y + 2, x, sym)) return 1;
            if(is_x && is_y && is_owned(tic, y + 1, x + 1, sym)
               && is_owned(tic, y + 2, x + 2, sym)) return 1;
        }
    }
    return 0;
}

int main(void) {
    struct Tic tic;
    if(!load(&tic)) return perror("stdin"), EXIT_FAILURE;
    printf("Xs won? %s.\n", won(&tic, 'X') ? "yes" : "no");
    return EXIT_SUCCESS;
}

我认为这是有效的,但可能需要更多测试。

*这是假设条件在一条直线上有3个条目。例如,won需要对其进行编辑才能更改3 -> n

static int won_row(const struct Tic *const tic, const size_t y,
    const char sym) {
    const size_t size = tic->size;
    size_t x;
    for(x = 0; x < size; x++) if(!is_owned(tic, x, y, sym)) return 0;
    return 1;
}

static int won_col(const struct Tic *const tic, const size_t x,
    const char sym) {
    const size_t size = tic->size;
    size_t y;
    for(y = 0; y < size; y++) if(!is_owned(tic, x, y, sym)) return 0;
    return 1;
}

static int won_diag(const struct Tic *const tic, const char sym) {
    const size_t size = tic->size;
    size_t x;
    for(x = 0; x < size; x++) if(!is_owned(tic, x, x, sym)) return 0;
    return 1;
}

static int won_anti_diag(const struct Tic *const tic, const char sym) {
    const size_t size = tic->size;
    size_t x;
    for(x = 0; x < size; x++) if(!is_owned(tic, x, size - x - 1, sym)) return 0;
    return 1;
}

/** @param tic A valid tic-tac-toe.
 @param sym Either X or O.
 @return Whether sym has won the game. */
static int won(const struct Tic *const tic, const char sym) {
    const size_t size = tic->size;
    size_t x, y;
    assert(tic && (sym == 'X' || sym == 'O'));
    /* These do a short-circuit evaluation. */
    for(y = 0; y < size; y++) if(won_row(tic, y, sym)) return 1;
    for(x = 0; x < size; x++) if(won_col(tic, x, sym)) return 1;
    return won_diag(tic, sym) || won_anti_diag(tic, sym);
}