如何在C ++中更有效地使用?

时间:2017-09-04 15:24:24

标签: c++

我正在尝试用C ++编写2048游戏,我创建了一些函数,在检测到用户按下箭头后,在随机位置添加一个新的随机数。这些功能即将找到一个没有数字的地方,然后放置新号码。我试着这样做。一种是愚蠢的,在很多情况下使用,而另一种只是使用,而在我运行这个游戏时工作缓慢。我是C ++的新手。我希望有人能帮助我找到更好的解决方案。 以下是这些代码:

bool add_new_number_when_up()
{
    srand(time(NULL));
    int n = rand() % 2 + 1;
    int newnumber = pow(2, n);
    while(true) {
        if(check_up_move() == 1) {
            loop:
            int a = rand() % 8;
            switch(a) {
            case 0:
                if(grid[2][0] == 0) {
                    grid[2][0] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 1:
                if(grid[2][1] == 0) {
                    grid[2][1] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 2:
                if(grid[2][2] == 0) {
                    grid[2][2] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 3:
                if(grid[2][3] == 0) {
                    grid[2][3] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 4:
                if(grid[3][0] == 0) {
                    grid[3][0] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 5:
                if(grid[3][1] == 0) {
                    grid[3][1] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 6:
                if(grid[3][2] == 0) {
                    grid[3][2] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            case 7:
                if(grid[3][3] == 0) {
                    grid[3][3] = newnumber;
                    return false;
                }
                else {
                    goto loop;
                }
                break;
            }
        }
        else {
            return false;
        }
    }
}

这是另一个:

void test_if_zero(int row, int col) 
{
    srand(time(NULL));
    int n = rand() % 2 + 1;
    int newnumber = pow(2, n);
    if(grid[row][col] == 0) {
        grid[row][col] = newnumber;
    }
}

int check_empty()
{
    int flag = 0; 
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++) {
            if(grid[i][j] == 0) {
                flag = 1;
                return flag;
            }
        }
    }
}

bool add_new_number(int num)
{
    Loop:
    int row, col;
    srand(time(NULL));
    switch(num) {
    case 1: //up
        row = rand() % 2 + 2;
        col = rand() % 4;
        break;
    case 2: //down
        row = rand() % 2;
        col = rand() % 4;
        break;
    case 3: //left
        row = rand() % 4;
        col = rand() % 2 + 2;
        break;
    case 4: //right
        row = rand() % 4;
        col = rand() % 2;
        break;
    }
    while(true) {
        if(check_empty() == 1) {
            if(grid[row][col] == 0) {
                test_if_zero(row, col);
                return false;
            }
            else {
                goto Loop;
            }
        }
        else {
            break;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

自从Edsger W. Dijkstra教授写了他的论文“Go To Statement Considered harmful”( ACM的通讯 11,3,1968年3月,几乎 50 以来, p.147-148。)并且仍然可以找到对该结构的不合理使用。

OP的第一个片段可以夏天化:

bool add_new_number_when_up()
{
    // ...
    while(true) {
        if( /* some unexplained condition */ ) {
            loop:                    // <- "loop" start
            int a = rand() % 8;
            switch(a) {
            case 0:
                if( /* something */ ) {
                    // ...
                    return false;
                }
                else {
                    goto loop;      // <- "loop" end
                }
                break;              // never reached...
            // many other cases...
            }
        }
        else {
            return false;
        }
    }
}

除了缺少任何return true之外,其中可能(但实际上不应该)重写为

bool add_new_number_when_up()
{
    // ...
    while(true) {
        if( /* some unexplained condition */ ) {
            while(true) {                    // <- nested loop!
                int a = rand() % 8;
                switch(a) {
                case 0:
                    if( /* something */ ) {
                        // ...
                        return false;        // true?
                    }
                    break;                   // <- restart the loop...
                // many other cases...
                }
            }            
        }
        else {
            return false;
        }
    }
}

将无限循环写为loop: ... goto loop;而不是while(1) {...}并不会让它神奇地加速,但它肯定会使代码混淆,而且更容易出错。

第二个片段更糟糕:

bool add_new_number(int num)
{
    Loop:                      // <- what kind of loop is this?
    // some expansive function which shouldn't be here...
    // ... 
    while(true) {
        if( /* call to another relatively expansive function */ ) {
            if( /* some condition */ ) {
                // call to another expansive function...
                return false;
            }
            else {
                goto Loop;          // <- end of loop?
            }
        }
        else {
            break;
        }
    }
}           // <- a return statement is missing!
OP抱怨这段代码的缓慢,考虑到整体设计和涉及的功能,这并不令人惊讶。

例如,有多个srand的调用,它们不仅是扩展的,而且在整个程序中一个调用也不必要,为伪随机数生成器播种,就足够了。即使是“现代”<random>生成器也是如此,例如std::random_devicestd::mt19937

此时进行任何类型的微优化都是无用的。找出一个完全不同的算法要好得多。

  

这些功能即将找到一个没有数字的地方   然后放置新号码。

我的建议是首先确定网格的哪些单元格是空的。只遍历网格的一半(该部分,取决于传递给函数的方向),并将空的(或它们的indeces)添加到候选列表(可能是数组......)中。其中有8个,它是一个非常小的域,它必须是一个快速循环(或嵌套循环)。

如果没有任何有效的候选人,则返回false,不添加任何数字。

否则,您可以提取0和候选数量之间的随机索引 - 1在它们之间选择要更新的单元格。您不需要再次检查它是否为空,由于上一步,只需提取1到2之间的数字以用作新值并返回true。