Почему мой блок if-else никогда не получит удар, хотя так и должно быть?(Просто нужна еще пара глаз.) - PullRequest
2 голосов
/ 11 мая 2011

Я делаю игру в стиле Falling Sand на Java, и у меня странные проблемы с блоком if-else, который у меня есть.В моем методе doGravity () у меня есть различные блоки условий, которые будут вызывать разные вещи, и по какой-то странной причине один блок НИКОГДА не получает удар.

Когда у меня есть этот блок, подсчитайте, сколько развыполняется каждое условие, левый и правый блоки поражаются почти равномерно:

else if(world[x][y+1]==EMPTY && (x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
    int r = rand.nextInt(50);
    if(r == 0) {
        world[x-1][y+1] = world[x][y];
        //System.out.println("GO: right");
        countRight++;
    }
    else if(r == 1) {
        world[x+1][y+1] = world[x][y];
        //System.out.println("GO: left");
        countLeft++;
    }
    else {
        world[x][y+1] = world[x][y];
        countCenter++;
    }
    world[x][y] = EMPTY;
}

Далее следует это условие, которое также в равной степени распределяет левое и правое.

else if((x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
    if(rand.nextBoolean()) {
        world[x-1][y+1] = world[x][y];
        //countLeft++;
    }
    else {
        world[x+1][y+1] = world[x][y];
        //countRight++;
    }
    world[x][y] = EMPTY;
}

Но когда я считаюВ этих блоках левый блок НИКОГДА не получает удар, даже когда пространство слева открыто .Я чувствую, что это просто глупая опечатка, которую я почему-то не вижу.

else if((x-1 >= 0) && world[x-1][y+1] == EMPTY) {
    world[x-1][y+1] = world[x][y];
    world[x][y] = EMPTY;
    countLeft++;
    System.out.println("Hit Left");
}
else if((x+1 < world.length) && world[x+1][y+1] == EMPTY) {
    world[x+1][y+1] = world[x][y];
    world[x][y] = EMPTY;
    countRight++;
    System.out.println("Hit Right");
}

ОБНОВЛЕНИЕ: Если я в конце выделю блок left, то совершенно точноничего не меняется.Песок действует точно так же.Если в конце я выделю блок right, он будет действовать так же, как если бы я выделил оба блока.Я не могу понять это.Это должно работать ... но это не так.

ОБНОВЛЕНИЕ: Вот полный исходный код.Я понятия не имею, что это может быть.Это на самом деле сведет меня с ума.http://pastebin.com/mXCbCvmb

Ответы [ 3 ]

2 голосов
/ 11 мая 2011

Ваш код для вставки показывает «Hit left», вам просто нужно изменить создание мира (строка 65 pastebin) на

    world = new Color[worldWidth][worldHeight+1];

Из-за части y + 1, которую я предположил бы. Кроме этого он растет как влево, так и вправо.

РЕДАКТИРОВАТЬ: http://pastebin.com/GVmSzN4z Я немного вертел с вашей doGravity, чтобы сделать капли немного более симметричными.

1 голос
/ 11 мая 2011

Я не вижу ничего странного в размещенном коде ... однако "else" в начале второго блока заставляет меня думать, что, вероятно, вышеупомянутое условие выполняется в случаях, когда insted вы хотели бы обработать«левый» чехол.Какое состояние в if до этой части?

EDIT

После проверки вашего полного исходного кода я наконец-то нашел, где проблема.Ваша doGravity функция обновления всегда идет влево-> вправо, и это вносит асимметрию.Изменяя его так, чтобы направление обновления чередовалось между левым - правым и правым -> левым для нечетных / четных линий сканирования, асимметрия исчезает.

private void doGravity() {
    for(int i = worldHeight - 1; i >= 0; i--) {
        if (i % 2 == 0)
        {
            for(int j = 0; j < worldWidth; j++) {
                if(world[j][i] != EMPTY) {
                    if(hasGravity(world[j][i])) {
                        dropParticle(j, i);
                    }
                }
            }
        } 
        else
        {
            for(int j = worldWidth-1; j >= 0; --j) {
                if(world[j][i] != EMPTY) {
                    if(hasGravity(world[j][i])) {
                        dropParticle(j, i);
                    }
                }
            }
        }
    }
}
0 голосов
/ 11 мая 2011

Я загрузил ваш код из paste bin, первым делом я извлек этот метод и использовал его вместо проверки всех встроенных ячеек массива, чтобы я мог установить точку останова и посмотреть, какие значения для x и y и каково было содержимое этой индексированной ячейки.

private boolean isEmpty(final int x, final int y)
{
    return world[x][y] == EMPTY;
}

Я бы извлек все проверки EMPTY в нечто более читаемое, например isLeftEmpty(x,y) и isRightEmpty(x,y) и isNextLeftEmpty(x,y), это поможет вам понять правильность вашей логики в вашем коде.

Я бы также извлек (x + 1 < world.length) в isNextXOutsideWorld(x), это поможет документировать ваши намерения и поможет в обосновании логики, которую вы намереваетесь.

У этого также есть побочный эффект упрощения логики в операторах if/elseif/else.

Я сделал небольшую отладку и позволил ей работать в течение нескольких минут, и пришел к выводу, что следующая строка всегда соответствует и заменяет следующую else if инструкцию.

else if ((x + 1 < world.length) && isEmpty(x + 1, y + 1) && 
         (x - 1 >= 0) && isEmpty(x - 1,y + 1))

всегда верно, когда я запускаю его, поэтому оно никогда не достигает следующего оператора

else if ((x - 1 >= 0) && isEmpty(x - 1,y + 1))

Я бы попытался разбить каждое из else/if выражений на вызовы методов с описательными именами и просто все их по порядку, используя шаблон Strategy, поскольку все они взаимоисключающие. Этот большой метод определенно является запахом кода, в сочетании со всеми этими else/if блоками, вонючий коэффициент высок.

Очень трудно экстраполировать, каково ваше предполагаемое поведение, из всего шума в if/elseif/else блоках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...