मैं मुख्य लूप को रोकने के बिना सी में इनपुट कैसे संभाल सकता हूं?

Dec 16 2020

मैं चाहता हूं कि मेरा सी प्रोग्राम कंसोल को हर सेकंड अपडेट करे, और जब तक मैं इनपुट को संभालने की कोशिश नहीं करता तब तक यह ठीक काम कर रहा था। अब प्रोग्राम रुकता है क्योंकि यह उपयोगकर्ता के इनपुट का इंतजार करता है। मैं यह कैसे कर सकता हूँ?

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_tclock()

अब मैं एक cप्रोग्रामर नहीं हूं , इसलिए मुझे नहीं पता कि यह cकोड "सुरुचिपूर्ण" है (यह शायद नहीं है), लेकिन इसने मेरी मशीन (विंडोज, विजुअल स्टूडियो) पर काम किया।

#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;
}

ध्यान देने योग्य बातें:

  • इसे प्राप्त करने के लिए शायद अन्य (बेहतर) तरीके हैं: अभी के लिए, जब मैं रिफ्रेश (क्लियरस्क्रीन) करता हूं, तो स्क्रीन थोड़ा "फ़्लिकर" करता है।
  • विंडोज़ पर, OS, ऐप्स को भेजे जाने वाले चरित्र की दोहराने की दर को "गति" देगा, इसलिए जब आप dउदाहरण के लिए हिट करते हैं, तो प्रोग्राम दिखाएगा कि आप मार रहे हैं d, फिर यह दिखाएगा कि आप कोई कुंजी नहीं मार रहे हैं, तब यह दिखाएगा कि आप dफिर से मार रहे हैं , जब तक आप कुंजी जारी नहीं करते।
  • अपने स्वयं के कार्यान्वयन की तरह, उपयोग किए गए कार्यों की प्रकृति के कारण यह पोर्टेबल नहीं है।
AliTeo Dec 16 2020 at 05:28

हालाँकि मुझे गैर-पोर्टेबल कोड का उपयोग करना था, लेकिन मुझे इसे तृतीय-पक्ष लाइब्रेरी की आवश्यकता के बिना काम करने के लिए मिला। यह भी पता चलता है _kbhit () फ़ंक्शन देरी बफर करता है ताकि आपको पूर्ण स्ट्रिंग में प्रवेश करने के लिए 1 सेकंड की प्रतीक्षा करने की आवश्यकता न हो। हालाँकि लिखित स्ट्रिंग को काट दिया जा रहा था यदि यह एक सेकंड में नहीं लिखा गया है। इसलिए मैंने इसे ShowConsole () फ़ंक्शन में भी दिखाया।

नोट: यह एक नॉन-सीबीएस, गैर-पोर्टेबल कोड है। मेरे ओएस (विंडोज) में काम करता है।

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.
}