需要缩短C ++代码

时间:2013-05-06 23:12:34

标签: c++ tic-tac-toe

如果有可能,我可以缩短它吗?

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;}

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

由于数字的随机组合

,我无法想到以其他方式做到这一点

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

代码检查移动[位置]与获胜移动的所有其他组合,如果已检测到获胜移动则返回1.

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

希望这有帮助

7 个答案:

答案 0 :(得分: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;
}

阵列获胜者描述了各种获胜组合以及每个组合的循环测试。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

由于您正在存储网格,因此也使用二维数组。然后循环遍历行以查找匹配项,并遍历列以查找匹配项。

答案 3 :(得分: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;

答案 4 :(得分:0)

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

e.g。

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被退回的情况......

答案 5 :(得分: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,则赢得游戏。每次播放需要非常少量的操作。无需检查整个电路板。

答案 6 :(得分: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()的展开处。