Bagaimana cara menangani input dalam C tanpa menghentikan loop utama?
Saya ingin program C saya memperbarui konsol setiap detik, dan itu berfungsi dengan baik sampai saya mencoba menangani masukan. Sekarang program berhenti karena menunggu masukan dari pengguna. Bagaimana saya bisa melakukan ini?
while(true) {
ShowConsole(); //Show
Sleep(1000); //Wait
scanf("%s",&a) //Handle Input
Update();
ClearScreen(); //Clear
}
Jawaban
Saya mengambil kebebasan untuk mencoba dan menangani ini sendiri.
Hanya berdasarkan teks pertanyaan, tidak terlalu jelas jenis permainan apa yang Anda coba lakukan, jadi saya mengambil pendekatan semacam permainan ular , di mana ular akan bergerak, apa pun yang pemain lakukan (atau tidak lakukan) .
Saya menggunakan Sleep
mondar-mandir di polling input dan tingkat redraw, dan _kbhit()
untuk mungkin membaca karakter, dan clock_t
/ clock()
memperbarui permainan sekali per detik.
Sekarang saya bukan seorang c
programmer, jadi saya tidak tahu apakah c
kode ini "elegan" (mungkin tidak), tetapi berfungsi pada mesin saya (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;
}
Beberapa hal yang perlu diperhatikan:
- mungkin ada cara lain (lebih baik) untuk mencapai ini: untuk saat ini, ketika saya menyegarkan (ClearScreen), layar "berkedip" sedikit.
- pada Windows, OS akan "memacu" tingkat pengulangan karakter yang dikirim ke aplikasi, jadi ketika Anda menekan dmisalnya, program akan menunjukkan bahwa Anda menekan d, kemudian akan menunjukkan bahwa Anda tidak menekan tombol, maka itu akan menunjukkan Anda menekan dlagi, sampai Anda melepaskan kunci.
- seperti penerapan Anda sendiri, ini tidak portabel karena sifat fungsi yang digunakan.
Meskipun saya harus menggunakan kode non-portabel, saya membuatnya berfungsi tanpa memerlukan perpustakaan pihak ketiga. Juga ternyata fungsi _kbhit () menunda buffer sehingga Anda tidak perlu menunggu 1 detik untuk memasukkan string lengkap. Namun string tertulis itu dipotong jika tidak ditulis dalam sedetik. Jadi saya juga menunjukkannya di fungsi ShowConsole ().
Catatan: Ini adalah kode non-standar, non-portabel. Bekerja di OS saya (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++;
}
Dalam Fungsi ShowConsole ():
ShowConsole(){
.
.
.
printf("%s", moveInput); // At the end of showing the graphics, also show the input that is being written.
}