我正在打井字游戏。
我有一个功能,可以在每步动作之后寻找赢家...
功能如下 int won(char sym) 其中char sym是玩家字母,例如X或O。
我的游戏可以在3-8的任何尺寸的木板上进行,例如(3z3-8x8) 并基于名为 S [] [] 的二维数组 大小也由用户选择,并存储在可验证的 int Scale 中。(全局可验证)
我如何检查玩家是否获胜?(如果行,列或对角线全都相同) 我只是惊艳,因为我不知道如何使它适用于任何尺寸的桌子。
请帮助!!!!!!
答案 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);
}