0

如果可能的话,我怎样才能缩短这个?

if(moves[1] == moves[4] && moves[4] == moves[7]) { return 1;}
else if(moves[1] == moves[2] && moves[2] == moves[3]) { return 1;}
else if(moves[4] == moves[5] && moves[5] == moves[6]) { return 1;}
else if(moves[7] == moves[8] && moves[8] == moves[9]) { return 1;}
else if(moves[1] == moves[5] && moves[5] == moves[9]) { return 1;}
else if(moves[3] == moves[5] && moves[5] == moves[7]) { return 1;}
else if(moves[2] == moves[5] && moves[5] == moves[8]) { return 1;}
else if(moves[3] == moves[6] && moves[6] == moves[9]) { return 1;}
else if (moves[1] != '1' && moves[2] != '2' && moves[3] != '3' && moves[4] != '4' && moves[5] != '5' && moves[6] != '6' && moves[7] != '7' && moves[8] != '8' && moves[9] != '9') {
return 2;}

在值 move 中存储了一个 X 或 0 进行比较以获得游戏的获胜者我需要尽可能缩短它,

由于数字的随机组合,我想不出任何其他方式来做到这一点

上面的代码是一个名为 CheckWinner 的函数,它传递用户选择的输入,其中包含已填充的位置数组

代码检查 move[position] 与获胜移动的所有其他组合,如果检测到获胜移动,则返回 1。

最后一段代码检查网格上的所有空格,如果没有空格,则返回 2 以调用绘图。

希望这可以帮助

4

7 回答 7

3

像这样的东西怎么样:

#include <stdio.h>

int winners[8][3] = { {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9},
            {1, 4, 7},
            {2, 5, 8},
            {7, 8, 9},
            {1, 5, 9},
            {3, 5, 7}};

int moves[10] = { 0,
          1, 2, 0,
          0, 2, 0,
          0, 2, 1};

int main()
{
    int i;
    for (i=0;i<8;++i)
    {
        if (moves[winners[i][0]] == moves[winners[i][1]] &&
            moves[winners[i][1]] == moves[winners[i][2]])
            printf("Player %d wins!\n",moves[winners[i][0]]);
    }
    return 0;
}

获胜者数组描述了各种获胜组合,并对它们中的每一个进行循环测试。

于 2013-05-06T23:33:27.183 回答
2

并非所有数字都是随机的...对于行,公式是N*3+1, N*3+2, N*3+3,对于列N+1, N+4, N+7等...其中0 <= N <= 2。许多其他方式来表示它。您可以创建单独的函数来检查行、列和对角线。

于 2013-05-06T23:19:50.883 回答
1
template <typename T> bool equal(T a, T b, T c) { return (a==b) && (b==c); }

int foo(char (&moves)[10])
{
    auto eqset = [&](int i1, int i2, int i3) { return equal(moves[i1], moves[i2], moves[i3]); };
    if (eqset(1,4,7) || eqset(1,2,3) || eqset(4,5,6) || eqset(7,8,9) || eqset(1,5,9) || eqset(3,5,7) || eqset(2,5,8) || eqset(3,6,9))
        return 1;
    else if (moves[1] != '1' && moves[2] != '2' && moves[3] != '3' && moves[4] != '4' && moves[5] != '5' && moves[6] != '6' && moves[7] != '7' && moves[8] != '8' && moves[9] != '9') {
        return 2;
    }
}

与文字发布的代码非常接近。请注意,并非所有代码路径都返回一个值,这就是我在这里停下来的原因。

否则,您可以继续执行以下操作:

for (int i = 1; i<10; i++)
    if (moves[i] == ('0'+i))
        return 0; // ???

return 2;
于 2013-05-06T23:33:02.013 回答
1

只需检查最后一次播放的行、列和可能的对角线。您无需检查整个网格。

还要使用二维数组,因为您要存储一个grid。然后循环查找匹配的行,循环查找匹配的列。

于 2013-05-06T23:24:17.550 回答
0

