Como posso controlar a entrada em C sem interromper o loop principal?
Quero que meu programa C atualize o console a cada segundo e estava funcionando bem até que tentei controlar a entrada. Agora o programa é interrompido, pois espera uma entrada do usuário. Como posso fazer isso?
while(true) {
ShowConsole(); //Show
Sleep(1000); //Wait
scanf("%s",&a) //Handle Input
Update();
ClearScreen(); //Clear
}
Respostas
Tomei a liberdade de tentar resolver isso sozinho.
Com base exclusivamente no texto da pergunta, não está muito claro que tipo de jogo você está tentando fazer, então usei a abordagem de um tipo de jogo de cobra , onde a cobra se moverá, o que quer que o jogador esteja fazendo (ou não) .
Eu costumava Sleep
a andar a votação de entrada ea taxa de redesenho, e _kbhit()
para talvez ler um personagem, eo clock_t
/ clock()
a atualizar o jogo uma vez por segundo.
Agora não sou um c
programador, então não sei se este c
código é "elegante" (provavelmente não é), mas funcionou na minha máquina (Windows, Visual Studio).
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <ctype.h>
#include <windows.h>
typedef int BOOL;
#define FALSE ((int)0)
#define TRUE ((int)1)
void ClearScreen()
{
// code here that clears the screen, see https://stackoverflow.com/a/42500322
}
int main( void )
{
BOOL run = TRUE;
clock_t lastTickClock = clock();
int position = 0;
char registeredCommand = 'd'; // Command that will be effective at the next game tick.
while ( run )
{
char currentCharIfAny = 0; // The char that is read this loop.
if ( _kbhit() )
currentCharIfAny = _getch();
if ( currentCharIfAny == 'a' || currentCharIfAny == 'd' )
registeredCommand = currentCharIfAny; // We only respond to 'a' or 'd'.
clock_t newClock = clock();
if ( ( newClock - lastTickClock ) > CLOCKS_PER_SEC )
{
// This is the command handling/the game tick
if ( registeredCommand == 'a' )
position = max( --position, 0 );
else if ( registeredCommand == 'd' )
position = min( ++position, 24 );
lastTickClock = newClock;
}
char buffer[1024];
buffer[0] = 0;
for ( int i = 0; i < position; ++i )
strcat_s( buffer, 1024, " " );
strcat_s( buffer, 1024, "_\n" ); // This underscore represents our "agent" or "game token" or "paddle".
// The following is only for debugging purpose; it prints the character we're currently handling.
if ( currentCharIfAny >= 'a' && currentCharIfAny <= 'z' )
{
char lbuff[2]; lbuff[0] = 0;
sprintf_s( lbuff, 2, "%c", currentCharIfAny );
strcat_s( buffer, 1024, lbuff );
}
ClearScreen();
printf( "%s\n", buffer );
Sleep( 1000 / 60 );
if ( currentCharIfAny == 'q' )
run = FALSE;
}
printf( "\ndone. press a key to quit." );
_getch();
return 0;
}
Algumas coisas a serem observadas:
- provavelmente existem outras (melhores) maneiras de fazer isso: por enquanto, quando eu atualizo (ClearScreen), a tela "pisca" um pouco.
- no Windows, o sistema operacional "acompanhará" a taxa de repetição do caractere que envia para os aplicativos, então quando você apertar, dpor exemplo, o programa mostrará que você está apertando d, então mostrará que você não está apertando nenhuma tecla, então ele mostrará que você está batendo dnovamente, até que você solte a tecla.
- como sua própria implementação, não é portátil devido à natureza das funções usadas.
Embora eu tenha que usar um código não portátil, consegui fazê-lo funcionar sem a necessidade de uma biblioteca de terceiros. Além disso, a função _kbhit () atrasa o buffer, então você não precisa esperar 1 segundo para inserir a string completa. No entanto, a string escrita estava sendo cortada se não fosse escrita em um segundo. Então, eu também mostrei na função ShowConsole ().
Nota: Este é um código não padronizado e não portátil. Funciona no meu SO (Windows).
char key;
if(_kbhit()){
key = _getch();
if(key == 13){ //If Enter key is pressed
HandleInput(moveInput); //handle the input string
memset(moveInput, 0, 6); //clear input string
moveIndex=0; //reset string index to 0
}
moveInput[moveIndex] = key; //If any other key is pressed, add the hit character to string input
moveIndex++;
}
Na função ShowConsole ():
ShowConsole(){
.
.
.
printf("%s", moveInput); // At the end of showing the graphics, also show the input that is being written.
}