2017-01-15 3 views
-1

Ich schrieb diesen C-Code für Conways Game of Life Simulation. Es funktioniert perfekt, außer wenn der Benutzer ein Zeichen als Eingabe eingibt. Das habe ich bisher gemacht. Wenn ich irgendein Zeichen z. * oder/Wenn das Programm nach Eingabe fragt, bleibt das Programm stehen oder geht in eine Endlosschleife. Kann mir jemand dabei helfen? Ich habe den Code auf alle möglichen Arten optimiert, um den Fehler zu entfernen, aber alles umsonst.Warum friert meine Eingabe ein?

#include "stdio.h" //for all basic functions 
#include "stdlib.h"//for exit function 
#include "time.h" //for random seed 
#include "windows.h" //for Sleep function 
#include "conio.h" //for _kbhit function 
#define scanf_s scanf //typing scanf_s is tedious compared to typing scanf 

void neighbour_manager();//custom function to calculate neighbours and make a cell alive or dead accordingly 
void generation_printer();//custom function to print the generations after selecting seed type 

//initializing all variables 
int generation; 
char fill_char; 
char array[35][85]; 
char array1[35][85]; 
char live = '+';//using + sign for live cells 
char dead = ' ';//using blank spaces for dead cells 
char n; 
char random_seed[3]={' ','+','\0'};//for random seed i.e. (case:12) 
//SEEDS 
char block[2][2] = {{'+','+'}, {'+','+'}}; 
char boat[3][3] = {{'+','+',' '}, {'+',' ','+'}, {' ','+',' '}}; 
char loaf[4][4] = {{' ','+','+',' '},{'+', ' ', ' ', '+'},{' ', '+', ' ', '+'},{' ', ' ', '+', ' '}}; 
char beehive[3][4] = {{' ','+','+',' '},{'+', ' ', ' ', '+'},{' ', '+', '+', ' '}}; 
char blinker[1][3] = {{'+', '+','+'}}; 
char beacon[4][4] = {{'+','+',' ',' '},{'+',' ',' ',' '},{' ',' ',' ','+'},{' ',' ','+','+'}}; 
char toad[2][4] = {{' ','+','+','+'},{'+','+','+',' '}}; 
char pulsar[15][15] = { 
          {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '}, 
          {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '}, 
          {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '}, 
          {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, 
          {'+','+','+',' ',' ','+','+',' ','+','+',' ',' ','+','+','+'}, 
          {' ',' ','+',' ','+',' ','+',' ','+',' ','+',' ','+',' ',' '}, 
          {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '}, 
          {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, 
          {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '}, 
          {' ',' ','+',' ','+',' ','+',' ','+',' ','+',' ','+',' ',' '}, 
          {'+','+','+',' ',' ','+','+',' ','+','+',' ',' ','+','+','+'}, 
          {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, 
          {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '}, 
          {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '}, 
          {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '} 
          }; 
char glider[3][3] = {{' ','+',' '},{' ',' ','+'},{'+','+','+'}}; 
char spaceship[4][5] = {{'+',' ',' ','+',' '},{' ',' ',' ',' ','+'},{'+',' ',' ',' ','+'},{' ','+','+','+','+',}}; 
char gosper_glider_gun[15][38] = { 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '+', '+', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ' }, 
            { ' ', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '+', ' ', '+', ' ', ' ', '+', ' ', ' ', ' ', '+', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 
            { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } 
           }; 


//main function starts here 
int main(void) 
{int i = 0, j = 0;     //initializing some more variables 
    int a = 0, b = 0, seed_type = 0; 
    int choice_after_execution=0; 
    system("title CONWAY'S GAME OF LIFE");//to change the console title 
    _flushall();//to remove garbage values 
    printf("\t\t\t\t\tWelcome to Conway's Game of Life\n");//welcome note 
    Sleep(2500);//for dramatic purposes 
    system("cls"); 
    printf("Please make sure the console is maximized for optimal simulation.");//whole grid is not visible if console is not maximized 
    Sleep(2000);//to create a pause to maximize screen before proceeding 

    start:       //jump point in case user decides to restart the game 
    for (i = 0; i < 35; i++) {  //emptying the array to avoid double printing of patterns in the same grid 
     for (j = 0; j < 85; j++) { 
      array[i][j]=dead; 
     } 
    } 
    system("cls"); 

    printf("Select the seed type\nSTILL LIFE PATTERNS\nEnter 1 for Block \nEnter 2 for Loaf \nEnter 3 for Boat\nEnter 4 for Beehive\n\nOSCILLATORS\nEnter 5 for Blinker\nEnter 6 for Beacon\nEnter 7 for Toad\nEnter 8 for Pulsar\n\nGLIDERS AND SPACSHIPS\nEnter 9 for Glider\nEnter 10 for Spaceship\n\nGOSPER GLIDER GUN\nEnter 11 for Gosper Glider Gun\n\nRANDOM\nEnter 12 for Random\n\nYour choice: "); 
    retake_seed_type: //jump point for invalid choice 

      scanf("%d", &seed_type); 

    srand(time(NULL)); //random seed generator 
    a = 1 + rand() % 35; //randomizing the row for first generation 
    b = 1 + rand() % 85; //randomizing the column for first generation 


    switch (seed_type)//switch case for different seed types 
    { 
    case 1: //for block 
     for (i = a; i < a + 2; i++){ 
      for (j = b; j < b + 2; j++){ 

       array[i%35][j%85] = block[i - a][j - b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 2://for loaf 
     for (i = a; i <a + 4; i++){ 
      for (j = b; j <b + 4; j++){ 
       array[i%35][j%85] = loaf[i - a][j - b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 3://for boat 
     for (i = a; i <a + 3; i++){ 
      for (j = b; j <b + 3; j++){ 

       array[i%35][j%85] = boat[i - a][j - b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 4://beehive 
     for(i = a; i <a + 3; i++){ 
      for(j = b; j <b + 4; j++){ 
      array[i%35][j%85] = beehive[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 5://blinker 
     for(i=a;i<a+1;i++){ 
      for(j=b;j<b+3;j++){ 
      array[i%35][j%85] = blinker[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 6://beacon 
     for(i=a;i<a+4;i++){ 
      for(j=b;j<b+4;j++){ 
      array[i%35][j%85] = beacon[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 7://Toad 
     for(i=a;i<a+2;i++){ 
      for(j=b;j<b+4;j++){ 
      array[i%35][j%85] = toad[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
    case 8://Pulsar 
     for(i=a;i<a+15;i++){ 
      for(j=b;j<b+15;j++){ 
      array[i%35][j%85] = pulsar[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
     case 9://glider 
     for(i=a;i<a+3;i++){ 
      for(j=b;j<b+3;j++){ 
      array[i%35][j%85] = glider[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
     case 10://spaceship 
     for(i=a;i<a+4;i++){ 
      for(j=b;j<b+5;j++){ 
      array[i%35][j%85] = spaceship[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
     case 11://gosper glider gun 
     for(i=a;i<a+15;i++){ 
      for(j=b;j<b+38;j++){ 
      array[i%35][j%85] = gosper_glider_gun[i-a][j-b];//i%35 and j%85 to facilitate wrap around 
      } 
     } 
     break; 
     case 12://random 
      a=0; 
      b=0; 
      for(i=a;i<35;i++){ 
       for(j=b;j<85;j++){ 
       array[i][j] = random_seed[1+rand()%2]; 
      } 
     } 
     break; 

    default://default case asks for input again 
      printf("Enter a valid choice i.e. from 1 to 12: "); 
      goto retake_seed_type;//go-to statement to take seed_type input again 
    } 
    printf("\nEnter the number of generations(-1 for infinite): "); 
    scanf_s("%d", &generation); 
if(generation>0){//different cases for generation input 
    for (i = 1; i <= generation; i++){ 
     system("cls"); 
     neighbour_manager(); 
     generation_printer(); 
     printf("GENERATION NUMBER: %d\n", i);//to know how many generations have been printed 
     printf("Press any key to stop simulation.\n"); 
     if(_kbhit())//if user presses a key to stop simulation 
      { 
      printf("Generation Interrupted."); 
     break; 
     } 
     if(i==generation)//if user does not interrupt generations 
     { 
      Sleep(200);//dramatic purposes 
      printf("Generation completed successfully."); 
     } 

     Sleep(700);//according to the instructions 
    } 
} 
    if (generation <0) 
    {int z=0; 
     while (!_kbhit())//to make sure loop continues printing unless user press a key on keyboard 
      { 
      system("cls"); 
      neighbour_manager(); 
      generation_printer(); 
      z++;//generation counter 
      printf("GENERATION NUMBER: %d\n", z);//to know how many generations have been printed 
      printf("Press any key to stop simulation.\n"); 
      Sleep(700);//according to the instructions 
      if(_kbhit())//if user presses a key to stop simulation 
      { 
      printf("Generation Interrupted."); 
     break; 
     } 

      } 

    } 
    if(generation==0) 
     { system("cls"); 
      printf("No generations printed."); 
     } 

    printf("\nPress 1 to Restart.\nPress 2 to Exit.\nYour Choice: ");//exit message 
    after_generation_valid_choice://jump point in case of wrong input choice 
    scanf("%d",&choice_after_execution); 

    if(choice_after_execution==1) 
     goto start;//if user wants to start simulation again then go back to start 

    if(choice_after_execution==2)//if user wants to exit 
     { 
      printf("Thank you for using this program."); 
      Sleep(2000);//for dramatic purposes 
      goto exit;//if user decides to exit the program then skip system pause and just exit 
     } 
    else 
    { 
     printf("Enter a valid choice: ");//if invalid choice is entered ask again 
     goto after_generation_valid_choice; 
    } 

    exit://jump point in case user wants to exit 
    exit(0); 
}//main end 

void neighbour_manager(){      //custom function to decide whether cells should be alive or dead 
    int i, j;         //corresponding to the number of neighbours alive or dead 
    int neighbour; 
    for (i = 0; i < 35; i++){ 
     for (j = 0; j < 85; j++){ 

      neighbour = 0; 
      if (array[i - 1 < 0 ? 34 : i - 1][j - 1 < 0 ? 84 : j - 1] == live) neighbour = neighbour + 1;//modifications in row and 
      if (array[i - 1 < 0 ? 34 : i - 1][j] == live) neighbour = neighbour + 1;     //column numbers to ensure 
      if (array[i - 1 < 0 ? 34 : i - 1][(j + 1) % 85] == live) neighbour = neighbour + 1;   //that the patterns wrap 
      if (array[i][j - 1 < 0 ? 84 : j - 1] == live)  neighbour = neighbour + 1;     //around 
      if (array[i][(j + 1) % 85] == live)  neighbour = neighbour + 1; 
      if (array[(i + 1) % 35][j - 1 < 0 ? 84 : j - 1] == live) neighbour = neighbour + 1; 
      if (array[(i + 1) % 35][j] == live) neighbour = neighbour + 1; 
      if (array[(i + 1) % 35][(j + 1) % 85] == live) neighbour = neighbour + 1; 


      if(neighbour == 3)      //game rules that decide whether a cell would be alive or 
      {           //not in the next generation 
       array1[i][j] = live; 
      } 
      else if (neighbour < 2 || neighbour > 3) 
      { 
       array1[i][j] = dead; 
      } 
      else 
      { 
       array1[i][j] = array[i][j]; 
      } 
     } 
    } 
    for(i=0; i<35; i++){       //replace array1 with array 
     for(j=0; j<85; j++){ 
      array[i][j] = array1[i][j]; 
      array1[i][j] = ' ';     // now empty array1 
     } 
    } 
    return; 
} 


int ran_out_of_variable_names1 = 35; 
int ran_out_of_variable_names2 = 85; 

void generation_printer() //custom function that prints both border and the array(with patterns) 
{ 
    int i,j; 
    // Top border 
    for (i = 0; i < ran_out_of_variable_names2 + 2; i++) { 
     printf("*"); 
    } 
    printf("\n"); 
    for (i = 0; i < ran_out_of_variable_names1; i++) { 
     // Star to the beginning of the line 
     printf("*"); 
     // Contents of the line 
     for (j = 0; j < ran_out_of_variable_names2; j++) { 
      printf("%c", array[i][j]); 
     } 
     // Star at the end of the line 
     printf("*\n"); 
    } 
    // Bottom border 
    for (i = 0; i < ran_out_of_variable_names2+ 2; i++) { 
     printf("*"); 
    } 
    printf("\n"); 
} 
//END OF CODE 
+0

'_kbhit' und' goto' nicht geht ein Problem sein. – killerzula

+1

Wenn das einzige Problem darin besteht, ein Zeichen als Eingabe einzugeben, könnten Sie versuchen, Ihre Frage auf genau das zu beschränken und nicht Ihren gesamten Code zu veröffentlichen. Das erste, was jemand tun muss, um Ihre Frage zu beantworten, ist zu finden, wo unter all dem Code die Eingabe akzeptiert wird, und auch herauszufinden, welche Eingabe akzeptiert werden soll - Sie haben uns nicht mitgeteilt, wie eine gültige Eingabe aussieht. Was kann der Benutzer eingeben, wenn kein "Charakter"? Alle Eingaben sind Zeichen. – Clifford

+0

'scanf' löscht die Eingabe nicht, wenn sie nicht konvertiert werden kann, der Eingang bleibt im Puffer. Das musst du selbst machen. Überprüfen Sie immer den Rückgabewert von 'scanf' (Anzahl der konvertierten Artikel). Es ist besser, 'fgets' und dann' sscanf' zu verwenden. Wenn es fehlschlägt, können Sie diese Zeichenfolge ausgeben und eine andere eingeben. –

Antwort

1

Wenn der Eingangspuffer nicht-stellige Zeichen enthält und Sie scanf() rith %d Eingang zu lesen, wird der Eingang fehlschlagen und die Nicht-stellige Zeichen bleiben gepuffert, nur für die nachfolgenden scanf() scheitern, weil nichts geändert.

Lösungen sind Legion; hier ist ein:

while(scanf("%d",&choice_after_execution) != 1) 
{ 
    while(getchar() != '\n') ; // read buffer until end of line 
} 

Eine Alternative ist eine ganze Reihe von Eingang mit fgets() und analysiert es mit sscanf() zu lesen.

Ich empfehle, dass aber Sie es tun, können Sie die Lösung in einer Funktion zur Wiederverwendung wickeln (so dass Sie nur das Problem einmal lösen müssen):

int getDecimalInput() 
{ 
    int input = 0 ; 
    while(scanf("%d",&input) != 1) 
    { 
     while(getchar() != '\n') ; // read buffer until end of line 
    } 

    return input ; 
} 
Verwandte Themen