Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Как сделать swap?


Автор: versus 19.9.2008, 01:13
Есть такой фрагмент кода:

Код

class Cell
{
...

   public void swap(Cell c)
   {
      Cell tmp = new Cell();
         
      tmp.Location = this.Location;
      tmp.X = this.X;
      tmp.Y = this.Y;
 
      ....

      this.Location = tmp.Location;

      ....
      
      c.Location = this.Location;
   }
}


где X, Y и Location - свойства.
Как бы его можно было оптимизировать?
Думал сначала использовать шаблонную функцую swap, но .NET сабака не дает properties передавать по ссылке. А передавать их по значению смысла мало. Как быть?

Автор: PashaPash 19.9.2008, 01:36
versus, оптимизировать - понятие относительное. Если X, Y и Location везде по коду связаны, то вынеси их в отдельный класс/структуру. И работай с ними как с цельным объектом. Если не связаны - то метод swap у тебя странно написан. Зачем создавать Cell tmp, если можно обменять свойства без нее? Да и вообще, сам смысл существования этого метода вызывает сомнения - совершенно непонятно что же он делает.

Автор: versus 20.9.2008, 00:47
Цитата(PashaPash @ 19.9.2008,  01:36)
versus, оптимизировать - понятие относительное. Если X, Y и Location везде по коду связаны, то вынеси их в отдельный класс/структуру. И работай с ними как с цельным объектом. Если не связаны - то метод swap у тебя странно написан. Зачем создавать Cell tmp, если можно обменять свойства без нее? Да и вообще, сам смысл существования этого метода вызывает сомнения - совершенно непонятно что же он делает.

Прошу прощения, за туманность формулировки.
Попробую описать ситуацию более подробно.

Я пишу простую программу-игру типа "пятнашек" (ну или "осьмушек" http://www.rsdn.ru/article/multimedia/octals.xml).  
Сначала пользователю показывается поле (матрица) из кнопок в определенной последовательности (например, дни недели). 
Затем, пользователь тыкает в какую-нибудь кнопку и кнопки перемешиваются в случайном порядке, причем пользователь видет процесс перемешивания, то есть кнопки меняются местами с некоторой задержкой.
После перемешивания пользователь должен восстановить исходную последовательность нажимая на соответсвующие кнопки (понедельник, вторник, среда, ...).

В процессе перешивания у каждой кнопки есть 5 параметров, которые мне интересны:
ширина и высота (эти параметры можно было бы игнорировать, если они были одинаковы для всех кнопок, но поскольку я увеличиваю крайние кнопки, чтобы они заполнили все игровое пространство, то эти параметры могут отличаться. Пример: игровое поле 10x10, кнопок 9, следовательно крайние кнопки должны быть на 1 пиксель больше остальных, чтобы заполнить все игровое поле).
позиция на игровом поле (чтобы можно было менять их позициями других кнопок)
ну и точки xy  задающие положение кнопки в исходной матрице, чтобы в событие Paint я мог по этим параметрам правильно расположить кнопки.

Собственно говоря в процессе перемешивания мне интересна только позиция кнопки и их ширина и высота. x, y нужны только в обработчике Paint - например, когда размер окна меняется и нужно перерисовывать все кнопки, учитывая то как они были перемешены.

Итак, чтобы переставить кнопки местами, мне нужно поменять у них 5 параметров.
Под оптимизацией в данном случае я имел, что мне хотелось бы получить фрагмент вроде:
swap(this.Location, c.Location)
swap(this.x, c.y)
swap(this.y, c.y)
...

и не писать один и тот же кусок кода для всех 5 переменных.

x, y - это просто открыте переменные, с ними проблем не возникает
Location, Height и Width - это свойства (property), их передать в качестве ссылки в метод swap .Net не разрешает.

Как быть?

Автор: PashaPash 20.9.2008, 01:34
versus, взять любую книгу по ооп и внимательно прочитать. У тебя проблемы с дизайном - с одной стороны пытаешься привязать cell к определенному месту, с другой - очень хочешь подвигать их по полю. Что делает метод swap? меняет местами ячейки? Ячейки - это часть игрового поля. Выпиливать их из него только ради того, чтобы поменять местами фишки, действительно трудоемко.

Введи отдельно ячейки (дырки), с фиксированной позицией. Составь из них матрицу. У ячеек будут фиксированные позиции, привязанные к матрице. Для каждой можно узнать 4 соседние. - это то, что у тебя сейчас под Cell подразумевается.
Потом введи сами фишки (Token) - что-то, вообще не имеющее представления о координатах. Возьми 15-ки, выковыряй одну фишку и посмотри. Должен получится соответствующий ей объект - никаких координат, только какая-то надпись на нем.
Потом сделай в Ячейке-Cell свойство, показывающее какая фишка в ней сейчас лежит. И тогда сможешь перекладывать их в 3 строчки, без "оптимизации". Вот примерно так:
Код
// где-то запоминаешь предыдущую ячейку
Cell oldSelectedCell = SomePreviousSelectedCell;
// как-то получаешь из координат мыши свежекликнутую
Cell justClickedCell = JustClickedSelectedCellBasedOnMouseCoords;
// меняешь фишки в них местами
Token temp = justClickedCell.Token;
justClickedCell.Token = oldSelectedCell.Token;
oldSelectedCell.Token = temp;

Автор: versus 20.9.2008, 10:13
Цитата(PashaPash @ 20.9.2008,  01:34)
versus, взять любую книгу по ооп и внимательно прочитать. У тебя проблемы с дизайном - с одной стороны пытаешься привязать cell к определенному месту, с другой - очень хочешь подвигать их по полю. Что делает метод swap? меняет местами ячейки? Ячейки - это часть игрового поля. Выпиливать их из него только ради того, чтобы поменять местами фишки, действительно трудоемко.

Введи отдельно ячейки (дырки), с фиксированной позицией. Составь из них матрицу. У ячеек будут фиксированные позиции, привязанные к матрице. Для каждой можно узнать 4 соседние. - это то, что у тебя сейчас под Cell подразумевается.
Потом введи сами фишки (Token) - что-то, вообще не имеющее представления о координатах. Возьми 15-ки, выковыряй одну фишку и посмотри. Должен получится соответствующий ей объект - никаких координат, только какая-то надпись на нем.
Потом сделай в Ячейке-Cell свойство, показывающее какая фишка в ней сейчас лежит. И тогда сможешь перекладывать их в 3 строчки, без "оптимизации". Вот примерно так:
Код
// где-то запоминаешь предыдущую ячейку
Cell oldSelectedCell = SomePreviousSelectedCell;
// как-то получаешь из координат мыши свежекликнутую
Cell justClickedCell = JustClickedSelectedCellBasedOnMouseCoords;
// меняешь фишки в них местами
Token temp = justClickedCell.Token;
justClickedCell.Token = oldSelectedCell.Token;
oldSelectedCell.Token = temp;

Спасибо, помогло.
Сделал у Cell вложенный класс Token с полями text и id. Text - для отображения, ID - идентификатор по которому я отслеживаю правильно ли пользователь выбрал очередной элемент последовательности.
Соответсвенно метод swap у Cell стал таким:

Код

        public void Swap(Cell c)
        {
            Token tmp;

            tmp = this.token;
            this.token = c.token;
            c.token = tmp;
        }


Этого мне вполне достаточно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)