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

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

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 18.05.2011, 20:53   #1
Juffin
Форумчянин
Форумчанин
 
Аватар для Juffin
 
Регистрация: 05.04.2009
Сообщений: 446
Вопрос как избежать подвисания

Решил тут написать игру "Пять камней" с целью попробовать силы в игровом АИ, но наткнулся на проблему: ход компьютера скорее всего будет занимать некоторое время, и окошко не должно подвисать. Вынес раздумия компьютера в отдельный поток, но все равно не знаю, как обойтись без Sleep в ожидании его хода.

Есть глобальные переменные cx, cy, после хода игрока равные -1.
Код в процедуре соображания:
Код:
CPUThread:=AIThread.Create(true);
CPUThread.Resume;
Sleep(2000);
//раздумия должны закончиться
if (cx=-1) or (cy=-1)
then Memo1.Lines.Add('Компьютер задумался.');
          
if (Field[cx][cy]=0) and (cx>0) and (cy>0) and (cx<30) and (cy<30)
then begin
     Field[cx][cy]:=2;
     Form1.DrawField;
     Memo1.Lines.Add('Компьютер сходил ('+inttostr(cx)+';'+inttostr(cy)+')');
     end
else begin
     Memo1.Lines.Add('Компьютер не смог сходить нормально.');
     end;
И код в классе потока:
Код:
type AIThread=class(TThread)
     private
     //здесь могут быть внутренние переменные
     protected
     procedure Think;
     procedure Execute; override;
     end;

implementation

procedure AIThread.Think;
begin
Sleep(1000);
cx:=random(10)+10;
cy:=random(10)+10;
end;

procedure AIThread.Execute;
begin
Think;
end;
Вложения
Тип файла: zip fivestones.zip (249.6 Кб, 12 просмотров)
Nobody expects Spanish Inquisition!
Juffin вне форума Ответить с цитированием
Старый 18.05.2011, 21:05   #2
chertovich
Форумчанин
 
Аватар для chertovich
 
Регистрация: 26.07.2009
Сообщений: 489
По умолчанию

пробуй через Timer, конечно не самый лучший подход, но все-таки
Если в глубине души вы программист, то, следуя своим наклонностям, вы захотите написать кусок кода.
chertovich вне форума Ответить с цитированием
Старый 18.05.2011, 21:29   #3
t2skler
Форумчанин
 
Аватар для t2skler
 
Регистрация: 25.11.2010
Сообщений: 164
По умолчанию

А смысл отказываться от Sleep? Тем более, что всё это делается в потоке. Попробуй ещё в поток вставить Application.ProcessMessages, мб и поможет.
Возможно Я Быдлокодер ©.
t2skler вне форума Ответить с цитированием
Старый 18.05.2011, 21:50   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Цитата:
Сообщение от t2skler Посмотреть сообщение
А смысл отказываться от Sleep? Тем более, что всё это делается в потоке. Попробуй ещё в поток вставить Application.ProcessMessages, мб и поможет.
категорически не согласен. Там не нужен application.processmessages. т.к. это вторичный поток, а не основной VCL который принимает сообщения от системы.

А вообще есть такая вещт как События..

делается оно так:
В приложении делаем глоб. переменную
Код:
var 
 aEvent:THandle; //наше событийное
Далее где-то создаём это событие(Момент перед началом раздумий ПК):
Код:
aEvent:=CreateEvent(nil,True,False,nil);  //создаём событие(в несигнальном состоянии)....

создаём на форме что-то чтро будет ждать при помощит этого:
Код:
WaiForSingleObject(aEvent,infinite); // ждем сигнал от события , бесконечное кол-во секунд(постоянно).
Затем в потоке раздумий говорим тому что ждет окончания раздумий, о том что что-то где-то завершилось и событие сигнализирует об этом:
Код:
 SetEvent(aEvent);
Теперь выполняем код после раздемий ПК. Т.е. SetEvent нам скажет что ПК подумал.

далее не забываем закрыть ивент:
Код:
closeHandle(aEvent);

