C++ Tetris: функция, удаляющая строки

Я изучал этот учебник по тетрису и наткнулся на функцию, которая удаляет строки и опускает строки на один уровень. Я вроде понимаю, что происходит с этими функциями, но некоторые части меня смущают. Я постараюсь объяснить как можно лучше, но вот ссылка на урок, если он вам нужен: http://javilop.com/gamedev/tetris-tutorial-in-c-platform-independent-сфокусированная-в-игровой-логике-для-начинающих/

Для меня это выглядит как функция, которая заставляет массив начинаться с последнего номера строки:

void Board::DeleteLine (int pY)
{
    // Moves all the upper lines one row down
    for (int j = pY; j > 0; j--)
    {
        for (int i = 0; i < BOARD_WIDTH; i++)
        {
            mBoard[i][j] = mBoard[i][j-1];
        }
    }   
}

Затем есть функция, которая вызывает у меня проблемы, которую я объясню:

void Board::DeletePossibleLines ()
{
    for (int j = 0; j < 20; j++)
    {
        int i = 0;
        while (i < 10)
        {
            if (mBoard[i][j] != 1) break;
            i++;
        }

        if (i == 10) DeleteLine (j);
    }
}

Если вы не знакомы, идея состоит в том, чтобы удалить строку, полностью состоящую из 1. Но if (mBoard[i][j] != 1) break; остановит цикл, если первая строка не будет 1. Как цикл достигнет 1, находящегося где-то в середине массива mBoard[][], если break не позволит ему сразу сделать что-либо возможное?

Я что-то упустил здесь? Это моя интерпретация этого. Может быть, кто-то видит то, чего не вижу я?

Изменить:

Спасибо за ответы, ценю.


person longAD    schedule 14.08.2014    source источник
comment
Кстати, более чистая реализация будет иметь bool Board::IsLineFull(int j) const. Итак, цикл будет содержать только if (IsLineFull(j)) { DeleteLine(j); }   -  person Jarod42    schedule 14.08.2014
comment
@longAD для этого создайте новый вопрос, пожалуйста   -  person CodeFanatic    schedule 14.08.2014
comment
Все в порядке, Феликс. Я поменял переменную i на переменную j, и все заработало, как я и ожидал. Либо первоначальный автор ошибся, либо, что более вероятно, он перепутал ширину и высоту своей доски.   -  person longAD    schedule 14.08.2014


Ответы (3)


Вы также можете структурировать код следующим образом:

for (int j = 0; j < 20; j++)
{
 int i = 0;
    while (i < 10)
    {
        if (mBoard[i][j] != 1) 
        {
            break; //only breaks the while loop and will continue with if (i == 10)
        }
        else 
        {
            i++;
        }
    }

    if (i == 10)
    {
        DeleteLine (j);
    }
}

Теперь вы можете ясно видеть, что break; прерывает только ваш цикл while, но не ваш цикл for.

person CodeFanatic    schedule 14.08.2014
comment
@Квентин Действительно. Цитата: Я что-то пропустил? Моя цель — прояснить код, а не использовать шаблоны проектирования и сказать, как это нужно делать. Это был не вопрос - person CodeFanatic; 14.08.2014
comment
@FelixLahmer: я не вижу разъяснения вашей версии (и ваш отступ хуже, чем исходный код). - person Jarod42; 14.08.2014
comment
@ jarod42, когда я изучал кодирование, у меня были проблемы с пониманием кода, когда не было скобок после if и т. д. - person CodeFanatic; 14.08.2014
comment
Используйте скобки, если хотите (я тоже предпочитаю всегда иметь скобки), но правильно форматируйте свой код, чтобы четко идентифицировать ваш блок. - person Jarod42; 14.08.2014

Разрыв выскочит из цикла while. Таким образом, если вы встретите строку, в которой где-то посередине есть не-1, i будет индексом в строке, а цикл for продолжится со следующей строки (j), снова начиная с i=0.

person glezmen    schedule 14.08.2014

break прерывает только один цикл, цикл while в вашем случае. Цикл for успешно продолжается.

Кстати, этот while можно легко (и нужно) преобразовать в for и сжать в соответствии с узнаваемым шаблоном for-if-break:

for (int j = 0; j < 20; ++j)
{
    int i;
    for(i = 0; i < 10 && mBoard[i][j] == 1; ++i);

    if (i == 10) DeleteLine (j);
}
person Quentin    schedule 14.08.2014
comment
На самом деле цикл while должен быть методом. А для переменной со временем жизни больше, чем у цикла, цикл for не обязательно более читабелен (особенно с пустым телом). - person Jarod42; 14.08.2014
comment
@ Jarod42 небольшое редактирование. Сжатие цикла было просто предложением, но это действительно не то, что нужно делать, если вы не знакомы с этим шаблоном. - person Quentin; 14.08.2014