簡體   English   中英

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

[英]How to use while more efficiently in 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;
        }
    }
}

自Edsger W. Dijkstra教授撰寫論文“發表聲明被認為有害”以來已經過去了近50年( ACM通訊11,3 ,1968年3月,第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

但是,此時進行任何微優化都是沒有用的。 最好找出完全不同的算法。

這些功能將查找沒有數字的位置,然后放置新數字。

我的建議是首先確定網格中的哪些單元格為空。 只需遍歷網格的一半(哪一部分取決於傳遞給函數的方向),然后將空的(或其索引)添加到候選列表(可以是數組...)。 其中最多有8個,這是一個非常小的域,必須是一個快速循環(或嵌套循環)。

如果沒有有效的候選者,則返回false,不添加任何數字。

否則,您可以提取介於0和候選數之間的隨機索引-1,以在它們之間選擇要更新的單元格。 由於上一步,您無需再次檢查它是否為空,只需提取介於1和2之間的數字即可用作新值並返回true。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM