Логические значения циклы while =?

#c# #boolean #while-loop

#c# #логическое #цикл while

Вопрос:

У меня странная проблема с приведенным ниже кодом (я удалил части, которые не имеют отношения к делу, и все классы / функции, на которые ссылаются, работают должным образом):

 int curNumRooms = 0;

while(curNumRooms < numberOfRooms) {
    int w = Random.Range(minimumRoomSize, maximumRoomSize 1);
    int h = Random.Range(minimumRoomSize, maximumRoomSize 1);

    int x = Random.Range(0, (int)levelSize.x - w - 1);
    int y = Random.Range(0, (int)levelSize.y - h - 1);          

    Rectangle newRoom = new Rectangle(x,y,w,h);

    bool failed = false;

    foreach (Rectangle otherRoom in rooms) {
        if(otherRoom != null) {                 
            if (newRoom.Intersect(otherRoom)) {
                failed = true;
                break;
            }
        }
    }

    if (!failed) {          
        rooms[curNumRooms] = newRoom;
        curNumRooms  ;
    }

}
  

По какой-то причине ошибка всегда оценивается как true. Я ввел пару отладочных сообщений, и, как ни странно, ошибка выполняется дважды — в первый раз, в цикле foreach, она выполняется правильно. Во второй раз он принимает значение false. Если я не смог инициализировать значение true, то во второй раз оно будет равно true, почти как если бы цикл while выполнялся дважды и во второй раз игнорировался цикл foreach.

Почему это?


ПРАВКА 1: Вот мой класс Rectangle и соответствующие переменные:

 public class Rectangle {
        public int x1;
        public int y1;
        public int x2;
        public int y2;

        public bool Intersect(Rectangle other) {
            return (x1 <= other.x2 amp;amp; x2 >= other.x1 amp;amp; y1 <= other.y2 amp;amp; y2 <= other.y1);      
        }

        public Rectangle(int x, int y, int w, int h) {
            this.x1 = x;
            this.x2 = x w;
            this.y1 = y;
            this.y2 = y   h;
        }

        public Rectangle() {

        }

        public Vector2 Center() {
            int centerX = (x1   x2) / 2;
            int centerY = (y1   y2) / 2;

            Vector2 center = new Vector2(centerX, centerY);

            return center;
        }
    }
  

Вот переменные, которые я использовал:

 public Vector2 levelSize = new Vector2(80,30);
public int maximumRoomSize = 10;
public int minimumRoomSize = 5;
  

Комментарии:

1. Каковы другие Rect значения в rooms ?

2. Как выглядит ваша функция Intersect? Каковы значения minRoomSize,maxRoomSize и levelSize перед вводом этого сегмента кода? Без этой информации трудно сказать, почему ваша функция Intersect всегда возвращает true.

3. @FreeAsInBeer, просто больше прямоугольников, созданных в том же цикле while и добавленных в rooms массив. rooms[curNumRooms] = newRoom; это строка, которая добавляет текущий Rect в rooms массив. @Yasser, если тебе нужна функция Intersect и эти переменные, я отредактирую их. Однако, похоже, что это ошибка с опубликованным мной сегментом кода — функция Intersect вычисляется правильно, но затем каким-то образом failed возвращается к false независимо от любого из других значений.

4. Да, если вы можете отредактировать их в, было бы легче увидеть, что происходит.

5. Хорошо, сойдет. Дайте мне минуту.

Ответ №1:

Вы ошибаетесь в математике. Это:

 public bool Intersect(Rectangle other) {
    return (x1 <= other.x2 amp;amp; x2 >= other.x1 amp;amp; y1 <= other.y2 amp;amp; y2 <= other.y1);
}
  

Должно быть изменено на (Обратите внимание, что я меняю <= на >= в последней части инструкции):

 public bool Intersect(Rectangle other) {
    return (x1 <= other.x2 amp;amp; x2 >= other.x1 amp;amp; y1 <= other.y2 amp;amp; y2 >= other.y1);
}
  

Комментарии:

1. Нет проблем. Рад, что смог помочь. Время от времени я сталкиваюсь с этими проблемами в коде, который кажется простым, но может доставить вам неприятности, если вы не будете обращать внимания.

2. Если бы у меня был пенни за каждую пустяковую проблему, я был бы миллионером. 🙂

Ответ №2:

Я не уверен, но вы используете Rectangle.Пересечение может быть неправильным. Intersect возвращает прямоугольник, представляющий пересечение двух указанных прямоугольников, или «пустой» прямоугольник, если пересечения нет. Вместо этого вы могли бы попробовать IntersectsWith — это возвращает логическое значение.

Комментарии:

1. Но как возвращаемый прямоугольник преобразуется в логическое значение?

2. На самом деле я использую пользовательский класс Rectangle — я избегал использовать Rect в качестве имени класса, поскольку думал, что это стандартный класс. Возможно, мне следовало назвать это Rect вместо этого и избежать использования Rectangle .

3. @Bala: Скорее всего, это просто оценка, true если это не так null . В противном случае оно было бы равно false .

Ответ №3:

Похоже, в вашей логике цикла нет ничего неправильного, что могло бы быть настроено failed неправильно. Если вы уверены, что метод не должен завершаться сбоем во втором цикле, проверьте свои вспомогательные методы, в частности Rectangle.Intersect . Добавление дополнительных выходных данных трассировки также будет полезно для вашей отладки.

Ответ №4:

На каждой итерации завершившегося ошибкой цикла while повторно инициализируется значение false

Комментарии:

1. похоже, что это ожидаемое поведение; rooms массив заполняется в цикле while несколькими комнатами, которые все не пересекаются.

Ответ №5:

Меня смущает, что вычисляется дважды? Конечно, после перерыва он выходит из цикла for. Возможно, попробуйте очистить ваше решение, удалить скрытый каталог obj и затем перестроить?

Комментарии:

1. Это то, о чем я думал, но, видимо, нет. У меня нет другого объяснения, почему failed всегда установлено значение false.

2. @Elliot Bonneville — Я думал, ты сказал, что ошибка всегда оценивается как true?

3. Нет, если я инициализирую (редактирую) его значением true, оно всегда будет оцениваться как true; если я инициализирую (редактирую) его значением false, оно всегда будет оценивать как false; другими словами, Intercept вычислялся неправильно.

Ответ №6:

Не понимая метода Intersect, я бы сказал, что это должно быть причиной вашей проблемы. Вы говорите, что первая итерация цикла while (предполагаю с моей стороны — ваш вопрос расплывчат по частям) дает правильную оценку failed (я предполагаю, что это в строке if (!failed) ). Метод Intersect здесь не вызывается, потому что в массиве rooms нет номеров, поэтому при инициализации переменной failed значение failed равно false. Затем, когда во второй раз в цикле while в массиве rooms есть комната, метод Intersect вычисляет неправильно для ваших целей и всегда говорит, что есть пересечение. Теперь я вижу, что @FreeAsInBeer обнаружил ошибку в методе Intersect.