paulo1205
(usa Ubuntu)
Enviado em 08/12/2014 - 06:11h
luccasrodge escreveu:
Obrigado pela disposição gente! Agora a dúvida seria outra, o tempo de resposta do teclado tá demorando alguns segundos pra modificar a posição i ou j, já tentei configurar o sleep, só que não to conseguindo, ou seja, uando apertar a tecla (cima,baix,esquerda,direita) mudar exatamente no exato momento a posição ... será necessário abrir outro tópico ?
Eu quase acertei quando falei em ConIO, não? Eu errei ao supor o Turbo C sobre DOS/Windows, mas o que você fez foi reinventar a ConIO do Turbo C, ou um pedaço dela, no Linux.
Você deveria considerar as boas dicas que lhe foram dadas. Pode acreditar: Curses é muito melhor do que ConIO. Além disso, a não ser que seja com objetivo didático, reinventar a roda costuma ser meio contraproducente.
No entanto, permita-me ajudá-lo com a “neorroda”.
As operações com terminal são necessariamente de baixo nível. Assim sendo, a primeira dica que lhe dou é não misturar operações sobre o descritor
STDIO_FILENO com entrada de mais alto nível no stream
stdin . Trabalhe consistentemente somente com o descritor, até porque você não conhece nem tem muito controle sobre o funcionamento interno das operações feitas sobre streams (aliás, os comentários no seu código que dizem fazer uma leitura sem buffers estão simplesmente errados).
Em lugar das chamadas a
getchar () dentro da sua versão de
getch () e
getche (), use algo como vai abaixo.
char ch;
if(read(STDIN_FILENO, &ch, 1)==1){
/* Leitura bem sucedida. */
}
Sua função
kbhit () tem problema parecido. Na verdade, tudo o que você gostaria de fazer é um
select () ou
poll () aplicado a
STDIN_FILENO .
inline bool kbhit(){
struct pollfd pollstdin={STDIN_FILENO, POLLIN, 0};
return poll(&pollstdin, 1, 0)==1;
}
Nessas três funções, é um desperdício tirar o terminal de modo canônico e desligar o eco e religar depois, pois você não faz qualquer operação de entrada que dependa do modo canônico voltar a ser ligado (aliás, nem do eco; sua função
getche () não é usada ao longo do programa -- em todo caso é trivialmente fácil sintetizar uma
getche () que não precise ligar o eco, a partir de
getch () e de uma operação de saída no terminal do byte por ela lido, se tal byte for imprimível). Parece-me que você quer que o modo canônico e o eco permaneçam desligados durante todo o jogo. Então faça isso só uma vez, no começo do programa, lembrando apenas de religá-los antes de o programa terminar.
Você não a usa, apesar de a definir, mas a função
clrscr () tem uma estranha dupla passada para definir um string com uma sequência de escape. Tal dupla passada é desnecessária, pois o C e o C++ permitem embutir qualquer caráter no meio de um string através das notações “\
número_octal “ ou “\x
número_hexadecimal ”. Você poderia, portanto, escrever
"\33[H\33[2J" ou
"\x1b[H\x1b[2J" . Em todo caso, a melhor forma de fazer o que você quer não é usar uma sequência de escape fixa de um tipo específico de terminal. Ainda que esse tipo seja, na prática, o mais comum, você pode topar com gente como eu, que passou anos trabalhando com terminais de texto que não eram compatíveis com VT100 nem ANSI (e aguarda a chance de ter um daqueles velhos terminais na sua coleção). Além de para esses dinossauros, para qualquer pessoa minimamente interessada em fazer código portável a forma correta de limpar a tela é consultar as informações do terminal e usar a sequência de escape correta para tal terminal.
/* No começo do programa... */
setupterm(NULL, STDOUT_FILENO, NULL);
/*
O NULL no primeiro argumento faz com que o terminal seja lido
da variável de ambiente TERM. O do terceiro é preguiça de alocar
uma variável para receber eventuais sinalizações de erro. Fique
à vontade para melhorar isso.
*/
/* ... */
/* Para limpar a tela. */
putp(clear_screen);
(Para usar isso, na hora de chamar o linker, inclua a biblioteca
termcap (opção “-ltermcap” passada ao gcc ou ao ld). Leia a documentação de
setupterm () e
putp () -- é a mesma manpage, aliás.)
Não entendi o problema com
sleep () que você mencionou. Em todo caso, acho que, para um jogo de testes de habilidades, uma pausa mínima de um segundo é um tanto grande demais. Considere usar
usleep () ou
nanosleep (), ou aproveite os parâmetros de timeout de
poll () (em milissegundos) ou
select () (resolução de microssegundos). Outra opção é usar um timer para redesenhar a tela periodicamente (leia sobre
setitimer () e
sigaction ()).