Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.04.2016, 15:37   #1
Armageddets
Форумчанин
 
Регистрация: 30.06.2012
Сообщений: 145
По умолчанию Как сделать так чтобы квадраты не прикосались друг к другу?

Всем доброго времени суток, уважаемые эксперты. Столкнулся с проблемой. Необходимо на поле размера 10х10 создать 7 квадратов случайного размера (1х1, 2х2, 3х3, 4х4). Они могут пересекаться, но не должны становиться стенка к стенке по соседству. Могут входить внутрь друг друга или пересекаться перпендикулярно. Я На картинках ниже покажу. У каждого квадрата на поле есть на одном из углов цифра, она показывает сколько цифр из других квадратов попали внутрь этого квадрата.

Помогите сделать проверку на создание квадрата так, чтобы квадраты не соприкасались бок о бок с другими квадратами.

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

Код:
type
  TKvadrat=record
  X,Y,R,N:integer;
  end;


var
  Form1: TForm1;
  Buf:TBitmap;
  i,j,k,r,n, q,w:integer;
  u:Boolean;
  map:array[0..9,0..9,0..1] of Integer;
  kvadrat:array[0..6] of Tkvadrat;




for i:=0 to 9 do
  for j:=0 to 9 do
  begin
  map[i,j,0]:=-1;
  map[i,j,1]:=0;
  end;


  //sozdaem 7 kvadratov
  k:=0;
  Randomize;
  while k<7 do
  begin
  i:=Random(10); //x
  j:=Random(10); //y
  r:=Random(4)+1; //radius
    //smotrim chtobi na uglah ne bilo tsifr
    //smotrim chtobi ne vishli za predeli polya
    if (map[i,j,0]<0) and (i+r<=9) and (j+r<=9)
    and (map[i+r,j+r,0]<0) and (map[i+r,j,0]<0) and (map[i,j+r,0]<0) then
    begin
      u:=true; //razreshaem sozdat kvadrat
      
      //esli kvadrat bolshe pervogo
      if k>0 then
      begin
        for w:=0 to k-1 do
        begin
          //esli granitsa kvadrata sovpadaet s granitsami predidushego kvadrata - to zapret
        if (i>=kvadrat[w].X) and (i<=kvadrat[w].X+kvadrat[w].R) and (j=kvadrat[w].Y) then u:=False;
        if (i>=kvadrat[w].X) and (i<=kvadrat[w].X+kvadrat[w].R) and (j=kvadrat[w].Y+kvadrat[w].R) then u:=False;
        if (j>=kvadrat[w].Y) and (j<=kvadrat[w].Y+kvadrat[w].R) and (i=kvadrat[w].X) then u:=False;
        if (j>=kvadrat[w].Y) and (j<=kvadrat[w].Y+kvadrat[w].R) and (i=kvadrat[w].X+kvadrat[w].R) then u:=False;

        if (i+r>=kvadrat[w].X) and (i+r<=kvadrat[w].X+kvadrat[w].R) and (j=kvadrat[w].Y) then u:=False;
        if (i+r>=kvadrat[w].X) and (i+r<=kvadrat[w].X+kvadrat[w].R) and (j=kvadrat[w].Y+kvadrat[w].R) then u:=False;
        if (j+r>=kvadrat[w].Y) and (j+r<=kvadrat[w].Y+kvadrat[w].R) and (i=kvadrat[w].X) then u:=False;
        if (j+r>=kvadrat[w].Y) and (j+r<=kvadrat[w].Y+kvadrat[w].R) and (i=kvadrat[w].X+kvadrat[w].R) then u:=False;

        if (i+r div 2>=kvadrat[w].X) and (i+r div 2<=kvadrat[w].X+kvadrat[w].R) and (j=kvadrat[w].Y) then u:=False;
        if (i+r div 2>=kvadrat[w].X) and (i+r div 2<=kvadrat[w].X+kvadrat[w].R) and (j=kvadrat[w].Y+kvadrat[w].R) then u:=False;
        if (j+r div 2>=kvadrat[w].Y) and (j+r div 2<=kvadrat[w].Y+kvadrat[w].R) and (i=kvadrat[w].X) then u:=False;
        if (j+r div 2>=kvadrat[w].Y) and (j+r div 2<=kvadrat[w].Y+kvadrat[w].R) and (i=kvadrat[w].X+kvadrat[w].R) then u:=False;
        end;
      end;

     if u=True then
     begin
      //zapominaem kvadrat
      kvadrat[k].X:=i;
      kvadrat[k].Y:=j;
      kvadrat[k].R:=r;

      //otmechaem na kakom uglu budet tsifra
      n:=Random(4);
      kvadrat[k].N:=n; //zapominaem na kakom uglu tsifra
      case n of
      0:map[i,  j,0]:=0;
      1:map[i+r,j,0]:=0;
      2:map[i+r,j+r,0]:=0;
      3:map[i,  j+r,0]:=0;
      end;

      //otmechaem tsiframi zanyatie linii
      for q:=0 to r do
      begin
      map[i+q,j,1]:=map[i+q,j,1]+1;
      map[i+q,j+r,1]:=map[i+q,j+r,1]+1;

      map[i,j+q,1]:=map[i,j+q,1]+1;
      map[i+r,j+q,1]:=map[i+r,j+q,1]+1;
      end;

     Inc(k);
     end;
    end;
    
  end;


  //schitaem skolko tsifr vnutri kazhdogo kvadrata
  k:=0;
  while k<7 do
  begin
    w:=0;
      //probegaem po kletkam vnutri kvadrata
      for i:=Kvadrat[k].X+1 to Kvadrat[k].X+Kvadrat[k].R-1 do
      for j:=Kvadrat[k].Y+1 to Kvadrat[k].Y+Kvadrat[k].R-1 do
      if (map[i,j,0]>=0) and ( (i<>Kvadrat[k].X) or (j<>Kvadrat[k].Y) ) then inc(w);


      //izmenyaem tsifru
      case Kvadrat[k].N of
      0:map[Kvadrat[k].X,  Kvadrat[k].Y,0]:=w;
      1:map[Kvadrat[k].X+Kvadrat[k].R,Kvadrat[k].Y,0]:=w;
      2:map[Kvadrat[k].X+Kvadrat[k].R,Kvadrat[k].Y+Kvadrat[k].R,0]:=w;
      3:map[Kvadrat[k].X,  Kvadrat[k].Y+Kvadrat[k].R,0]:=w;
      end;
      
    inc(k);
  end;

  Regim:=0;
  Timer1.Enabled:=True;
