joao_o grande Posted January 9, 2016 at 03:06 PM Report Share #591704 Posted January 9, 2016 at 03:06 PM (edited) Ola, como é que eu devo fazer para colocar um cronometro num ciclo repeat, ou seja, quando o cronometro chegar a 30. o ciclo repeat pára de funcionar. Nota: eu sei fazer o cronómetro. Edited January 9, 2016 at 03:08 PM by joao_o grande Link to comment Share on other sites More sharing options...
pwseo Posted January 9, 2016 at 03:13 PM Report Share #591705 Posted January 9, 2016 at 03:13 PM joao_o grande, Podes ter uma variável «de controlo» que é verificada no ciclo para saber se este será ou não executado. Basta que essa variável seja alterada ao fim de 30 segundos (presumo que sejam segundos). O que tens feito para já? Link to comment Share on other sites More sharing options...
joao_o grande Posted January 9, 2016 at 05:12 PM Author Report Share #591707 Posted January 9, 2016 at 05:12 PM (edited) sim, são 30 segundos. a estrutura é algo deste género: repeat Case ch of Case ch of //comandos for end; end; end; until ... os dois primeiros cases movem um cursor. o until do repeat pode estar relacionado com essa variavel de controlo. Aqui fica o que tenho: repeat ch:=readkey; Case ch of #0:begin ch:=readkey; Case ch of #75:begin //left Escrever(Jogador.X,Jogador.Y,' ',False); Jogador.X:=Jogador.X-1; end; #77:begin //right Escrever(Jogador.X,Jogador.Y,' ',False); Jogador.X:=Jogador.X+1; end; #80:begin //up Escrever(Jogador.X,Jogador.Y,' ',False); Jogador.Y:=Jogador.Y+1; end; #72:begin //down Escrever(Jogador.X,Jogador.Y,' ',False); Jogador.Y:=Jogador.Y-1; end; end; If Jogador.X>MaxX then Jogador.X:=MaxX else If Jogador.X<MinX then Jogador.X:=MinX; If Jogador.Y>MaxY then Jogador.Y:=MaxY else If Jogador.Y<MinY then Jogador.Y:=MinY; textcolor(15); Desenha_Jogador(Jogador.X,Jogador.Y); for n_com:=1 to n_comida do If (Jogador.X=coordenadasx[n_com]) and (Jogador.Y=coordenadasy[n_com]) then Begin Pontos:=Pontos+1; Textcolor(13); gotoxy(2,24); Writeln('Pontos: ',Pontos); end; end; #27:Exit; end; until ch=#27; o meu objetivo é: quando passarem 30 segundos este ciclo repeat termina. Tbm queria que o tempo aparecesse na posiçao 60,24. Não sei se te interessa perceber o ciclo for, mas os vetores coordenadasx[n_com] e coordenadasy[n_com] criam um carater (#178) aleatorio na tela. Há n_comida destes caracteres aleatorios e o qie o ciclo for faz é aumentar o numero de pontos se as posiçoes Jogador.X e Jogador.Y (ou seja o caracter branco que o usuario move pela tela) coincidirem com um caracter aleatorio. Edited January 9, 2016 at 05:26 PM by joao_o grande Link to comment Share on other sites More sharing options...
pwseo Posted January 9, 2016 at 05:16 PM Report Share #591708 Posted January 9, 2016 at 05:16 PM Onde está o código que controla a passagem do tempo? Referiste que também sabias fazer isso. Link to comment Share on other sites More sharing options...
joao_o grande Posted January 9, 2016 at 06:04 PM Author Report Share #591710 Posted January 9, 2016 at 06:04 PM (edited) Já o apaguei e decidi deixar estar como estava dantes. Já o faço. Fi.lo numa function, ok?? 5 minutos depois........ Cá está ele, é um funçao do tipo boolean se quiseres eu mudo. para integer, ou assim. O meu problema neste caso é como ligar esta function ao repeat... Sempre que eu chamo esta function não posso mover o caracter pela tela uma vez que ele primeiro conta 30 segundos e depois disso fecha o programa porque é o fim do repeat Program Cronometro ;function Cronos (tmp_desejado:integer) : boolean;var i:byte;Begin Cronos:=False; for i:= 1 to tmp_desejado do begin If i<10 then begin delay(1000); Gotoxy(60,24); Writeln('Tempo: 00:0',i); end else begin delay(1000); Gotoxy(60,24); Writeln('Tempo: 00:',i); end; end; Cronos:=True;end;Begin Cronos(30);End.[/Code] Edited January 9, 2016 at 06:18 PM by joao_o grande Link to comment Share on other sites More sharing options...
pwseo Posted January 9, 2016 at 07:47 PM Report Share #591721 Posted January 9, 2016 at 07:47 PM joao_o grande, Da forma que estás a fazer vais ter dificuldade em resolver o teu problema. O ideal é fazeres a contagem do tempo dentro do repeat .. until, recorrendo a valores do tipo TDateTime e à função SecondsBetween. Vais ter que determinar quantas vezes queres que o ciclo seja executado por segundo para determinar o que fornecer como parâmetro à delay, pois o valor de 1000 implica uma paragem durante 1 segundo inteiro no teu programa (e pode não ser isso que queres). De uma forma mais geral, é o seguinte: o teu programa (ou jogo, o que for) deveria ter todo o seu funcionamento *dentro* desse ciclo repeat .. until, pois assim todos os componentes passariam a ter acesso a uma forma de medir o tempo. A tua função Cronos só deveria ser responsável por escrever o tempo actual, e não contá-lo também. Atenção: isto são coisas algo complicadas, não te sintas mal se não perceberes tudo. 1 Report Link to comment Share on other sites More sharing options...
joao_o grande Posted January 9, 2016 at 10:02 PM Author Report Share #591741 Posted January 9, 2016 at 10:02 PM (edited) percebi mais ou menos o que disseste, exceto: joao_o grande, De uma forma mais geral, é o seguinte: o teu programa (ou jogo, o que for) deveria ter todo o seu funcionamento *dentro* desse ciclo repeat .. until, pois assim todos os componentes passariam a ter acesso a uma forma de medir o tempo. A tua função Cronos só deveria ser responsável por escrever o tempo actual, e não contá-lo também. Podes dar-me uma sugestão de erstrutura?? Estou um bocado à nora. como é que é suposto eu escrever o tempo sem o contar?? Edited January 9, 2016 at 10:02 PM by joao_o grande Link to comment Share on other sites More sharing options...
pwseo Posted January 9, 2016 at 10:14 PM Report Share #591743 Posted January 9, 2016 at 10:14 PM Repara no seguinte pseudo-código: inicio ← time() repeat agora ← time() tempo-passado ← seconds-between(inicio, agora) # Aqui estaria a parte principal do teu programa # Esta função desenharia o tempo passado desenhar-cronometro(tempo-passado) # Este valor de 50 é arbitrário... terias que decidir o melhor para ti delay(50) until quit = True 1 Report Link to comment Share on other sites More sharing options...
thoga31 Posted January 10, 2016 at 12:36 AM Report Share #591746 Posted January 10, 2016 at 12:36 AM (edited) como é que é suposto eu escrever o tempo sem o contar?? Se eu te pedir para veres quando passou 1 hora, tu vais pegar no relógio e contar segundo a segundo sem tirares os olhos do relógio, ou vais vendo de tempos a tempos e calcular de cabeça se já passou 1 hora? O pensamento aqui é o mesmo. Neste momento tu estás a pedir ao programa que conte segundo a segundo - o que nem sequer é exacto, e já explico porquê - usando o Delay. Isto traz um problema grave: durante esse segundo, o programa está parado uma vez que essa é a função do Delay. Nota bem isto: durante o Delay, o programa não faz mais nada a não ser esperar os milissegundos que indicaste! Aquilo que tu deves pedir ao programa é calcular quanto tempo já passou desde o início do ciclo repeat. Existe um tipo de dados, o TDateTime, que permite manipular datas de forma simples. Este tipo de dados e respectivas funções e procedimentos estão disponíveis nas units sysutils e dateutils. NOTA: porque é que usar o Delay não é exacto? Qualquer comando gasta um determinado tempo a ser processador na CPU. Mesmo sendo normalmente na ordem de milésimas de segundo, é um tempo com o qual devemos contar. Este tempo é maior quantos mais comandos dermos à CPU para processar (isto dito de uma forma muito simplista). Ora, tu pedes 30 vezes um Delay de 1000 milissegundos - tempo este no qual o programa pára e não faz mais nada -, mas entre cada Delay tu dás uma série de comandos à CPU para processar. Imaginemos que esta série de comandos demoram 10 milissegundos de cada vez. Ao fim dos 30 Delays, passaram 30*(1000+10) = 30300 milissegundos, ou seja, 30,3 segundos - passaram 300 milissegundos a mais daquilo que pretendias. Este é o motivo pelo qual jamais se faz um cronómetro usando o Delay! Ele é minimamente exacto em contagens de tempo pequenas, mas rapidamente começa a ganhar um erro enorme, contando menos tempo do que aquele que realmente passou. Cumprimentos. Edited January 10, 2016 at 12:41 AM by thoga31 1 Report Knowledge is free! Link to comment Share on other sites More sharing options...
joao_o grande Posted January 10, 2016 at 01:55 AM Author Report Share #591751 Posted January 10, 2016 at 01:55 AM Em 10/01/2016 às 01:36, thoga31 disse: contando menos tempo do que aquele que realmente passou. Cumprimentos. Muito obrigado pela explicação: so um pequeno pormenor: menos = mais. Link to comment Share on other sites More sharing options...
thoga31 Posted January 10, 2016 at 02:05 AM Report Share #591752 Posted January 10, 2016 at 02:05 AM Em 10/01/2016 às 02:55, joao_o grande disse: so um pequeno pormenor: menos = mais. Menos. Olha o exemplo que te dei dos 30 segundos com comandos a demorar 10 milissegundos de cada vez que eram executados. No final contaste 30 segundos mas passaram 30,3 segundos. Vamos passar a 1 hora: são contados 3600 segundos mas passaram 3636 segundos. Então, contou mais ou menos do que o tempo real que passou? Knowledge is free! Link to comment Share on other sites More sharing options...
KTachyon Posted January 10, 2016 at 04:40 AM Report Share #591754 Posted January 10, 2016 at 04:40 AM Este problema é relativamente fácil de resolver utilizando event-driven programming (ou programação orientada a eventos, em português). Carregar numa tecla é um evento. E podes agendar um evento para acontecer no futuro (e, dependendo de quão low level a linguagem conseguir chegar, a precisão que se pretende). Basicamente, a ideia é teres um handler que está à escuta por eventos do teclado e que é configurado com uma estratégia. E depois tens qualquer coisa que agenda um evento que muda a estratégia do handler passado X tempo. Não te vou dizer como é que isto se faz em Pascal, mas tendo em conta que praticamente todas as linguagens modernas têm mecanismos para fazer isto, não deve ser difícil de descobrir como é que isto se faz. “There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.” -- Tony Hoare Link to comment Share on other sites More sharing options...
joao_o grande Posted January 10, 2016 at 10:15 AM Author Report Share #591758 Posted January 10, 2016 at 10:15 AM Este problema é relativamente fácil de resolver utilizando event-driven programming (ou programação orientada a eventos, em português). Carregar numa tecla é um evento. E podes agendar um evento para acontecer no futuro (e, dependendo de quão low level a linguagem conseguir chegar, a precisão que se pretende). Basicamente, a ideia é teres um handler que está à escuta por eventos do teclado e que é configurado com uma estratégia. E depois tens qualquer coisa que agenda um evento que muda a estratégia do handler passado X tempo. Não te vou dizer como é que isto se faz em Pascal, mas tendo em conta que praticamente todas as linguagens modernas têm mecanismos para fazer isto, não deve ser difícil de descobrir como é que isto se faz. No percebi o que quiseste dizer com isso. Mas está relacionado com o tempo?? Link to comment Share on other sites More sharing options...
joao_o grande Posted January 10, 2016 at 10:34 AM Author Report Share #591760 Posted January 10, 2016 at 10:34 AM (edited) Bem, já consegui fazer um relogio. Agora so tenho de fazer algumas alterações para parecer um cronometro. Aceitam-se sugestões. Aqui fica o codigo: program relogio_sistema; uses crt; type TDataHora = record relogio : record hora : word; minuto : word; segundo : word; centesimo_segundo : word; end; data : record ano : word; mes : word; dia : word; dia_semana : word; end; end; procedure GuardaDataHora(var datahora : TDataHora); begin with datahora.relogio do begin gettime(hora, minuto, segundo, centesimo_segundo); // determina a hora do sistema end; with datahora.data do begin getdate(ano, mes, dia, dia_semana); // determina a data do sistema end; end; var tempo_registo : TDataHora; begin cursoroff; repeat GuardaDataHora(tempo_registo); with tempo_registo.relogio, tempo_registo.data do begin Gotoxy(1,1); writeln(hora,':',minuto,':',segundo); end; until keypressed; end. Edited January 10, 2016 at 10:34 AM by joao_o grande Link to comment Share on other sites More sharing options...
nunopicado Posted January 10, 2016 at 12:16 PM Report Share #591763 Posted January 10, 2016 at 12:16 PM (edited) No percebi o que quiseste dizer com isso. Mas está relacionado com o tempo?? O que o @KTachyon está a falar, é extremamente válido em Object Pascal, ou qualquer linguagem OO/ED (Object Oriented/Event Driven). No teu caso concreto, creio que é melhor manteres-te para já com as sugestões do @pwseo e do @Thoga31. Mas guarda a dica dele na memória. Um dia, quando tiveres os conceitos de programação básicos bem definidos, e começares a mexer em conceitos OO/ED, será interessante refazeres este projecto com recursos como objectos e eventos. Bem, já consegui fazer um relogio. Agora so tenho de fazer algumas alterações para parecer um cronometro. Aceitam-se sugestões. Aqui fica o codigo: O teu relógio tem dois problemas: 1. Está permanentemente a escrever a data e hora no ecrã, sem controlo. Visto que todo aquele ciclo repeat demora menos de um segundo a ser executado pelo processador, quer dizer que a mesma data/hora será escrita várias vezes no ecrã, quando o que devia acontecer era escrever apenas se a data/hora for diferente da que lá está. Deverias ter uma segunda variável do tipo TDataHora, que guarde a última hora que foi escrita, e só escrever novamente se elas forem diferentes: var tempo_registo, lastDateTime : TDataHora; begin cursoroff; lastDateTime.Data.ano := 0; // Inicializa a variável lastDateTime. Basta neste caso inicializar o campo Ano, porque é certo que tempo_registo nunca terá o ano 0, pelo que a primeira comparação irá ser True (são diferentes) e portanto, irá ser escrita a data e hora inicial sem problemas. repeat GuardaDataHora(tempo_registo); if tempo_registo <> lastDateTime then with tempo_registo.relogio, tempo_registo.data do begin lastDateTime := tempo_registo; Gotoxy(1,1); writeln(hora,':',minuto,':',segundo); end; until keypressed; end. No entanto, para isto funcionar, tens de te livrar o campo centesimo_segundo, que não usas para nada, mas iria fazer com que a data e hora fosse escrita no ecrã bastando que mudasse o centésimo, ou seja, 100x mais do que o necessário (em teoria). Como não o usas, seria caso de removeres o campo: type TDataHora = record relogio : record hora : word; minuto : word; segundo : word; end; data : record ano : word; mes : word; dia : word; dia_semana : word; end; end; procedure GuardaDataHora(var datahora : TDataHora); var centesimo_segundo: Word; // A variável centesimo_segundo passa a ser local, e não será usada para mais nada begin with datahora.relogio do begin gettime(hora, minuto, segundo, centesimo_segundo); // determina a hora do sistema end; with datahora.data do begin getdate(ano, mes, dia, dia_semana); // determina a data do sistema end; end; Isto vai reduzir imenso o número de vezes que a data e hora é escrita. Na verdade, vai escrever apenas uma vez por segundo, muito mais optimizado do que escrever sempre que o ciclo completa uma volta. Se só mostrasses minutos e segundos, bastava-te tirar o campo segundos do record, e a data/hora já só seria escrita uma vez por minutos. O teu segundo problema leva-te de encontro ao conceito de threads. Um programa em Pascal tem, nativamente, uma thread, ou seja, um fluxo único em que os comandos são executados. Um comando só é executado depois de terminada a execução do seu antecessor. Na prática isto quer dizer que este teu código de relógio só funciona correctamente em duas situações: 1. Se o programa só fizer isto 2. Se o programa fizer mais coisas, mas essas outras coisas, no total, demorarem menos do que a unidade mais pequena que escreves no ecrã, neste caso, se demorarem menos de 1 segundo. Isto engloba tudo, desde as instruções que dás ao tempo que o utilizador tem para reagir - é impraticável. "E se essas coisas demorarem mais", perguntas tu... Pois, não morre ninguém neste caso. Simplesmente o relógio vai saltar numeros. Imagina que o que fazes demora 10 segundos. O relógio só será actualizado a cada 10 segundos. Se demorar 10 minutos, o relógio só é actualizado a cada 10 minutos, e assim sucessivamente. Isto porque o ciclo repeat só será concluído depois de tudo feito. Se esta limitação servir para o teu programa, tudo bem, podes avançar. Lembra-te só que tudo o que estiver controlado pelo relógio deve estar dentro daquele repeat...until. Se não funcionar, como resolver? Como ter um relógio a trabalhar tranquilamente sem que isso interfira no resto do programa? A única solução é fazeres com que a execução do relógio não esteja dependente da execução do resto do código, ou seja, estarem em fluxos de execução diferentes. Para fazer isso, ou vamos de volta ao que disse o @KTachyon, com um sistema de eventos, em que o programa está permanentemente a verificar determinadas condições (mudança de hora) e caso se verifique, escreve a nova hora (de forma independente do restante código), ou então tens de criar uma nova thread, um novo fluxo de execução, e colocar o relógio nesse fluxo à parte. Nesta fase em que estás a aprender ainda os conceitos básicos, threads não me parecem de todo um passo que devas dar já. Enquanto não tiveres bem definidos os conceitos básicos na tua forma de programar, avançares para threads é dar um tiro no pé, pois o risco de bugs é enorme, especialmente porque no caso do teu jogo vai haver momentos em que as threads têm de ser sincronizadas, pois terão de aceder aos mesmos recursos (variáveis, por exemplo). Edited January 10, 2016 at 04:55 PM by nunopicado "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to comment Share on other sites More sharing options...
thoga31 Posted January 10, 2016 at 03:51 PM Report Share #591771 Posted January 10, 2016 at 03:51 PM Todos estes tópicos levam-me a comentar algo que tenho vindo a concluir. @joao_o grande, gosto bastante de ver este teu entusiasmo em programar em Pascal, mas tenho visto que ainda há vários conceitos com os quais não estás bem familiarizado, e falo em conceitos fundamentais do Pascal. É minha opinião que, nesta fase, estás a dar o passo maior que a perna. Sem dúvida que este programa te está a levar a aprender imensas coisas, mas a verdade é que estás a aprender demasiadas coisas para um programa só na tua fase de aprendizagem. Digo isto porque estás a lidar com diversos conceitos que deviam ficar bem cimentados e, com o desenvolver deste programa, aquilo que tenho visto é que, assim que consegues resolver um problema que tens em mãos, consideras o assunto resolvido mesmo que os conceitos inerentes não ficassem, de todo, cimentados. Isto é problemático uma vez que, quando quiseres avançar para outros programas, vais ter dificuldade em implementar de novo estes conceitos. Vais ver os teus programas anteriores mas não vais conseguir possivelmente adaptar boa parte do código uma vez que em cada programa há uma implementação específica do conceito que pode não se ajustar ao que precisas no próximo programa. Friso novamente que considero muito bom quereres aprender mais acerca desta linguagem. Apenas quero deixar a minha opinião acerca deste assunto em particular: não é vantajoso aplicares conceitos sem antes os dominares. Uma sugestão (que é aquilo que eu ainda hoje faço quando preciso de aprender conceitos novos): podes ir fazendo este programa, mas quando te deparas com um novo conceito, treina-o à parte, e só quando o dominares minimamente é que o tentas implementar no programa. Cumprimentos. 1 Report Knowledge is free! Link to comment Share on other sites More sharing options...
joao_o grande Posted January 11, 2016 at 07:32 PM Author Report Share #591830 Posted January 11, 2016 at 07:32 PM Obrigado pela critica. Se calhar vou deixa-lo de parte por uns tempos. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now