Последний раз редактировалось Человек_Борща; 18.05.2011 в 22:02.
Человек_Борща вне форума Ответить с цитированием
Старый 18.05.2011, 21:53   #5
Juffin
Форумчянин
Форумчанин
 
Аватар для Juffin
 
Регистрация: 05.04.2009
Сообщений: 446
По умолчанию

Смысл отказываться от Sleep в том, что от нее приложение зависат. Попробуй на нажатие кнопки написать Sleep(5000) и потом сдвинуть окно.
Nobody expects Spanish Inquisition!
Juffin вне форума Ответить с цитированием
Старый 18.05.2011, 22:03   #6
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Sleep() усыпляет поток(отсрочивает действие) а смысла то нет. Исп. события(Написал выше).

Держи. Переделал твой проект.
Прога не зависает, комп думает находу..
Теперь все работает через aEvent.
И исправил 1 баг(Ты создовал потоки но не освобождал их).

Надеюсь за помощь хотябы +

ЗюЫю если надо чтобы комп думал медленно(в пределах 1 сеунды), делаем так:
Код:
//ВЫрезано из Math модуля чтобы за зря его не тащить.. 
function RandomRange(const AFrom, ATo: Integer): Integer;
begin
  if AFrom > ATo then
    Result := Random(AFrom - ATo) + ATo
  else
    Result := Random(ATo - AFrom) + AFrom;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//Вишаемся на рандомное кол-во милисек. в значении от 100 до 1000 мс.
  Sleep(RandomRange(100,1000));
end;
Вложения
Тип файла: zip fivestones_Borsch_edition.zip (205.5 Кб, 14 просмотров)

Последний раз редактировалось Человек_Борща; 18.05.2011 в 22:31.
Человек_Борща вне форума Ответить с цитированием
Старый 18.05.2011, 22:33   #7
Juffin
Форумчянин
Форумчанин
 
Аватар для Juffin
 
Регистрация: 05.04.2009
Сообщений: 446
По умолчанию

Человек_Борща, спасибо, не тоже неправильно работает.
Поставь в procedure AIThread.Think в начале Sleep(100) и в результате будет сообщение о том, что компьютер не смог сходить нормально, он не успевает изменить переменные.
Nobody expects Spanish Inquisition!
Juffin вне форума Ответить с цитированием
Старый 18.05.2011, 22:41   #8
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Ну значит вы ошиблись в просчёте коээфициета ошибки ПК. Поток работает нормально и считает ок. Ошибка в том что ПК ходит по тем клеткам по котрым уже ходили.. и часто пытается попасть в одно и тоже место..



задерживать поток на 100 мс нет смысла =) ПРавьте алгоритм. Ищите свободные клнетки и рандомно выбирайте одну.

Последний раз редактировалось Человек_Борща; 18.05.2011 в 22:45.
Человек_Борща вне форума Ответить с цитированием
Старый 18.05.2011, 22:48   #9
Juffin
Форумчянин
Форумчанин
 
Аватар для Juffin
 
Регистрация: 05.04.2009
Сообщений: 446
По умолчанию

Он работает нормально только если он работает очень недолго. Даже после Sleep(10) ошибка каждый ход. И она возникает не потому, что он не туда ходит, а потому, что координаты остаются -1;-1 это можно отследить через ShowMessage.
Nobody expects Spanish Inquisition!
Juffin вне форума Ответить с цитированием
Старый 18.05.2011, 22:55   #10
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Ну тебе судить =) Я сильно не углублялся в алгоритмы проги.. просто приделал работу через Events....
Человек_Борща вне форума Ответить с цитированием
Ответ


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

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как избежать конфликта строковых функций? Trust_357 Visual C++ 2 09.04.2011 15:09
Как избежать повтор строк в тексте Federal Помощь студентам 3 19.10.2010 14:38
Как избежать Selection? Мультипликатор Microsoft Office Word 10 21.06.2010 17:15
Бот - как избежать слежки? boris-blade Win Api 9 28.12.2009 09:11
как избежать кэширования в Опере rolling PHP 3 01.12.2009 18:34