Jak mogę obsłużyć dane wejściowe w C bez zatrzymywania głównej pętli?
Chcę, aby mój program w C aktualizował konsolę co sekundę i działał dobrze, dopóki nie spróbowałem obsłużyć danych wejściowych. Teraz program zatrzymuje się, ponieważ oczekuje na dane wejściowe od użytkownika. Jak mogę to zrobić?
while(true) {
ShowConsole(); //Show
Sleep(1000); //Wait
scanf("%s",&a) //Handle Input
Update();
ClearScreen(); //Clear
}
Odpowiedzi
Pozwoliłem sobie samemu się tym zająć.
Opierając się wyłącznie na tekście pytania, nie jest bardzo jasne, jaką grę próbujesz zrobić, więc przyjąłem podejście do gry w węża , w której wąż będzie się poruszał, cokolwiek gracz robi (lub nie robi) .
Kiedyś Sleep
chodzić odpytywanie wejściowy i szybkość odświeżania, a _kbhit()
do może odczytać charakter i clock_t
/ clock()
zaktualizować grę raz na sekundę.
Teraz nie jestem c
programistą, więc nie wiem, czy ten c
kod jest „elegancki” (chyba nie), ale zadziałał na moim komputerze (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;
}
Kilka uwag:
- są prawdopodobnie inne (lepsze) sposoby osiągnięcia tego: na razie, kiedy odświeżam (ClearScreen), ekran trochę "migocze".
- w systemie Windows system operacyjny będzie „przyspieszał” tempo powtarzania znaku, który wysyła do aplikacji, więc gdy dna przykład naciśniesz , program pokaże, że uderzasz d, a następnie pokaże, że nie naciskasz żadnego klawisza, wtedy pokaże, że uderzasz dponownie, dopóki nie zwolnisz klawisza.
- podobnie jak Twoja własna implementacja, nie jest przenośna ze względu na charakter używanych funkcji.
Chociaż musiałem użyć kodu nieprzenośnego, udało mi się go uruchomić bez potrzeby biblioteki innej firmy. Okazuje się również, że funkcja _kbhit () opóźnia buforowanie, więc nie trzeba czekać 1 sekundę na wprowadzenie pełnego ciągu. Jednak napisany ciąg był odcinany, jeśli nie został zapisany w ciągu sekundy. Więc pokazałem to również w funkcji ShowConsole ().
Uwaga: to jest kod niestandardowy, nieprzenośny. Działa w moim systemie operacyjnym (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++;
}
W funkcji ShowConsole ():
ShowConsole(){
.
.
.
printf("%s", moveInput); // At the end of showing the graphics, also show the input that is being written.
}