您可以使用宏简单地缩短代码:

#define comp(i,j,k) (moves[i]==moves[j] && moves[j]==moves[k])
return comp(1,2,3) || comp(4,5,6) || comp(7,8,9)
    || comp(1,5,9) || comp(3,5,7) || comp(2,5,8);

否则,您可以旋转电路板:

#define comp(i,j,k) (moves[i]==moves[j] && moves[j]==moves[k])

int rot[6][2] = { {1, 3}, {7, 9}, {9, 1}, {2, 6}, {4, 8}, {2, 8} };
for (int x = 0; x < 4; x++) {
    if (comp(1,2,3) || comp(4,5,6) || comp(1,5,9)))
        return 1;
    for (int i = 0; i < 6; i++)
        std::swap(moves[rot[i][0]], moves[rot[i][1]]);
}
return 0;

这是完整的 C++ 代码,带有解释(很容易是简单的 C,而不是 C++,但我喜欢std::swap)。该板包含无意义的数字,因此您可以看到旋转:

#include <iostream>

void print_tic(int moves[]) {
    for (int i = 1; i < 10; i += 3)
        std::cout << moves[i] << moves[i + 1] << moves[i + 2] << std::endl;
    std::cout << std::endl;
}

void rotate(int moves[]) {
    static const int rot[6][2] = {{1, 3}, {7, 9}, {9, 1}, {2, 6}, {4, 8}, {2, 8} };
    for (int i = 0; i < 6; i++)
        std::swap(moves[rot[i][0]], moves[rot[i][1]]);
}

int comp(int moves[], int i, int j, int k) {
    return moves[i]==moves[j] && moves[j]==moves[k];
}

int main() {
    int moves[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //meaningless.

    print_tic(moves);
    for (int x = 0; x < 4; x++) {
        rotate(moves);
        print_tic(moves);
        if (comp(moves, 1,2,3)  // first row
             || comp(moves, 4,5,6)  // second row - forget that earlier
             || comp(moves, 1,5,9)) // main diagon
            return 1;
    }
    return 0;
}

通过打印,您可以看到旋转:

123
456
789

741
852
963

987
654
321

369
258
147

123
456
789

您只能旋转一次,comp()而第三行则需要多旋转一次。

于 2013-05-07T01:55:24.403 回答
0

这可以检查是否获胜……您可能会说它“更短”。

// Check rows and columns
for( int i = 0; i < 3; i++ ) {
    char *row = &moves[3*i+1];
    char *col = &moves[i+1];
    if( row[0] == row[1] && row[0] == row[2] ) return 1;
    if( col[0] == col[3] && col[0] == col[6] ) return 1;
}

// Check diagonals
if( moves[1] == moves[5] && moves[1] == moves[9] ) return 1;
if( moves[3] == moves[5] && moves[3] == moves[7] ) return 1;

还有很多其他方法可以做到这一点。一种方法是简单地为每一行、每一列和对角线保留一个计数器。如果出现交叉,则将相关计数器加 1。如果打出 naught,则从相关计数器中减去 1。如果任何计数器达到 3 或 -3,则游戏获胜。每次播放都需要很少的操作。无需检查整个电路板。

于 2013-05-06T23:38:49.230 回答
0

我不确定这会有所帮助,但我会试一试:我现在在您的代码中看到的是,您的大多数条件返回 1,只有在一种情况下您返回 2。所以我只写 if 条件返回 2,在所有其他情况下返回 1,不是吗?

例如

if (moves[1] != '1' && moves[2] != '2' && moves[3] != '3' && moves[4] != '4' && moves[5] != '5' && moves[6] != '6' && moves[7] != '7' && moves[8] != '8' && moves[9] != '9') {
return 2;}
else
{
// return 1 probably
}

嗯...不,我在上面的代码中收回我的话,所有其他情况都将返回 1 而在您的情况下,可能存在您不希望返回 1 的情况...

于 2013-05-06T23:19:13.520 回答