Program from a book not working?

Monado_III

Well-Known Member
OP
Member
Joined
Feb 8, 2015
Messages
722
Trophies
0
Location
/dev/null
XP
1,443
Country
Canada
So I'm gradually learning C from this: http://www.amazon.com/Beginning-From-Novice-Professional/dp/1590597354 but there's an example that fails to work (on Linux) even when I straight copy it from the book. The problem occurs as soon as the random input is shown, so I as soon as I press enter nothing appear and thus it is an impossible game as it never showed me the string of digits I'm supposed to repeat. I'd try and figure it out but for all I know, what this book says is outdated.


Code:
/* Program 4.12 Simple Simon */

#include <stdio.h>                     /* For input and output   */
#include <ctype.h>                     /* For toupper() function */
#include <stdbool.h>                   /* For bool, true, false  */
#include <stdlib.h>                    /* For rand() and srand() */
#include <time.h>                      /* For time() and clock() */

int main(void)
{
  /* Records if another game is to be played */
  char another_game = 'Y';

  /* true if correct sequence entered, false otherwise */
  int correct = false;

  /* Number of sequences entered successfully          */
  int counter = 0;

  int sequence_length = 0;     /* Number of digits in a sequence        */
  time_t seed = 0;             /* Seed value for random number sequence */
  int number = 0;              /* Stores an input digit                 */

  time_t now = 0;            /* Stores current time - seed for random values  */
  int time_taken = 0;        /* Time taken for game in seconds                */

  /* Describe how the game is played */
  printf("\nTo play Simple Simon, ");
  printf("watch the screen for a sequence of digits.");
  printf("\nWatch carefully, as the digits are only displayed"
                                                " for a second! ");
  printf("\nThe computer will remove them, and then prompt you ");
  printf("to enter the same sequence.");
  printf("\nWhen you do, you must put spaces between the digits. \n");
  printf("\nGood Luck!\nPress Enter to play\n");
  scanf("%c", &another_game);

  /* One outer loop iteration is one game */
  do
  {
    correct = true;         /* By default indicates correct sequence entered */
    counter = 0;            /* Initialize count of number of successful tries*/
    sequence_length = 2;    /* Initial length of a digit sequence            */
    time_taken = clock();  /* Record current time at start of game       */

    /* Inner loop continues as long as sequences are entered correctly */
    while(correct)
    {
      /* On every third successful try, increase the sequence length */
      sequence_length += counter++%3 == 0;

      /* Set seed to be the number of seconds since Jan 1,1970  */
      seed = time(NULL);

      now = clock();                  /* record start time for sequence  */

      /* Generate a sequence of numbers and display the number */
      srand((unsigned int)seed);      /* Initialize the random sequence */
      for(int i = 1; i <= sequence_length; i++)
        printf("%d ", rand() % 10);    /* Output a random digit          */

      /* Wait one second */
      for( ;clock() - now < CLOCKS_PER_SEC; );

      /* Now overwrite the digit sequence */
      printf("\r");                   /* go to beginning of the line */
      for(int i = 1; i <= sequence_length; i++)
        printf("  ");                 /* Output two spaces */

      if(counter == 1)           /* Only output message for the first try */
        printf("\nNow you enter the sequence  - don't forget"
                                               " the spaces\n");
      else
        printf("\r");                /* Back to the beginning of the line */

      /* Check the input sequence of digits against the original */
      srand((unsigned int)seed);     /* Restart the random sequence    */
      for(int i = 1; i <= sequence_length; i++)
      {
        scanf("%d", &number);         /* Read an input number         */
        if(number != rand() % 10)     /* Compare against random digit */
        {
          correct = false;            /* Incorrect entry             */
          break;                      /* No need to check further... */
        }
      }
      printf("%s\n", correct? "Correct!" : "Wrong!");
    }

    /* Calculate total time to play the game in seconds)*/
    time_taken = (clock() - time_taken) / CLOCKS_PER_SEC;

    /* Output the game score */
    printf("\n\n Your score is %d", --counter * 100 / time_taken);

    fflush(stdin);

    /* Check if new game required*/
    printf("\nDo you want to play again (y/n)? ");
    scanf("%c", &another_game);

  }while(toupper(another_game) == 'Y');
  return 0;
}
 
