Здравствуйте! при написании одного из модулей программы я столкнулся с такой проблемой как наложение фигур друг на друга. Как сделать так чтоб последующая фигура рисовалась на свободном месте экрана и не накладывалась на другие?
uses Crt, Graph; const k=100; var GraphDriver, GraphMode: Integer; X1,y1, r: Integer;ch:char; begin GraphDriver := Detect; InitGraph(GraphDriver, GraphMode, ' '); if GraphResult<> grOk then Halt(1); repeat ch:=readkey; if ch=chr(13) then begin X1 := Random(640-k)+k; y1 := Random(480-k)+k; r:=Random(k)+1; circle(X1,y1,r); end; until ch=chr(27); CloseGraph; end.
мисс_граффити
28.03.2011 20:57
фигуры - только круги? а что делать, если свободных мест не осталось вообще?
ТОХА
28.03.2011 21:01
да, только круги это просто часть моей игры на запоминание, сделаю их такого размера чтоб в районе 50 вмещалось, больше запомнить будет просто невозможно)
volvo
29.03.2011 2:39
Если только круги - то можно сделать
что-то типа вот такого...(Показать/Скрыть)
uses Crt, Graph;
const k = 100; maxCircles = 50;
var GraphDriver, GraphMode: Integer; X1,y1, r: Integer; ch: char;
i, curr : integer; ok : boolean; C : array[1 .. maxCircles] of record X, Y, R : longint; end;
begin GraphDriver := Detect; InitGraph(GraphDriver, GraphMode, ' '); if GraphResult<> grOk then Halt(1);
curr := 0; repeat ch := readkey; if ch = chr(13) then begin repeat X1 := Random(GetMaxX - k) + k; { Не надо привязываться к "магическим числам" } Y1 := Random(GetMaxY - k) + k; r := Random(k) + 1;
ok := true; for i := 1 to curr do ok := ok and (sqr(C[i].X - X1) + sqr(C[i].Y - Y1) > sqr(R + C[i].R)); until ok;
Откуда такая интересная формула, если не секрет З.Ы. спасибо, сам бы не додумался
volvo
29.03.2011 4:44
Чего ж тут такого особенного? Чистая логика. Когда новая окружность не будет пересекаться с уже отрисованной? Правильно, когда расстояние между центрами окружностей больше суммы их радиусов. Причем это должно проверяться для ВСЕХ уже отрисованных объектов.
Чтоб не вычислять квадратный корень, я оставил квадрат расстояния между центрами. Значит, сравнивать его надо с квадратом суммы радиусов. Всё просто.
ТОХА
29.03.2011 4:49
точно это ж геометрия за 8 класс
TarasBer
29.03.2011 13:13
> repeat random... until ok;
Предлагаю придумать не потенциально-бесконечный алгоритм.
volvo
29.03.2011 13:52
Цитата
Предлагаю придумать не потенциально-бесконечный алгоритм.
Не проблема. Только не надо мне рассказывать ,что "в некотором царстве, в некотором государстве" Random может бесконечно возвращать значения, большие некоего порога. Давай будем реалистами: Random - это генератор, который возвращает равномерно-распределенные случайные числа. То есть, в какой-то момент времени он вернет и 1, и 2, и 4, и 10.
Тогда для того, чтоб алгоритм стал НЕ потенциально бесконечным, достаточно, чтобы выполнялось условие maxCircles * Pi * K2 < GetMaxX * GetMaxY
То есть, либо уменьшаем K до [Sqrt(GetMaxX * GetMaxY / (50 * Pi))] = 44
, либо уменьшаем MaxCircles до [GetMaxX * GetMaxY / (50 * K2)] = 9
, либо увеличиваем GetMaxX * GetMaxY так, чтобы их произведение превышало 1570797. С современными мониторами и компиляторами это ни разу не проблема: любой широкоформатный монитор выдаст разрешение 1920*1024, и GetMaxX * GetMaxY = 1963137. Опять никакого шанса алгоритму стать бесконечным...
Я уж не говорю о том, что можно одновременно уменьшить и радиус и maxCircles...
TarasBer
29.03.2011 14:05
> Random - это генератор, который возвращает равномерно-распределенные случайные числа
Не случайные, а ПСЕВДОслучайные. Будут ли тройки последовательно возвращаемых значений равномерно распределены? Позволяют ли внутренние особенности именно данной реализации алгоритма надеяться на отсутствие возможности зацикливания?
ТОХА
29.03.2011 15:31
смысл игры в том, что нужно запомнить какой шарик появился на поле и щелкнуть на него(пока вместо мыши энтер), я сомневаюсь что есть люди которые дойдут до зацикливания TarasBer, надеюсь я ответил на твой вопрос
осталось добавить мышку и небольшое мигание перед появлением каждого из шариков для усложнения запоминания, как закончу скину
TarasBer
29.03.2011 16:16
> TarasBer, надеюсь я ответил на твой вопрос
Нет, вопрос был не об этом. Вопрос был в том, что сама концепция выполнения случайного действия до выполнения какого-то условия мне видится сомнительной. Кто сказал, что условие когда-либо выполнится, мало ли как случайное действие себя вести будет?
volvo
29.03.2011 18:40
Цитата
сама концепция выполнения случайного действия до выполнения какого-то условия мне видится сомнительной
Это твои заморочки. Оно ОБЯЗАНО отработать по изложенным выше причинам. А отработает оно за 0.0002 сек. или за 0.05 сек - это дело десятое (в данном конкретном случае), время реакции человека все равно гораздо больше.
Проверил на своей машине: сгенерировал (без вывода на экран) 50 окружностей, в цикле. Цикл прогнал 10000 раз. А потом - полтора миллиарда раз. И в первом и во втором случае среднее время генерации всех 50 окружностей приблизительно одно и то же. Если алгоритм за полтора миллиарда испытаний не дает не только сбоя (коим здесь является "вечный цикл"), но даже ощутимого увеличения времени выполнения - я бы его использовал без сомнений... Но если очень хочется пойти другим путем - изобретайте очередной велосипед... Меня эта отрасль машиностроения не интересует уже давно...
ТОХА
29.03.2011 18:51
небольшой оффтоп как пользоваться коммандой MouseIn для кругов и эллипсов?представлять их в виде многоугольников и ставить условие под каждый угол или же есть способ проще? просто точность попадания в многоугольник будет зависеть от количества углов, а проверок получается очень много)
TarasBer
29.03.2011 19:03
> Это твои заморочки. Оно ОБЯЗАНО отработать по изложенным выше причинам.
Причины недостаточно доказаны.
> А отработает оно за 0.0002 сек. или за 0.05 сек - это дело десятое (в данном конкретном случае)
Лишь бы раз в год оно не заработало за 50 сек.
> Проверил на своей машине: сгенерировал (без вывода на экран) 50 окружностей, в цикле. Цикл прогнал 10000 раз. А потом - полтора миллиарда раз. И в первом и во втором случае среднее время генерации всех 50 окружностей приблизительно одно и то же.
Возьми не среднее, а максимальное. А потом возьми другой ГСЧ, для него придётся доказывать всё по новой.
Это хорошо, что полтора миллиарда испытаний отработали как надо, но всё-таки само понятие случайного числа противоречит понятию алгоритма, и завязывание жизненно важных участков алгоритма на случайные числа лишает алгоритм права называться алгоритмом, поскольку делает его поведение непредсказуемым. Ты математически можешь доказать, что алгоритм гарантировано даст нужный результат не более, чем за эн тактов процессора (или итераций цикла, или ещё каких-то условных единиц)? Нет, не можешь. Поэтому с такими алгоритмами надо быть очень осторожными. И если есть обходные пути, работающие за разумное время - то надо их искать. Иначе на этом алгоритме надо огромными красными буквами писать, что так как он основан на случайных событиях, то он ничего не гарантирует.
Добавлено через 2 мин. > как пользоваться коммандой MouseIn для кругов и эллипсов?
Чтобы узнать, что точка с координитами mx, my попала в эллипс с центром в точке x, y и полуосями rx, ry, надо сравнить
sqr((mx-x)/rx) + sqr((my-y)/ry)
с единицей.
ТОХА
29.03.2011 19:15
Спасибо )
ТОХА
29.03.2011 21:48
немного запутался и возникло 2 проблемы: мышь ползает только по верхней половине экрана программа виснет после появления 8 шарика, почему именно 8 я без понятия буду благодарен если кто-нить посмотрит))
volvo
29.03.2011 23:06
Цитата
Возьми не среднее, а максимальное
Максимальное время различается не больше, чем на 20%. С учетом того, что речь идет о тысячных долях секунды - это не критично. Я тебе уже говорил, где нужна шлифовка тактов. В прикладной программе, которая ожидает реакции пользователя, я этим заниматься не собираюсь. И тебе не советую.
Цитата
А потом возьми другой ГСЧ, для него придётся доказывать всё по новой.
Вот когда мне понадобится другой ГСЧ, и я получу его реализацию - я буду думать над этим. Решаем проблемы по мере поступления. А то ведь теоретически можно придумать такой ГСЧ, что он ЛЮБОЙ алгоритм (вообще любой, не только по этой задаче) запорет. Вот и сиди, и доказывай правильность алгоритма для ВСЕХ ВОЗМОЖНЫХ генераторов. У меня есть более интересные занятия.
А пока - перечитай первый абзац этого сообщения и первый абзац сообщения №9. Вот ты и начал мне рассказывать, что "где-то существует другой ГСЧ, который..." Я не пользуюсь другим. Я использую стандартный Random (который использовал еще в 1987 году, и до сих пор в учебных программах он меня более чем устраивает. В реальных - используются совершенно другие генераторы, и совершенно другие алгоритмы). Если б я написал свою функцию GetRandomNumber (пусть даже в ней был бы вызов того же Random-а) - у тебя был бы повод придраться, ибо я хоть какую-то возможность смены генератора предполагаю. Сейчас у тебя его нет, ибо я однозначно дал понять: использовать другой генератор не собираюсь, в коде жестко прописан тот, что есть. Так что про "другой ГСЧ" - это даже не обсуждается...
Цитата
программа виснет после появления 8 шарика, почему именно 8 я без понятия
Потому что у тебя генерация X, Y, R должна быть внутри repeat/until, а ее там нет. И что получилось? Сгенерированы значения, проверено по формуле, получено Ok = False. Ты опять присваиваешь Ok := True, и для тех же X, Y, R что и прежде, начинаешь проверку. Это неправильно. Надо сгенерировать другие значения для новой окружности, и проверять уже для них...
ТОХА
30.03.2011 1:07
нашел, исправил, а что делать с мышкой?
TarasBer
30.03.2011 13:30
> Максимальное время различается не больше, чем на 20%.
Ну если ты перебрал при этом все 4 млрд возможных стартовых состояния ГСЧ, то это подойдёт, как доказательство.
> Я тебе уже говорил, где нужна шлифовка тактов.
Как будто мне она тут нужна. Чё сразу - раз ТарасБер, значит шлифовка тактов? Мне не нужно, чтобы раз в год программа затупливала на минуту. Конечно, когда пишешь игрушку, на это вообще все кладут - у 10 игроков игра упала, у 90 отработала, вот и зашибись. А в серьёзном программировании так нельзя.
ТОХА
1.04.2011 2:52
мышку одолел,
вопрос покажется странным но как сделать так чтобы перерисовка картинки занимала больше времени, я понимаю что все стараются избавляться от перерисовки всего экрана, но мне это нужно для того чтоб человеческий глаз начинал воспринимать весь экран заново а не только появившуюся часть
можно ли рисовать черный прямоугольник на весь экран на секунду а потом убирать его и чтоб на нем сохранилось все что было до его рисования?
volvo
1.04.2011 21:20
Цитата
можно ли рисовать черный прямоугольник на весь экран на секунду а потом убирать его и чтоб на нем сохранилось все что было до его рисования?
Вообще самым оптимальным было бы использовать граф. режим, в котором есть больше одной видеостраницы. Рисуешь на активной, в это время видимой установлена другая. Когда нужное время прошло - меняешь видимую страницу, у тебя мгновенно отображается рисунок.
Но...
1) чтобы было больше одной страницы, надо чем-то пожертвовать. В твоем случае - придется жертвовать разрешением. Например, вместо VgaHi (640*480) использовать VgaMed (640*350), там есть 2 страницы. 2) я не знаю, как будет вести себя мышь в случае использования нескольких видеостраниц.
ТОХА
1.04.2011 22:39
а с помощью комманд getimage и putimage можно сделать так?: 1 нарисовать появившийся круг 2 сохранить весь экран 3 очистить 4 нарисовать сохраненный фрагмент и если можно то насколько быстро это будет происходить чтоб не успеть воспринять 1 пункт, а то смысл игры становится не таким интересным
volvo
1.04.2011 23:08
А ты знаешь, мне тут еще один финт в голову пришел. Попробуй, будет оно работать или нет, мне сейчас негде, Турбо Паскаля под рукой нет, а в FPC это не отработает.
{ Отрисовал картинку, теперь надо "погасить" на секунду }
{ Гасим. Для этого просто все цвета сделаем "черными" } for i := 1 to 15 do begin setpalette (i, black); { Нулевой цвет я бы не трогал. } end;
readln; { Ждем какое-то время, можешь заменить на Delay }
{ "Проявляем" картинку } for i := 1 to 15 do begin setpalette (i, i); end; { ... и рисуем новую окружность сразу после "проявки"... }
Как тебе такой вариант?
P.S. Еще более наглый вариант - попробовать рисовать вслепую, пока цвета палитры сброшены в черный. То есть, устанавливаешь цвет через SetColor, и рисуешь. В принципе, не вижу причин, чтоб потом, при восстановлении палитры это не "проявилось".
ТОХА
1.04.2011 23:17
работает, правда белый цвет поменялся на голубой, проверял на самом первом с кругами без меню, но все равно спасибо)))
Добавлено через 4 мин. на основную программу не очень повлияло, там красный используется, курсор голубой только
Добавлено через 19 мин. для окончательного завершения осталось только подправить функцию mousein, у меня 1 из 10 запусков она хоть как-то работает на шариках и то под восьмой сбивается остальные случаи при нахождении курсора внутри она возвращает false, да и способ игры не очень получается, приходится ставить readkey, наводишь мышь и жать энтер, иначе она так быстро рисует и проверяет координаты что я даже навести не успеваю))
Добавлено через 5 мин.
Function MouseIn(KoordX,KoordY,x1,y1,r:word):boolean; var rdx,rcx:word; begin asm mov ax,$03 int $33 mov rdx,dx mov rcx,cx end; MouseIn := (sqr((KoordX-x1)/r) + sqr((KoordY-y1)/r))<=1 end; {из основной} if ButtonPressed=1 then begin GetMouseXY(KoordX,KoordY); if MouseIn(KoordX,KoordY,x1,y1,r) then next_circle:=true else next_circle:=false; end;
volvo
2.04.2011 0:01
Ты б прикрепил весь файл полностью (можно в приват), как только доберусь до TP - посмотрю, что там творится... А то так "глухие телефоны" получаются...
ТОХА
2.04.2011 0:05
ок в приват скину, а то при защите найдут проект мой тута и скажут скачал
volvo
2.04.2011 0:55
Что-то я не понял, чего ты творишь... Вот тут:
Цитата
{ из основной } if ButtonPressed = 1 then begin GetMouseXY(KoordX,KoordY); if MouseIn(KoordX,KoordY,x1,y1,r) then next_circle:=true else next_circle:=false; end;
все логично: если нажата мышь, то взять её координаты. Это понятно. А потом проверить, эти координаты находятся ли внутри окружности радиуса R с центром в (X1, Y1)... Это тоже понятно. Но вот зачем ты внутри MouseIn опять получаешь координаты нажатия - это уже непонятно. Я бы сделал так:
{ Заметь, я сделал параметры типа LongInt сразу, чтоб предотвратить переполнение } Function MouseIn (KoordX, KoordY, x1, y1, r : LongInt) : boolean; begin MouseIn := sqr(KoordX - X1) + sqr(KoordY - Y1) <= sqr®; end;
Опять же, чисто теоретически, проверить будет где в лучшем случае послезавтра...
ТОХА
2.04.2011 1:02
модуль мыши просто из FAQ брал, как я и предпологал он рисует все круги сразу, как будто buttonpressed=1 это отсутсвие нажатия клавиши
Добавлено через 4 мин. при изменении buttonpressed=1 -> buttonpressed=5 результат тот же, как будто условия вовсе нет
ТОХА
2.04.2011 1:46
ошибка в buttonpress это 100%, изменил условие начала вместо левой кнопки на ентер с учетом координат мыши, работает
volvo
2.04.2011 1:50
Так... Нашел DosBox с шестым Турбо-Паскалем... Вот это:
Function MouseIn (x1, y1, r : LongInt) : boolean; var C_X, C_Y: word; begin Asm mov ax, $03 int $33 mov C_X, CX mov C_Y, DX end; MouseIn := sqr(C_X - X1) + sqr(C_Y - Y1) <= sqr®; end;
{ и в основном коде: }
repeat { который после mouse_on }
{ ... } repeat until ButtonPressed = 1; { вместо if ButtonPressed=1 then } { Просто ждем, пока будет нажата левая кнопка мыши, а потом - проверяем, где именно она была нажата }
next_circle := MouseIn(x1, y1, r);
until next_circle = false;
работает достаточно стабильно. Но все равно где-то сбоит, попробуй пройтись отладчиком, посмотреть, какие значения функция MouseIn получает через параметры, и какие координаты мыши выдает Asm-часть кода.
ТОХА
2.04.2011 2:15
Эврика все работает, буду до конца вечера тестить на баги) без вас я бы не справился, это точно))
andriano
2.04.2011 18:18
Цитата
Предлагаю придумать не потенциально-бесконечный алгоритм.
Действительно, стоит изменить лишь одну константу: r := Random(k) + 20; чтобы потенциально бесконечный алгоритм превратился в реально бесконечный. Действительно, хороший алгоритм должен: 1. Давать правильный результат при корректных данных. 2. Давать предсказуемый результат (в частности, отсутствие деструктивных действий таких как завершение программы по ошибке, зацикливание, порча памяти...) при некорректных данных. Очевидно, если алгоритм приводит к зацикливанию программы при изменении внешних констант (т.е. таких, которые не являются имманентной частью алгоритма), то это плохой алгоритм. Желательно также, чтобы он сообщал пользователю о конкретной ошибке. Предлагаю что-то вроде.
ok := true; for i := 1 to curr do ok := ok and (sqr(C[i].X - X1) + sqr(C[i].Y - Y1) > sqr(R + C[i].R)); inc(IntIt); until ok or (IntIt > MaxIt); inc(curr); if IntIt > MaxIt then writeln('Ошибка: невозможно разместить ',curr,'-ю окружность');
Да, прошу еще обратить внимание на порядок, в котором определяются характеристики окружностей, и как именно это сделано (3-5 строки листинга).
volvo
2.04.2011 18:46
Цитата
Действительно, стоит изменить лишь одну константу:
А ты не меняй, и алгоритм бесконечным не будет. Если я этого не сделал - по какому праву это делаешь ты? Языком потрепать захотелось? Ты пришел по неверному адресу: я больше не буду молчать в ответ на всякие бредни. Ответ будет жестким. Не дойдет с первого раза - во второй раз будет еще жестче.
Цитата
Очевидно, если алгоритм приводит к зацикливанию программы при изменении внешних констант (т.е. таких, которые не являются имманентной частью алгоритма), то это плохой алгоритм.
В таком случае, хороших алгоритмов не существует. В любом случае можно так поменять внешнюю константу, что ЛЮБОЙ алгоритм (вернее, его реализация) перестанет работать.
Еще раз: без изменения констант ни одного зацикливания на миллиарды тестов не наблюдается. Разглагольствования типа "где-то там, у сферического пользователя в вакууме, это может быть не сработает, и программа зависнет" меня не интересуют. Я - практик. Программа зависает? Нет. Еще вопросы будут?
ТОХА
2.04.2011 20:31
защитил проект сегодня удачно всем спасибо за помощь кому интересно что получилось прикладываю проект, делимся на скока шариков у кого хватило зрительной памяти)
Lapp
3.04.2011 6:09
Цитата(ТОХА @ 2.04.2011 17:31)
кому интересно что получилось прикладываю проект, делимся на скока шариков у кого хватило зрительной памяти)
Мне было интересно, но - увы! у меня уже везде W7 или Vista. Даже и ТР есть, но полноэкранная графика для меня уже недоступна.
Все же это странно - обучать студентов на таком старье, как TP.
ТОХА
3.04.2011 16:51
я не студент учусь в 10 классе)
hydroxychloroquine sulfate 200 m
5.12.2021 21:51
Cialis Super Actif Plus
is gabapentin a controlled subst
6.12.2021 3:44
Compro Viagra Poco Prezzo Mexico
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.