Loop Issue

This is a discussion on Loop Issue within the C Programming forums, part of the General Programming Boards category; Hello, I am making a program where a computer and player take turns rolling dice. There seems to be an ...

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    28

    Loop Issue

    Hello,

    I am making a program where a computer and player take turns rolling dice.

    There seems to be an issue somewhere in my loop where when the player selects from the possible dice choices, it rolls for the computer and does not select the choice and it immediately becomes the player's turn again.

    I am trying to get it to where when the computer rolls the dice, it should display the list of possible values, and ask the user to hit the enter key in order for the computer to choose which value to select using the following command:
    Code:
    while ( getchar() != '\n' ) ;
    I've tried it a hundred times and no matter where I put the command it still skips the computer's turn.

    Below is my code:

    Code:
    while (compscore < 99 && playerscore < 99){
    
            printf("You have rolled the following pair of dice:\n");
            a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            b =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            multiply = a * b;
            d1d2 = a*10 + b;
            d2d1 = b*10 + a;
    
            dice_roll(a);
            dice_roll(b);
            printf("You have the following choices to choose from:\n");
            printf("%i/%i/%i\n", multiply,d1d2,d2d1);
            scanf("%i", &playerscore);
            printf("Player Score : %i\n", playerscore);
            playerscore = 0 + playerscore;
    
    
            printf("The computer rolled the following pair of dice:\n");
            a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            b =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            multiply = a * b;
            d1d2 = a*10 + b;
            d2d1 = b*10 + a;
            dice_roll(a);
            dice_roll(b);
            printf("The following choices to choose from are:\n");
            printf("%i/%i/%i\n", multiply,d1d2,d2d1);
            if (multiply < d1d2 && d1d2 < d2d1)
            compscore = multiply;
            if (d1d2 < multiply && multiply < d2d1)
            compscore = d1d2;
            if (d2d1 < multiply && multiply < d1d2)
            compscore = d2d1;
            printf("Press enter for the computer to choose a value.\n");
            compscore = 0 + compscore;
    Thank you for your time.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,427
    It's hard to say for sure, without a complete program that I can compile and run myself, but here's my guess:

    You're mixing input types, specifically formatted input (scanf) and character-based input (getchar). When you type a number, you hit enter. That puts a new line in the buffer. The scanf call reads the number, but leaves the new line. Then your getchar loop comes along, and the first char it grabs is the leftover newline, so the getchar loop ends right away, and appears to have not worked. I recommend using fgets to read an entire line of data at once, then using strtol or sscanf to parse out the number. If you don't want to do that, at least flush the input buffer immediately after you call scanf, to discard everything up to and including the new line. See here: FAQ > Flush the input buffer - Cprogramming.com. Just don't use fflush(stdin)! Oh, and your "wait for enter" loop should probably handle EOF too. That "wait for enter" loop is just like flushing the input buffer.

    Also:
    Code:
    a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
    That line and all the other similar ones almost certainly do not do what you think. Heck, I'm not sure what you think they do, but they're wrong. Perhaps if you can describe what you are trying to do, we can help. The "%i" seems to imply printf or scanf, but I'm not sure how you intend that to fit into that statement.

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,675
    I don't get why you are doing this
    Code:
    playerscore = 0 + playerscore;
    You do it with the other variable too
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  4. #4
    Registered User
    Join Date
    Jan 2013
    Posts
    28
    Quote Originally Posted by std10093 View Post
    I don't get why you are doing this
    Code:
    playerscore = 0 + playerscore;
    You do it with the other variable too
    I used it to keep a running total of the score for both players. It doesn't work now, and I will fix it soon. Another thing I have to fix after my loop issue.

  5. #5
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,675
    I did not understand the answer. My point is, that if you add zero to a number, then you do nothing. Of course this is not an error, but I do not see the point of that to be there.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  6. #6
    Registered User
    Join Date
    Jan 2013
    Posts
    28
    Quote Originally Posted by anduril462 View Post
    It's hard to say for sure, without a complete program that I can compile and run myself, but here's my guess:

    You're mixing input types, specifically formatted input (scanf) and character-based input (getchar). When you type a number, you hit enter. That puts a new line in the buffer. The scanf call reads the number, but leaves the new line. Then your getchar loop comes along, and the first char it grabs is the leftover newline, so the getchar loop ends right away, and appears to have not worked. I recommend using fgets to read an entire line of data at once, then using strtol or sscanf to parse out the number. If you don't want to do that, at least flush the input buffer immediately after you call scanf, to discard everything up to and including the new line. See here: FAQ > Flush the input buffer - Cprogramming.com. Just don't use fflush(stdin)! Oh, and your "wait for enter" loop should probably handle EOF too. That "wait for enter" loop is just like flushing the input buffer.

    Also:
    Code:
    a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
    That line and all the other similar ones almost certainly do not do what you think. Heck, I'm not sure what you think they do, but they're wrong. Perhaps if you can describe what you are trying to do, we can help. The "%i" seems to imply printf or scanf, but I'm not sure how you intend that to fit into that statement.
    Thank you for the reply. I guess it is hard without the complete program to speculate. In my class we have not learned fgets or strtol so I will have to find another way. The
    Code:
    a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
    is suppose to choose random dice each time for the player and computer. My complete program is:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define LOSS 99
    #define MAX_VAL 6
    #define MIN_VAL 1
    
    int dice_roll(int x);
    
    
    int main
    (void)
    {
        srand(time(NULL));
    
        printf("This game is called Dice 99 and the object of the game is to not go over 99.\n");
        printf("Players will roll two dice and choose one out of three ways to total their\n");
        printf("score. A player may multiply the two dice or use the numbers they roll as\n");
        printf("digits for their score. For example, if a player rolls 3 5, then they can\n");
        printf("choose between 15, 35, and 53.If a player's score is greater than the other's\n");
        printf("score, then they can choose to roll or not.\n");
    
        int a,b;
        int multiply,d1d2,d2d1;
        int compscore = 0,playerscore = 0;
        int decide;
        char answer;
    
    
    
    
    
        decide = rand() % (2) + 1;
        if (decide == 1)
        printf("Player goes first!\n");
        else
        printf("Computer goes first!\n");
    
    
    
        while (compscore < 99 && playerscore < 99){
    
            printf("You have rolled the following pair of dice:\n");
            a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            b =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            multiply = a * b;
            d1d2 = a*10 + b;
            d2d1 = b*10 + a;
    
            dice_roll(a);
            dice_roll(b);
            printf("You have the following choices to choose from:\n");
            printf("%i/%i/%i\n", multiply,d1d2,d2d1);
            scanf("%i", &playerscore);
            printf("Player Score : %i\n", playerscore);
            playerscore = 0 + playerscore;
    
    
            printf("The computer rolled the following pair of dice:\n");
            a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            b =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
            multiply = a * b;
            d1d2 = a*10 + b;
            d2d1 = b*10 + a;
            dice_roll(a);
            dice_roll(b);
            printf("The following choices to choose from are:\n");
            printf("%i/%i/%i\n", multiply,d1d2,d2d1);
            if (multiply < d1d2 && d1d2 < d2d1)
            compscore = multiply;
            if (d1d2 < multiply && multiply < d2d1)
            compscore = d1d2;
            if (d2d1 < multiply && multiply < d1d2)
            compscore = d2d1;
            printf("Press enter for the computer to choose a value.\n");
            compscore = 0 + compscore;
    
    
            if (playerscore == 99 || compscore > 99){
            printf("Player Wins!");
            }
            else if (compscore == 99 || playerscore > 99){
            printf("Computer Wins!");
            }
    
    
    
          }
    
          }
    
    
    
    
    
    int dice_roll(int x)
    {
        if (x==1){
        printf("+-------+\n");
        printf("|       |\n");
        printf("|   @   |\n");
        printf("|       |\n");
        printf("+-------+\n");}
    
        if (x==2){
        printf("+-------+\n");
        printf("|      @|\n");
        printf("|       |\n");
        printf("| @     |\n");
        printf("+-------+\n");}
    
        if (x==3){
        printf("+-------+\n");
        printf("|      @|\n");
        printf("|    @  |\n");
        printf("| @     |\n");
        printf("+-------+\n");}
    
        if (x==4){
        printf("+-------+\n");
        printf("|@     @|\n");
        printf("|       |\n");
        printf("|@     @|\n");
        printf("+-------+\n");}
    
        if (x==5){
        printf("+-------+\n");
        printf("|@     @|\n");
        printf("|   @   |\n");
        printf("|@     @|\n");
        printf("+-------+\n");}
    
        if (x==6){
        printf("+-------+\n");
        printf("|@     @|\n");
        printf("|@     @|\n");
        printf("|@     @|\n");
        printf("+-------+\n");}
    
    }

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,427
    Turn your compiler warnings all the way up:
    Code:
    $ make dice
    gcc -Wall -Wunreachable-code -ggdb3 -std=c99 -pedantic  -lm -lpthread  dice.c   -o dice
    dice.c: In function ‘main’:
    dice.c:43: warning: left-hand operand of comma expression has no effect
    dice.c:44: warning: left-hand operand of comma expression has no effect
    dice.c:59: warning: left-hand operand of comma expression has no effect
    dice.c:60: warning: left-hand operand of comma expression has no effect
    dice.c:26: warning: unused variable ‘answer’
    dice.c: In function ‘dice_roll’:
    dice.c:138: warning: control reaches end of non-void function
    Lines 43, 44, 59 and 60: That has to do with the ("%i", rand()...) lines, see below.
    Line 26: remove the extraneous variable.
    Line 138 (and 9): You declare dice_roll to return an integer, but you never return anything, nor do you attempt to use the return value anywhere. Simply declare it to return void: void dice_roll(int x). Make sure you change the prototype and the definition.

    Quote Originally Posted by M_A_T_T View Post
    In my class we have not learned fgets or strtol so I will have to find another way.
    That's fine, continue with scanf, however, immediately after you call it, flush the input buffer, as shown in the link I provided in my post #2 above. I suggest putting that code in a function so you can reuse it. Then, when you want to wait for the user to press enter, simply call the flush_input() function and you'll be all set.

    Quote Originally Posted by M_A_T_T View Post
    Code:
    a =("%i ", rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL);
    is suppose to choose random dice each time for the player and computer.
    And it does. I guess I just don't understand why there is a "%i" in there, I thought you were trying to call printf or something. If not, that "%i" is totally useless, only the value of the right-most part of a comma expression is assigned to a. Since the left part doesn't even do anything (it's equivalent to something like x; which has no effect), it's totally ignored (hence the warnings above), so you can drop it. You just need
    Code:
    a = rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL;
    Similarly, what std10093 was saying is that
    Code:
    compscore = 0 + compscore;
    is completely useless. It does not change the value of compscore, or have any other side effect, so you can simply remove all such lines.

  8. #8
    Registered User
    Join Date
    Jan 2013
    Posts
    28
    Quote Originally Posted by anduril462 View Post
    Turn your compiler warnings all the way up:
    Code:
    $ make dice
    gcc -Wall -Wunreachable-code -ggdb3 -std=c99 -pedantic  -lm -lpthread  dice.c   -o dice
    dice.c: In function ‘main’:
    dice.c:43: warning: left-hand operand of comma expression has no effect
    dice.c:44: warning: left-hand operand of comma expression has no effect
    dice.c:59: warning: left-hand operand of comma expression has no effect
    dice.c:60: warning: left-hand operand of comma expression has no effect
    dice.c:26: warning: unused variable ‘answer’
    dice.c: In function ‘dice_roll’:
    dice.c:138: warning: control reaches end of non-void function
    Lines 43, 44, 59 and 60: That has to do with the ("%i", rand()...) lines, see below.
    Line 26: remove the extraneous variable.
    Line 138 (and 9): You declare dice_roll to return an integer, but you never return anything, nor do you attempt to use the return value anywhere. Simply declare it to return void: void dice_roll(int x). Make sure you change the prototype and the definition.


    That's fine, continue with scanf, however, immediately after you call it, flush the input buffer, as shown in the link I provided in my post #2 above. I suggest putting that code in a function so you can reuse it. Then, when you want to wait for the user to press enter, simply call the flush_input() function and you'll be all set.


    And it does. I guess I just don't understand why there is a "%i" in there, I thought you were trying to call printf or something. If not, that "%i" is totally useless, only the value of the right-most part of a comma expression is assigned to a. Since the left part doesn't even do anything (it's equivalent to something like x; which has no effect), it's totally ignored (hence the warnings above), so you can drop it. You just need
    Code:
    a = rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL;
    Similarly, what std10093 was saying is that
    Code:
    compscore = 0 + compscore;
    is completely useless. It does not change the value of compscore, or have any other side effect, so you can simply remove all such lines.
    Thanks for all the help. I've cleared up all the warning messages which is great and I read the article you posted but I am having a difficult time understanding it. I ran the program and seen what it does, but this line confuses me:
    Code:
      if (fgets(buf, sizeof(buf), stdin))   {     printf ("You entered: %s", buf);   }
    I don't understand what the if statement is exactly saying.

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,427
    Read the documentation for fgets: fgets(3): input of char/strings - Linux man page. It would help you immensely if you learned where to find the documentation for all the standard C functions.

    fgets returns a pointer to buf on success, or NULL on error. NULL has a numeric value of 0*. In C, zero is considered false, and anything non-zero is considered true. Thus, the expression says "if fgets succeeded, print "you entered ...". It could be written
    Code:
    if (fgets(buf, sizeof(buf), stdin) != NULL) {
        printf("You entered: %s", buf);
    }
    * At least, as far as the compiler/programmer is concerned. The actual, physical memory address 0 may or may not be a valid address, and may or may not be what the NULL constant maps to when the final executable is built, but that is abstracted away from the programmer. When you are writing your program, you always treat NULL as zero. The compiler will handle any conversion to a different value for whatever platform you are developing on.

  10. #10
    Registered User
    Join Date
    Jan 2013
    Posts
    28
    Quote Originally Posted by anduril462 View Post
    Read the documentation for fgets: fgets(3): input of char/strings - Linux man page. It would help you immensely if you learned where to find the documentation for all the standard C functions.

    fgets returns a pointer to buf on success, or NULL on error. NULL has a numeric value of 0*. In C, zero is considered false, and anything non-zero is considered true. Thus, the expression says "if fgets succeeded, print "you entered ...". It could be written
    Code:
    if (fgets(buf, sizeof(buf), stdin) != NULL) {
        printf("You entered: %s", buf);
    }
    * At least, as far as the compiler/programmer is concerned. The actual, physical memory address 0 may or may not be a valid address, and may or may not be what the NULL constant maps to when the final executable is built, but that is abstracted away from the programmer. When you are writing your program, you always treat NULL as zero. The compiler will handle any conversion to a different value for whatever platform you are developing on.
    Okay so in the context of my problem, what I should do is create a function that flushes input. Lets call it flush_input. Should I put this after my instructions that display the choices like so?
    Code:
    printf("The following choices to choose from are:\n");
    printf("%i/%i/%i\n", multiply,d1d2,d2d1);
    flush_input();
    And then should my function be something along the lines of..

    Code:
    void flush_input (argument?){
    if (fgets(choice, sizeof(buf), stdin)) 
      printf ("You entered: %s", choice);   }
    Where choice is where the computer selected one of the three scores.

  11. #11
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,427
    Read that "input flushing" tutorial more carefully next time:
    Code:
    puts("Flushing input");
    while ((ch = getchar()) != '\n' && ch != EOF);
    That while loop is the input flushing part. The other part is just getting a string from the user. That one-line while loop is your flush_input() function. Of course, you need to be sure to declare ch (as an int!) in your function too: int ch;

    flush_input needs no argument, nor does it return anything. The prototype/declaration should be:
    Code:
    void flush_input(void)
    You call your flush_input() function in two places
    1. Right after you call scanf, to get rid of any extra stuff in the input buffer, like the new line from when you pressed "enter" after typing in a number.
    2. When you want to wait for the user to press enter before continuing. The flush_input() function discards all input up to and including the new line, so it effectively waits for the user to press enter. Something like:
    Code:
    printf("Press 'enter' to continue...");
    flush_input();

  12. #12
    Registered User
    Join Date
    Jan 2013
    Posts
    28
    Ahh thank you! I got it to pause on the computer turn and ask the user to hit enter. Odd though when the user hits the enter key, this happens:


    You have rolled the following pair of dice:
    +-------+
    | |
    | @ |
    | |
    +-------+
    +-------+
    | @|
    | @ |
    | @ |
    +-------+
    You have the following choices to choose from:
    3/13/31
    13
    Player Score : 13
    The computer rolled the following pair of dice:
    +-------+
    | @|
    | @ |
    | @ |
    +-------+
    +-------+
    |@ @|
    |@ @|
    |@ @|
    +-------+
    The following choices to choose from are:
    18/36/63
    Press enter for the computer to choose a value.







    77

    Process returned -1073741819 (0xC0000005) execution time : 16.550 s
    Press any key to continue.


    As soon as I hit enter, the computer does not take one of the three possible combinations for the dice. It just stops the game right there. Here is my new code with the flush_input() for the computer's turn.
    Code:
            printf("The computer rolled the following pair of dice:\n");
            a = rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL;
            b = rand() % (MAX_VAL - MIN_VAL + 1) + MIN_VAL;
            multiply = a * b;
            d1d2 = a*10 + b;
            d2d1 = b*10 + a;
            dice_roll(a);
            dice_roll(b);
            printf("The following choices to choose from are:\n");
            printf("%i/%i/%i\n", multiply,d1d2,d2d1);
            printf("Press enter for the computer to choose a value.\n");
            if (multiply < d1d2 && d1d2 < d2d1)
            compscore = multiply;
            if (d1d2 < multiply && multiply < d2d1)
            compscore = d1d2;
            if (d2d1 < multiply && multiply < d1d2)
            compscore = d2d1;
            scanf("%i", compscore);
            flush_input();
            compscore = 0 + compscore;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. For Loop Issue
    By Dynesclan in forum C Programming
    Replies: 5
    Last Post: 05-07-2012, 09:35 PM
  2. for loop issue
    By begginer in forum C Programming
    Replies: 8
    Last Post: 03-20-2011, 08:22 AM
  3. Loop issue
    By Gordon in forum Windows Programming
    Replies: 14
    Last Post: 01-07-2008, 01:04 AM
  4. While loop issue
    By exvor in forum C Programming
    Replies: 2
    Last Post: 09-17-2005, 11:13 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21