我正在尝试用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;
}
}
}
答案 0 :(得分:0)
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_device
和std::mt19937
。
此时进行任何类型的微优化都是无用的。找出一个完全不同的算法要好得多。
这些功能即将找到一个没有数字的地方 然后放置新号码。
我的建议是首先确定网格的哪些单元格是空的。只遍历网格的一半(该部分,取决于传递给函数的方向),并将空的(或它们的indeces)添加到候选列表(可能是数组......)中。其中有8个,它是一个非常小的域,它必须是一个快速循环(或嵌套循环)。
如果没有任何有效的候选人,则返回false,不添加任何数字。
否则,您可以提取0和候选数量之间的随机索引 - 1在它们之间选择要更新的单元格。您不需要再次检查它是否为空,由于上一步,只需提取1到2之间的数字以用作新值并返回true。