我为康威的生命游戏模拟编写了这个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
答案 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()