Converting Recurision to Iteration - c

How would I convert this code to use while loops instead of recursion?
void game(void)
{
int answer;
printf("%s", Questions[level]);
scanf("%d", &answer);
if (level < 8) {
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
game();
}
else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
game();
}
}
else {
printf("Great Job, You Won!");
}
}
I tried starting with a while loop and trying to work backwards, but I got lost in the sea of code

There is a couple of "strange" things in your program that I'll get back to later but to start with let's focus on the question:
How would I convert this code to use while loops instead of recursion?
There are many ways to do that...
The current recursive calls, i.e. game();, takes no arguments, nor does it use a return value. So a very simple way to get rid of recursion and keeping the exact same functionality could be:
Add a while(1) loop around all the existing code
Replace the current recursive calls with a continue; statement
Add a break; statement when the loop is to terminate
That would look like:
void game(void)
{
while(1) { // Add a while loop
int answer;
printf("%s", Questions[level]);
scanf("%d", &answer);
if (level < 8) {
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
// game();
continue; // Start a new round of the game
}
else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
//game();
continue; // Start a new round of the game
}
}
else {
printf("Great Job, You Won!");
break; // End the game by breaking out of the while loop
// This could also be a return; statement
}
}
}
The above solution preserves the structure of the original program. If we allow some (minor) restructuring, we can do a little better.
void game(void)
{
while(1) {
int answer;
printf("%s", Questions[level]);
scanf("%d", &answer);
// Check if the game has finished
if (level >= 8) {
printf("Great Job, You Won!");
return; // or break;
}
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
} else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
}
}
}
Instead of checking for "shall game continue" the above version checks for "has game finished" and - if so - it returns. By doing that we no longer need the explicit continue; statements.
Now getting back to the "strange" things in your program:
When a user wins the game (i.e. level reach 8), the code will still ask one more question and once the answer has been entered, the program finish. That is probably not intended...
Further, the only way to finish the game is to win the game (i.e. answer correct a number of times in a row). I would expect a way for the user to say "I give up"
Finally there is a serious problem with your code that may lead to errors like program crash or infinite loop. Always, always, always, check the return value of scanf !!! (see end-note)
Fixing those things and doing a little more restructuring could lead to a program like:
void game(void)
{
level = 0; // Assuming a new game always starts a level zero
while(1) {
int answer;
printf("%s", Questions[level]);
if (scanf("%d", &answer) != 1) {
// Wrong input or input error
// Add error handling... but for now, just terminate
exit(1);
}
// Let the user end the program with a negative input
if (answer < 0) {
printf("Sorry to see you leave before finishing the game. Bye.\n");
return 0;
}
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
// Check if the game has finished
if (level == 8) {
printf("Great Job, You Won!");
return;
}
} else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
}
}
}
End-note:
While it's true that the return value from scanf shall be checked, the better advice would be:
Never use scanf.
At the surface scanf looks like an easy way to get user input but the truth is that it has so many pitfalls that only real experts are able to use it (and they probably wont). The number of SO questions where (incorrect use of) scanf is the root cause of a problem is extreme. And they keep coming...
So forget that you ever heard about scanf. If you do like the features of scanf, you will (nearly) always do better by using fgets followed by sscanf.

It is hard to call it recursion.
void game(void)
{
int answer;
while (level < 8)
{
printf("%s", Questions[level]);
if(scanf("%d", &answer) != 1){ /* handle error */}
if (is_right(level, answer))
{
printf("Good Job!\n");
level += 1;
}
else
{
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
}
}
printf("Great Job, You Won!");
}

Related

C program doesn't wait for user input with scanf()

I'm new to C and this is my TicTacToe for first C project. For that, I setup a simple process for user where to choose X or O. But it doesn't seem to work for reason. Here it continues to the if statements and goes into infinite loop cause it didn't wait for user input.
I've gone through similar forums about this exact question but I was unable to get an answer that fixed my problem. Also, feedbacks about the code are much appreciated because I do want to improve my code.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char checks_player;
int is_input_valid = 0;
while(is_input_valid == 0)
{
printf("What do you want to choose? (X/O) ");
scanf(" %c",checks_player);
if(checks_player == 'x')
{
checks_player = 'X';
is_input_valid = 1;
}
else if(checks_player == 'o')
{
checks_player = 'O';
is_input_valid=1;
}
else if((checks_player == 'O')|| (checks_player == 'X'))
{
is_input_valid = 1;
}
else
{
printf("Invalid Input!!\nTry Again.\n\n");
}
}
}
You need to pass a pointer to scanf. Instead of this:
scanf(" %c",checks_player);
Use this:
scanf(" %c", &checks_player);

