¿Cómo puedo manejar la entrada en C sin detener el bucle principal?
Quiero que mi programa C actualice la consola cada segundo, y funcionaba bien hasta que intenté manejar la entrada. Ahora el programa se detiene ya que espera una entrada del usuario. ¿Cómo puedo hacer esto?
while(true) {
ShowConsole(); //Show
Sleep(1000); //Wait
scanf("%s",&a) //Handle Input
Update();
ClearScreen(); //Clear
}
Respuestas
Me tomé la libertad de intentar abordar esto yo mismo.
Basándome únicamente en el texto de la pregunta, no está muy claro qué tipo de juego estás tratando de hacer, así que tomé el enfoque de una especie de juego de serpientes , donde la serpiente se moverá, lo que sea que el jugador esté haciendo (o no haciendo) .
He utilizado Sleep
a pasearse por la entrada de votación y la velocidad de redibujado, y _kbhit()
que tal vez leído un carácter, y el clock_t
/ clock()
a actualizar el juego una vez por segundo.
Ahora no soy c
programador, así que no sé si este c
código es "elegante" (probablemente no lo sea), pero funcionó en mi 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;
}
Un par de cosas a anotar:
- Probablemente hay otras (mejores) formas de lograr esto: por ahora, cuando actualizo (ClearScreen), la pantalla "parpadea" un poco.
- en Windows, el sistema operativo "acelerará" la tasa de repetición del carácter que envía a las aplicaciones, por lo que cuando presionas, dpor ejemplo, el programa mostrará que estás presionando d, luego mostrará que no presionas ninguna tecla, luego mostrará que está presionando dnuevamente, hasta que suelte la tecla.
- al igual que su propia implementación, no es portátil debido a la naturaleza de las funciones utilizadas.
Aunque tuve que usar un código no portátil, lo hice funcionar sin la necesidad de una biblioteca de terceros. También resulta que la función _kbhit () retrasa el búfer, por lo que no es necesario esperar 1 segundo para ingresar la cadena completa. Sin embargo, la cadena escrita se cortaba si no se escribía en un segundo. Así que también lo mostré en la función ShowConsole ().
Nota: Este es un código no estándar ni portátil. Funciona en mi sistema operativo (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++;
}
En la función ShowConsole ():
ShowConsole(){
.
.
.
printf("%s", moveInput); // At the end of showing the graphics, also show the input that is being written.
}