为什么我的输入会冻结?

时间:2017-01-15 17:56:08

标签: c

我为康威的生命游戏模拟编写了这个C代码。除了当用户输入一个字符作为输入时,它工作得很好。这是我到目前为止所做的。如果我输入任何字符,例如*或/当程序要求输入时,程序冻结或进入无限循环。有人可以帮我解决这个问题。我已经用一切可能的方法调整了代码来删除bug,但都是徒劳的。

#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

1 个答案:

答案 0 :(得分:1)

如果输入缓冲区包含非数字字符并且您使用LinearLaout rith scanf()来读取输入,则输入将失败并且非数字字符将保持缓冲,仅用于后续{{ 1}}因为没有任何改变而失败。

解决方案很多;这是一个:

%d

另一种方法是使用scanf()读取整行输入,然后使用while( scanf("%d",&choice_after_execution) != 1 ) { while( getchar() != '\n' ) ; // read buffer until end of line } 对其进行解析。

我强烈建议你这样做,你将解决方案包装在一个函数中以便重用(所以你只需要解决一次问题):

fgets()