Вот исходный код с проектом:
http://rghost.ru/8mhnsyNFl

Картинки как правильно создавать квадраты и как неправильно прилагаю:
Изображения
Тип файла: jpg 11.JPG (25.8 Кб, 149 просмотров)
Тип файла: jpg 12.JPG (34.6 Кб, 150 просмотров)
Тип файла: jpg 13.JPG (28.9 Кб, 136 просмотров)
Armageddets вне форума Ответить с цитированием
Старый 06.04.2016, 16:36   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

1) Пролечите свою Дельфи от вируса "Induc".
2) Оставил только такую проверку (UPD НЕВЕРНАЯ):
Код:
      for w := 0 to k - 1 do
      begin
        if (i = kvadrat[w].X) or (i + R = kvadrat[w].X) or
          (i = kvadrat[w].X + kvadrat[w].R) or
          (i + R = kvadrat[w].X + kvadrat[w].R) or (j = kvadrat[w].Y) or
          (j + R = kvadrat[w].Y) or (j = kvadrat[w].Y + kvadrat[w].R) or
          (j + R = kvadrat[w].Y + kvadrat[w].R) then
          u := False;
        if u = False then
          break;
      end;
Там не нужен "if k>0 then", так как цикл все равно не выполнится при при k = 0.
3) У меня не получилось дождаться, пока сгенерится 7 квадратов с таким условием - пришлось поставить "while k < 4 do". Мне кажется, способ "тупого" рандома тут не очень подходит. Всего разных квадратов с заданными условиями существует 294 (100 единичного размера, 81 - двойного, 64 - тройного, 49 - четверного). Мне кажется, нужно сгенерировать все квадраты, а затем уже из них как-то выбирать семь нужных.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 10.04.2016 в 16:43.
BDA на форуме Ответить с цитированием
Старый 06.04.2016, 17:53   #3
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,964
По умолчанию

Цитата:
Вот мой код, в котором я запрещаю становиться рядом квадратам. Я просто смотрю чтобы на границе с другим квадратом не проходила граница нового квадрата:
Ты уже сделал 99,9 % процентов работы. Тебе только нужно понять, что кахый квадрат, можно представить как сумму площадей треугольников.... Всё станет на свои места.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 06.04.2016, 18:40   #4
Armageddets
Форумчанин
 
Регистрация: 30.06.2012
Сообщений: 145
По умолчанию

Цитата:
Сообщение от Smitt&Wesson Посмотреть сообщение
Ты уже сделал 99,9 % процентов работы. Тебе только нужно понять, что кахый квадрат, можно представить как сумму площадей треугольников.... Всё станет на свои места.
Не совсем понимаю, честно говоря. Но насколько я понимаю это позволит мне сделать чтобы квадраты вообще не пересекались. А мне нужно чтобы перпендикулярно они могли пересекаться. А вот стенка к стенке - нельзя и угол к углу нельзя чтобы прикасались. Или есть какой-то способ это реализовать через подсчет суммы площадей?

Последний раз редактировалось Armageddets; 06.04.2016 в 19:14.
Armageddets вне форума Ответить с цитированием
Старый 10.04.2016, 09:44   #5
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,792
По умолчанию

а может просто сначала задать стороны квадратов как массив из точкек (X1,Y1) и потом их сравнивать, чтоб ни у одного квадрата не было точного совпадения более двух точке с другим квадратом (X2, Y2).
если хотя бы 2 соседние точки совпадают, то это означает, что квадраты соприкасаются сторонами.
а если только одна точка - это значит соприкасаются углами.
если 2 разные не соседние точки - квадраты пересекаются (а это допустимо)
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.
NetSpace вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Лесть не приносит профитов, так зачем Вы врете друг другу? Alar Свободное общение 18 07.11.2014 11:23
Проверить, являются ли данные два слова обращенными друг к другу, то есть первое читается слева направо так же, как второе справа FYNZIK Паскаль, Turbo Pascal, PascalABC.NET 4 10.03.2014 18:23
Как сделать так, чтоб когда заходит определённый друг в контакт мне приходило смс-уведомление? romantik2011 Свободное общение 7 29.07.2011 15:08
как сделать так,чтобы он левой рукой до стены коснулся? и если можно чтобы двери лифта закрылись maxon56 Паскаль, Turbo Pascal, PascalABC.NET 0 07.06.2011 18:46
Как сделать так, что б Float-элементы не уезжали друг под друга (если не влазят в экран) barbiturat HTML и CSS 3 09.12.2008 10:26