有没有更简单的方法来表示C++中的条件?

Bug*_*ter 2 c++ language-features

我写了一个基于多维数组的基本tic-tac-toe游戏.克[3] [3].在我的程序中,我有大约9个条件,比如我要向您展示的条件:

if((g[0][0] == X && g[0][1] == X && g[0][2] == X) || (g[0][0] == O && g[0][1] == O && g[0][2] == O))
Run Code Online (Sandbox Code Playgroud)

这太疯狂了.我可能做错了,但这就是为什么我要解决这个问题.是否有更简单的方法来表示像这样的长而复杂的条件?例如我不能以某种方式做:

if(grid.hasXes)
Run Code Online (Sandbox Code Playgroud)

Jam*_*nze 6

你可能会以错误的方式去做.只有3 ^ 9或19683种可能的组合,因此int即使在16位机器上也可以将网格转换为:

int
asInt( char const (&grid)[3][3] )
{
    int results = 0;
    for ( int i = 0; i != 3; ++ i ) {
        for ( int j = 0; j != 3; ++ j ) {
            results *= 3;
            switch ( grid[i][j] ) {
            case 'X':
                results += 1;
                break;

            case 'Y':
                results += 2;
                break;

            case ' ':
                break;

            default:
                assert(0);
            }
        }
    }
    return results;
}
Run Code Online (Sandbox Code Playgroud)

之后,您可以使用int索引到表中谁赢了(如果有人).或者,您可以将一个或另一个玩家的位置转换为9位int:

int
asInt( char const (&grid)[3][3], char who )
{
    int results = 0;
    for ( int i = 0; i != 3; ++ i ) {
        for ( int j = 0; j != 3; ++ j ) {
            results *= 2;
            if ( grid[i][j] == who ) {
                ++ results;
            }
        }
    }
    return results;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用简单的线性搜索到表中,验证是否设置了必要的位:

static int const wins[] =
{
    0007, 0070, 0700,       //  rows
    0111, 0222, 0444,       //  columns
    0124, 0421              //  diagonals
};

class Wins
{
    int myToMatch;
public:
    Wins( char const (&grid)[3][3], char who )
        : myToMatch( asInt( grid, who ) )
    {
    }
    bool operator()( int entry ) const
    {
        return (entry & myToMatch) == entry;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后:

if ( std::find_if( begin( wins ), end( wins ), Wins( grid, 'X' ) )
            != end( wins ) {
    //  X wins
else if ( std::find_if( begin( wins ), end( wins ), Wins( grid, 'O' ) )
            != end( wins ) {
    //  O wins
else
    //  play another turn.
Run Code Online (Sandbox Code Playgroud)

您甚至可以考虑将网格保持为两个int,每个玩家一个.位置的位数将是3 * i + j,并测试移动是否合法:

bool
isLegal( int gridX, int gridY, int i, int j )
{
    return ((gridX | gridY) & (1 << (3 * i + j))) == 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @ThePlan一点也不.看到这种可能性很大程度上取决于经验.获得这种体验和学习的唯一方法就是提出这样的问题.我认为这是一个很好的问题; 这就是为什么我付出一些努力来思考我认为是一个好答案的原因.(除非你过去做过类似的事情,否则最后的抨击技术不会发生在你身上.) (2认同)