Last edited by Monado_III,

zoogie

playing around in the end of life
Developer
Joined
Nov 30, 2014
Messages
8,560
Trophies
2
XP
15,000
Country
Micronesia, Federated States of
are you on linux? If so how are you running it? Terminal won't display the digits and skips the 'press y to play again part' altogether.
nope windows, hence the .exe output.

--------------------- MERGED ---------------------------

rename the attached file and try it.
i have a theory why it didn't work.
 

Attachments

  • simon.txt
    4 KB · Views: 237

zoogie

playing around in the end of life
Developer
Joined
Nov 30, 2014
Messages
8,560
Trophies
2
XP
15,000
Country
Micronesia, Federated States of
what? pls explain, How did that save like 100 bytes? From what I can tell based off of google results that would've only affected a few bytes.
There's about 100 lines of 2 chars in the win version, so you go to one char per line ending in a unix text file and save 100 bytes. Sounds right 2 me. :P

Anyway. Put a getch(); after the
printf("%s\n", correct? "Correct!" : "Wrong!");

it's hacky but may fix the issue.
 
  • Like
Reactions: Monado_III

cdoty

Well-Known Member
Member
Joined
Sep 14, 2009
Messages
329
Trophies
0
Website
www.rastersoft.net
XP
352
Country
United States
So I'm gradually learning C from this: http://www.amazon.com/Beginning-From-Novice-Professional/dp/1590597354 but there's an example that fails to work (on Linux) even when I straight copy it from the book. The problem occurs as soon as the random input is shown, so I as soon as I press enter nothing appear and thus it is an impossible game as it never showed me the string of digits I'm supposed to repeat. I'd try and figure it out but for all I know, what this book says is outdated.

Replace this:

Code:
/* Now overwrite the digit sequence */
printf("\r"); /* go to beginning of the line */
for(int i = 1; i <= sequence_length; i++)
printf(" "); /* Output two spaces */

With this:
Code:
/* Now overwrite the digit sequence */
#if 0
printf("\r"); /* go to beginning of the line */
for(int i = 1; i <= sequence_length; i++)
printf(" "); /* Output two spaces */
#endif

And see if it shows the result.

It's designed to hide the sequence after 1 second.

The correct way to write this for loop:
Code:
for( ;clock() - now < CLOCKS_PER_SEC; );

is:

Code:
for ( ;clock() - now < CLOCKS_PER_SEC; )
{
}

Many compilers will generate a warning on the original version, because it it a common programming error to put a semicolon at the end of for or while loops.

This should probably be a while loop also.
Code:
while (clock() - now < CLOCKS_PER_SEC)
{
}
 
  • Like
Reactions: Monado_III

Monado_III

Well-Known Member
OP
Member
Joined
Feb 8, 2015
Messages
722
Trophies
0
Location
/dev/null
XP
1,443
Country
Canada
Replace this:

/* Now overwrite the digit sequence */
printf("\r"); /* go to beginning of the line */
for(int i = 1; i <= sequence_length; i++)
printf(" "); /* Output two spaces */

With this:
/* Now overwrite the digit sequence */
#if 0
printf("\r"); /* go to beginning of the line */
for(int i = 1; i <= sequence_length; i++)
printf(" "); /* Output two spaces */
#endif

And see if it shows the result.

It's designed to hide the sequence after 1 second.

The correct way to write this for loop:
for( ;clock() - now < CLOCKS_PER_SEC; );

is:

for ( ;clock() - now < CLOCKS_PER_SEC; )
{
}

Many compilers will generate a warning on the original version, because it it a common programming error to put a semicolon at the end of for or while loops.

This should probably be a while loop also.
while (clock() - now < CLOCKS_PER_SEC)
{
}
What do the hashtags do for #if and #endif
 

cdoty

Well-Known Member
Member
Joined
Sep 14, 2009
Messages
329
Trophies
0
Website
www.rastersoft.net
XP
352
Country
United States
They are compiler directives.

In this case, it removes the code between #if 0 and #endif from the program. It's a way to conditionally compile sections of code.

You'll usually see it used in something like this

