메인 루프를 중단하지 않고 C의 입력을 어떻게 처리 할 수 있습니까?
Dec 16 2020
내 C 프로그램이 매초마다 콘솔을 업데이트하기를 원하며 입력을 처리하려고 할 때까지 제대로 작동했습니다. 이제 프로그램은 사용자의 입력을 기다리기 때문에 중지됩니다. 어떻게 할 수 있습니까?
while(true) {
ShowConsole(); //Show
Sleep(1000); //Wait
scanf("%s",&a) //Handle Input
Update();
ClearScreen(); //Clear
}
답변
1 Vaillancourt Dec 17 2020 at 08:32
나는이 문제를 스스로 해결할 자유를 얻었다.
질문 텍스트만으로는 어떤 종류의 게임을하려고하는지 명확하지 않기 때문에 플레이어가 무엇을하든하지 않든, 뱀이 어디로 이동할 것인가 하는 일종의 스네이크 게임에 접근했습니다. .
내가 사용하는 Sleep
입력 폴링 및 다시 그리기 속도를 속도를 조절하고, _kbhit()
할 어쩌면 문자를 읽고, 그리고 clock_t
/ clock()
초당 한 번 게임을 업데이트 할 수 있습니다.
이제 저는 c
프로그래머가 아니기 때문에이 c
코드가 "우아한"지 (아마도 그렇지 않은지) 모르겠지만 내 컴퓨터 (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;
}
몇 가지 유의할 사항 :
- 이 작업을 수행하는 다른 (더 나은) 방법이있을 수 있습니다. 현재로서는 (ClearScreen)을 새로 고치면 화면이 약간 "깜빡입니다".
- Windows에서 OS는 앱에 보내는 문자의 반복 속도를 "빠르게"하므로 d예를 들어를 누르면 프로그램이를 치고 d있음을 표시 한 다음 키를 누르지 않음을 표시합니다. 그러면 d키를 놓을 때까지 다시 치는 것을 보여줍니다 .
- 자신의 구현과 마찬가지로 사용되는 기능의 특성으로 인해 이식 할 수 없습니다.
AliTeo Dec 16 2020 at 05:28
이식 불가능한 코드를 사용해야했지만 타사 라이브러리 없이도 작동하도록했습니다. 또한 _kbhit () 함수가 버퍼를 지연 시키므로 전체 문자열을 입력하기 위해 1 초 동안 기다릴 필요가 없습니다. 그러나 1 초 안에 쓰여지지 않으면 쓰여진 문자열이 잘리고있었습니다. 그래서 ShowConsole () 함수에서도 보여주었습니다.
참고 : 이것은 비표준적이고 이식 불가능한 코드입니다. 내 OS (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++;
}
ShowConsole () 함수에서 :
ShowConsole(){
.
.
.
printf("%s", moveInput); // At the end of showing the graphics, also show the input that is being written.
}