Ana döngüyü durdurmadan C'deki girişi nasıl idare edebilirim?

Dec 16 2020

C programımın konsolu her saniye güncellemesini istiyorum ve girişi işlemeye çalışana kadar iyi çalışıyordu. Artık program kullanıcıdan bir girdi beklediği için durmaktadır. Bunu nasıl yapabilirim?

while(true) {
    ShowConsole();  //Show
    Sleep(1000);        //Wait
    scanf("%s",&a)      //Handle Input  
    Update();
    ClearScreen();      //Clear
}

Yanıtlar

1 Vaillancourt Dec 17 2020 at 08:32

Bunu kendim halletmeye çalıştım.

Yalnızca soru metnine dayanarak, ne tür bir oyun yapmaya çalıştığınız çok net değil, bu yüzden , yılanın hareket edeceği, oyuncu ne yaparsa yapsın (veya yapmazsa) bir tür yılan oyunu yaklaşımını benimsedim. .

Kullandığım Sleepgiriş yoklama ve yeniden çizme hızını hızlandırmak amacıyla ve _kbhit()karşı belki bir karakteri okumak ve clock_t/ clock()saniyede bir kez oyuna güncellemek için.

Şimdi bir cprogramcı değilim , bu yüzden bu ckodun "zarif" olup olmadığını bilmiyorum (muhtemelen değil), ama makinemde çalıştı (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;
}

Dikkat edilmesi gereken birkaç nokta:

  • muhtemelen bunu başarmanın başka (daha iyi) yolları vardır: şimdilik, (ClearScreen) yenilediğimde, ekran biraz "titriyor".
  • Windows'ta, işletim sistemi uygulamalara gönderdiği karakterin tekrar oranını "hızlandıracak", böylece dörneğin vurduğunuzda program vurduğunuzu gösterecek ve dardından hiçbir tuşa basmadığınızı gösterecektir. sonra dtuşu bırakana kadar tekrar bastığınızı gösterecektir .
  • kendi uygulamanız gibi, kullanılan işlevlerin doğası gereği taşınabilir değildir.
AliTeo Dec 16 2020 at 05:28

Taşınabilir olmayan kod kullanmam gerekmesine rağmen, üçüncü taraf bir kitaplığa ihtiyaç duymadan çalışmasını sağladım. Ayrıca _kbhit () işlevi arabelleği geciktirir, böylece tam dizeyi girmek için 1 saniye beklemenize gerek kalmaz. Ancak yazılı dize bir saniyede yazılmazsa kesiliyordu. Bu yüzden ShowConsole () fonksiyonunda da gösterdim.

Not: Bu standart olmayan, taşınabilir olmayan bir koddur. İşletim sistemimde çalışıyor (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 () İşlevinde:

ShowConsole(){
    .
    .
    .
    printf("%s", moveInput); // At the end of showing the graphics, also show the input that is being written.
}