#if defined Win32
... code for Windows
#elif defined OSX
... code for Macs
#elif defined LINUX
... code for Linux
#endif

or:
#if defined DEBUG
.,. code only included in Debug builds
#endif
 
  • Like
Reactions: Monado_III

Cyan

GBATemp's lurking knight
Former Staff
Joined
Oct 27, 2002
Messages
23,749
Trophies
4
Age
45
Location
Engine room, learning
XP
15,648
Country
France
unrelated to the issue, I have a question:
Code:
sequence_length += counter++%3 == 0;
Shouldn't the right side comparison returns TRUE instead of 1 ?
sequence_length += true; is strange.

1 is true, but true is not 1.
By default a comparison returns 1 instead of true?
that's why sometime there are dual reverse to get true instead of 1?
!!( counter++%3 == 0) always returns true or false

i would have write
Code:
if(counter++%3 == 0)
    sequence_length++;

but if it returns 1 then I suppose inline is better, it uses less cycles.
 

tj_cool

Site dev
Supervisor
Joined
Jan 7, 2009
Messages
10,064
Trophies
2
Location
This planet
XP
3,102
Country
Belgium
unrelated to the issue, I have a question:
Code:
sequence_length += counter++%3 == 0;
Shouldn't the right side comparison returns TRUE instead of 1 ?
sequence_length += true; is strange.

1 is true, but true is not 1.
By default a comparison returns 1 instead of true?
that's why sometime there are dual reverse to get true instead of 1?
!!( counter++%3 == 0) always returns true or false

i would have write
Code:
if(counter++%3 == 0)
    sequence_length++;

but if it returns 1 then I suppose inline is better, it uses less cycles.
Booleans don't really exist in C. "FALSE" is represented by the integer 0 and "TRUE" by any other integer (standardized as 1).

The C open standard actually mentions it:
Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type int.
 
  • Like
Reactions: Cyan

cdoty

Well-Known Member
Member
Joined
Sep 14, 2009
Messages
329
Trophies
0
Website
www.rastersoft.net
XP
352
Country
United States
It displays the digits now (and it looks like the rest of the program works), but then how would I go about getting the digits to disappear after 1 second?

I am surprised the original code doesn't work. You may try replacing it with:

for ( ;clock() - now < CLOCKS_PER_SEC * 3; )
{
}

to give it a three second delay. and see if that works. My guess is clock() may not work correctly on new systems.
 
Last edited by cdoty,

Monado_III

Well-Known Member
OP
Member
Joined
Feb 8, 2015
Messages
722
Trophies
0
Location
/dev/null
XP
1,443
Country
Canada
I surprised the original code doesn't work. You may try replacing it with:

for ( ;clock() - now < CLOCKS_PER_SEC * 3; )
{
}

to give it a three second delay. and see if that works. My guess is clock() may not work correctly on new systems.
Tried it and it still didn't work, this is what the program should look like right?
 

Attachments

  • program4_12.txt
    4.2 KB · Views: 258

zoogie

playing around in the end of life
Developer
Joined
Nov 30, 2014
Messages
8,560
Trophies
2
XP
15,000
Country
Micronesia, Federated States of
Tried it and it still didn't work, this is what the program should look like right?
Honestly, you should move on with your book.
A single demo program not working is insignificant compared with the rest of your learning.
Allocate your time wisely.

Besides, once you have a grasp of the language, you will be better equiped to debug issues like this rather than get others to figure it out.
 

Monado_III

Well-Known Member
OP
Member
Joined
Feb 8, 2015
Messages
722
Trophies
0
Location
/dev/null
XP
1,443
Country
Canada
Honestly, you should move on with your book.
A single demo program not working is insignificant compared with the rest of your learning.
Allocate your time wisely.
I would, but that's the end of the chapter and sone of the exercises requires me to modify the program and do some other stuff with time.
Although I might do that if no one comes up with solution by the end of of today.
 

sarkwalvein

There's hope for a Xenosaga port.
Member
Joined
Jun 29, 2007
Messages
8,506
Trophies
2
Age
41
Location
Niedersachsen
XP
11,221
Country
Germany
I would, but that's the end of the chapter and sone of the exercises requires me to modify the program and do some other stuff with time.
Although I might do that if no one comes up with solution by the end of of today.