Can't get while loop to work 2 times? (C)

So I'm trying to loop the name asking section as well as the age one, the age one worked fine but when I tried to do it with name one it doesn't work. What I'm just trying to achieve is that when you put a number in the name section or vice versa, you get an error message and it loops you back to the same question
#include <stdio.h>
int vek;
char name[20];
int result1;
int result2;
int main()
{
FindName();
void FindName() { // it wants me to put a ";" which doesn't make sense to me and doesn't work
printf("Napis svoje meno \n");
result2 = scanf("%s",&name);
while (gethar() != '\n');
if(result2 == 1){
printf("Ahoj %s \n",name);
break;
system("pause");
}
else {
printf("nepis sem cisla ty kokot \n");
}
findAge();
}
void findAge() {
printf("Napis svoj vek \n");
result1 = scanf("%d",&vek);
while (getchar() != '\n');
if(result1 == 1){
printf("%s si krasny %d rocny priklad downoveho syndromu \n ",&name,vek);
}
else {
printf("co si jebnuty \n");
findAge();
}
}
I've tried to just break the loop if it's the right answer but that wouldn't work either, I'm just a beginner
The while loop will run everything inside the body as long as the condition is true. You need to put the code that needs to be repeated in a block, between { and }. You've put a semicolon behind it. That means a null statement, or do nothing. That way the condition is checked until it is no longer true, but nothing else is done. For example:
int i=0;
while(i < 3) {
printf("%d\n", i);
i++;
}
That will print the numbers 0,1 and 2. And then it stops because the condition is no longer true.
You want the program to look like this. In pseudocode:
main:
call findName
call findAge
findName:
print "Something Eastern European asking for a name"
result = 0;
while result != 1:
result = read input
if result == 0
print "Try again"
And the same for findAge
Notice the functions never call themselves. They just run the loop until the input is valid.

return to the beginning of an if-statement in a loop

I'm trying to create a simple game where the user has to go through a maze. At the beginning of the maze, I give the user possible routes to take, and ask the user which route to take next. If the user enters a correct route, I take him to the next route. If the user enters a wrong route, I print an error message, followed by the prompt again, and read his input again.
I'm having trouble figuring out what to do after I print the error message. How do I go back to the beginning of the loop? I did some research and am starting to think that I should use a do-while loop instead, but given the iterations in between (repeating this step until the user finds the exit of the maze), I struggle to figure out exactly how to do that.
Here is my original if-else statement:
printf("Prompt for user input\n"); //step1
//user input
scanf("%s", &input); //step2
//check input
for (i = 0; i < 7; i++) {
if (strncmp(input, condition) == 0){//do something}
else{
printf("error\n");
//need to do steps 1 and 2 again
}
Thank you for your time, any help would be greatly appreciated!
From your question i could understand that you are prompting the user to enter value untill he gives correct answer or he completes the 7 chances.
You can use do while loop for the same:
int chanceCount = 0; //it will keep track of number of chances user gets
do {
printf("Prompt for user input\n");
//user input
scanf("%s", &input);
if (strncmp(input, condition) == 0)
{
//do something
break; /* come out of loop, as user gave correct answer*/
}
else
{
printf("error try again \n");
}
chanceCount ++;
}while(chanceCount != 7);
The simplest approach is to wrap it in another loop.
bool game_over = false;
do {
printf("Prompt for user input\n"); //step1
//user input
scanf("%s", &input); //step2
//check input
bool input_okay = true;
for (i = 0; i < 7; i++) {
if (strncmp(input, condition) == 0) {
//do something
}
else{
printf("error\n");
input_okay = game_over = false;
break;
}
if (!input_okay)
continue; // restart do while
//
} while(!game_over);
The flags (defined with the bool type from stdbool.h) are required to make sure the continue statement is executed in the correct scope (of the do ... while loop).
bool OK = false
while( ! OK ) {
printf("Prompt for user input\n"); //step1
//user input
scanf("%s", &input); //step2
//check input
for (i = 0; i < 7; i++) {
if (strncmp(input, condition) == 0)
{//do something}
OK = true
}
else
{
printf("error\n");
//need to do steps 1 and 2 again
OK = false;
}
}
}

File Handling and Strings(Log in system)

I am creating a log in system. Just the basic, username and pass.
=====Log in===
user: abcd
pass: ****
==============
max 4 alphanumeric characters.
struct account
{
user[5];
pass[5];
}s;
For example in my database.txt file I already have this.
abcd //user
1234 //pass
So in the main its like this:
main()
{
FILE *fp;
fp=fopen("account.txt","r");
char user[5],pass[5];
printf("enter user: ");
gets(user);
printf("enter pass: ");
pass[0] = getch();
printf("*"); //doing this for
pass[1] = getch(); //password security
printf("*"); //asterisk(*)
pass[2] = getch();
printf("*");
pass[3] = getch();
printf("*");
pass[4] = '0';
getch();
while(fread(&s,sizeof(s),1,fp)==1);
{
if(ferror(fp))
{
printf("error");
}
else if (strcmp(s.user,user) == 0 && strcmp(s.pass,pass) == 0)
{
printf("success!");
}
else
{
printf("invalid");
}
}
getch();
}
problem is it is not working. When I put the correct pass it will always say invalid. but when I use
gets(pass); rather than the pass[0]=getch(); it works perfect.
Is this the correct way of doing the password security and reading it?
First, this is not a particularly good idea, as it is extremely insecure. Several decades of lessons on how not to do this have been learned by the industry, and you are on track to re-learn those the painful way.
As to your specific problem, you are not null terminating the pass array before running a null-terminated string comparison on it.
Declare it with 5 elements, and set the fifth - pass[4] - to 0.

Letter guessing game weird output

So here is my code:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#define MAX_GUESSES 4
int PlayGame(char guess);
int WinOrLose(char userguess, char solution);
int main()
{
FILE* infile;
char correctlet;
int games,
igame,
result;
infile = fopen("inputLet.txt", "r");
printf ("Welcome to the letter guessing game!\n");
printf ("Your job is to guess a random letter.\n");
printf("You can guess each letter a maximum of 4 times,\n");
printf ("and you will get a hint after every guess.\n");
printf ("LET'S DO THIS!\n\n>");
printf ("\nHow many games would you like to play (1-3)?\n>");
scanf ("%d",&games);
for(igame=0;igame<games;igame++)
{
fscanf(infile," %c",&correctlet);
printf("This is game %d\n", igame+1);
result = PlayGame (correctlet);
if (result == 0)
{
printf ("\nCongratulations, you guessed the right letter!\n");
}
else
{
printf ("\nUnfortunately, you did not guess the right letter. Better luck next time!\n");
}
}
return 0;
}
int PlayGame(char solution)
{
int guessnumber,
result;
char userguess;
guessnumber = 0;
while(guessnumber < MAX_GUESSES)
{
printf("Please enter your guess\n>");
scanf("%c", &userguess);
if (sizeof userguess == 0)
{
continue;
}
else if (sizeof userguess >=1)
{
printf ("Your guess was %c\n",userguess);
result = WinOrLose (userguess, solution);
if (result == 0)
{
return 0;
break;
}
else if (result == 1)
{
if (solution < userguess)
{
printf("The correct letter comes before %c alphabetically\n", userguess);
}
else if (solution > userguess)
{
printf("The correct letter comes after %c alphabetically\n", userguess);
}
guessnumber ++;
}
}
}
}
int WinOrLose (char userguess, char solution)
{
if(solution==userguess)
{
return 0;
}
else if (solution != userguess)
{
return 1;
}
}
The output asks for the number of games, and then it outputs please enter your guess your guess was (blank) The correct letter comes after (blank) Please enter your guess and THEN it allows for user input. So why is it going through one iteration of PlayGame without asking for user input? I have tried everything I can think of and can't fix the problem. I am compiling on VC++ 2010, if that helps.
Thanks in advance!
The simple answer is to flush your buffers.
The stdin buffer, the buffer that takes instructions from the keyboard (or a pipe) and submits it to the program occasionally gets some characters "stuck" in it. Junk characters that never quite get submitted, extra returns, etc. that will cause scanf() to think it reached the proper end, but actually hasn't.
fflush(stdin);
The function fflush "flushes" a buffer. The effect of this is to consume data from a buffer until the data received is the character '\0' (NULL). This means that it's reached the last of the data that is currently in the buffer.
Calling this before calling scanf() means that when scanf() is called, you reasonably know that the program will block on scanf() until you've submitted, and not just consume some junk from the buffer.

Resources