Don't be dirty!
Flush the output!

Code:
/* Program 4.12 Simple Simon */
#include <stdio.h>                     /* For input and output   */
#include <ctype.h>                     /* For toupper() function */
#include <stdbool.h>                   /* For bool, true, false  */
#include <stdlib.h>                    /* For rand() and srand() */
#include <time.h>                      /* For time() and clock() */

int main(void)
{
  /* Records if another game is to be played */
  char another_game = 'Y';

  /* true if correct sequence entered, false otherwise */
  int correct = false;

  /* Number of sequences entered successfully          */
  int counter = 0;

  int sequence_length = 0;     /* Number of digits in a sequence        */
  time_t seed = 0;             /* Seed value for random number sequence */
  int number = 0;              /* Stores an input digit                 */

  time_t now = 0;            /* Stores current time - seed for random values  */
  int time_taken = 0;        /* Time taken for game in seconds                */

  /* Describe how the game is played */
  printf("\nTo play Simple Simon, ");
  printf("watch the screen for a sequence of digits.");
  printf("\nWatch carefully, as the digits are only displayed"
                                                " for a second! ");
  printf("\nThe computer will remove them, and then prompt you ");
  printf("to enter the same sequence.");
  printf("\nWhen you do, you must put spaces between the digits. \n");
  printf("\nGood Luck!\nPress Enter to play\n");
  scanf("%c", &another_game);

  /* One outer loop iteration is one game */
  do
  {
    correct = true;         /* By default indicates correct sequence entered */
    counter = 0;            /* Initialize count of number of successful tries*/
    sequence_length = 2;    /* Initial length of a digit sequence            */
    time_taken = clock();  /* Record current time at start of game       */

    /* Inner loop continues as long as sequences are entered correctly */
    while(correct)
    {
      /* On every third successful try, increase the sequence length */
      sequence_length += counter++%3 == 0;

      /* Set seed to be the number of seconds since Jan 1,1970  */
      seed = time(NULL);

      now = clock();                  /* record start time for sequence  */

      /* Generate a sequence of numbers and display the number */
      srand((unsigned int)seed);      /* Initialize the random sequence */
      for(int i = 1; i <= sequence_length; i++)
        printf("%d ", rand() % 10);    /* Output a random digit          */

     // (!) Flush the text OUTPUT!!!
     // Otherwise the buffered output waits for a new line (\n) to print data
     fflush(stdout);

      /* Wait one second */
      for(;clock() - now < CLOCKS_PER_SEC*3;);

      /* Now overwrite the digit sequence */
      printf("\r");                   /* go to beginning of the line */
      for(int i = 1; i <= sequence_length; i++)
      printf("  ");                 /* Output two spaces */

     // (!) Flush the text OUTPUT!!!
     // Otherwise the buffered output waits for a new line (\n) to print data
     fflush(stdout);

      if(counter == 1)           /* Only output message for the first try */
        printf("\nNow you enter the sequence  - don't forget"
                                               " the spaces\n");
      else
        printf("\r");                /* Back to the beginning of the line */

      /* Check the input sequence of digits against the original */
      srand((unsigned int)seed);     /* Restart the random sequence    */
      for(int i = 1; i <= sequence_length; i++)
      {
        scanf("%d", &number);         /* Read an input number         */
        if(number != rand() % 10)     /* Compare against random digit */
        {
          correct = false;            /* Incorrect entry             */
          break;                      /* No need to check further... */
        }
      }
      printf("%s\n", correct? "Correct!" : "Wrong!");
    }

    /* Calculate total time to play the game in seconds)*/
    time_taken = (clock() - time_taken) / CLOCKS_PER_SEC;

    /* Output the game score */
    printf("\n\n Your score is %d", --counter * 100 / time_taken);

    fflush(stdin);

    /* Check if new game required*/
    printf("\nDo you want to play again (y/n)? ");
    scanf("%c", &another_game);

  }while(toupper(another_game) == 'Y');
  return 0;
}
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Maximumbeans @ Maximumbeans: It's going alright thanks :) I know what you mean with gaming time. It's precious where I can...