Lab Activity 8

Lab Description:

This week's lab consists of four parts. In the second part you review how loops work in C and consider how to generate random numbers in C. In the third part we will write a number-guessing game in C. To do so you will use C program constructs such as the if-else statement and the while statement.

In the fourth part of this lab you will learn to use external libraries to draw some 3D graphics. To do so, you will use for-loops and the OpenGL graphics library.



Part 1: Prelab


First of all, this lab requires you to use some math functions. Don't forget to use the -lm option when compiling your code.

Fill in the blanks to answer the following questions. You should use the material found in Lecture 12 and 13/14 of the course notes and/or the course C book Chapters 3.6 , 6.3 & 3.7 - 3.10, 7.5
As with all prelabs/labs, if you are not sure of the answer you may go to any EWS lab on campus and check your results by using the gcc compiler, or you can ask anyone of the CS101 staff for help.

The following exercises should help prepare you for the in-lab activities and MP2.


You will use the C selection statements (if and if-else) along with C loop statements (while, do-while,for).

  1. The following C program compiles without errors. Write the output produced by this program.

    #include <stdio.h> 
    void main(void)
    { 
      int i = 17.25; /* i holds ONLY  integer values */
      double x;
       
      printf(" %i ", i );
      x = 8 / 3;    /* 8 and 3 are integers */
      printf("%lf ",x);
      x = 8 / 3.0;   /* 8 is an integer 3.0 is a real (double) */
      printf("%lf ",x);
      
      x = 8.0 / 3; 
      printf("%lf ",x); 
      x = 8.0/3.0;
      printf("%lf ",x);
      printf("\n"); 
    }
    _______________________________ 
     
  2. The following C program compiles without errors. Write the output produced by this program.

  3. #include <stdio.h> 
    void main(void)
    { 
       int x ; 
       if (0)              /* 0 means FALSE */
          printf("False ");
       if (33)              /* any non-zero value in C means TRUE */
          printf("True ");
       x = 0;
       if (x == -1) 
         printf("T "); 
       else 
        if (x != 0)       /* != means "not equal" */
          printf("U "); 
        else 
        printf("Y ");
       if (x == -1);      /* BAD place for a ; as discussed in lecture */
           printf("(';' Are not good after ifs) ");
       if (x = 0)        /* oops!, forgot == */
          printf("W ");
       printf("\n");
    } 
    _________________________________________________________________________
     
  4. The following C program compiles without errors. Write the output produced by this program.

    #include <stdio.h>

    void main(void)
    { 
  5.    	int x = 8; 
       	int y = 3; 
       	if ((x < 2) || ( y > 3))   /* || means OR */
         	printf("L "); 
      
       	if ((x > 7) && (y < 4))    /* && means AND */
        		printf("M "); 
       	else 
        		printf("N ");
       	if ( !(x < 10))            /* ! means NOT */
               printf("O ");
       	printf("\n");
    }

    _____________________________________________________


  6. The following C program compiles without errors (Note: there are no typos). Write the output produced by this program.

    #include <stdio.h> 
    void main(void)
    { 
       int y = 3; 
       while (y >= 0)    /* while condition is TRUE execute code in block { } */
       { 
            y = y - 2;
       } 
       printf("y = %i ",y);
     
       printf("\n");
       
    } 
    _________________________________________________________________________ 
     
        
  7. The following C program compiles without errors (Note: there are no typos). Write the output produced by this program.

    #include <stdio.h> 
    void main(void)
    { 
       int y = 56; 
       while (y >= 0)    /* how many statements below are part of the while loop? */
         y = y - 1;
         printf("T ");
     
       printf("\n");
       
    }  
    _________________________________________________________________________ 
  8. The following C program compiles without errors (Note: there are no typos). Write the output produced by this program.

    #include <stdio.h> 
    void main(void)
    { 
       int y = 2; 
       while (y >= 0)    /* how many statements below are part of the while loop? */
       { 
            y = y - 1; 
            printf("N ");
       }
       printf("\n");
     } 
    ________________________________________________________________________
     
  9. The following C program compiles without errors. Write the output produced by this program.

    #include <stdio.h> 
    void main(void)
    { 
       int i; 
       for(i=1; i < 6; i=i+2) 
       { 
          printf("%i ",i);  
       } 
       printf("\n"); 
    } 
        
    _______________________________________________________________________ 
  10. The following C program compiles without errors. Write the output produced by this program.

    #include <stdio.h> 
    void main(void)
    { 
       int i, j; 
       for(i=0; i < 4; i=(2*i)+1) 
          for(j=i; j < 2; j = j + 1) 
               printf("<%i,%i> ",i,j);   
     } 
        _____________________________________________________________ 
  11. The following code fragment is placed in a complete C program compiled (without errors) and run. Will the following loop terminate? (Yes/ No)

    ______________________________________________________________
    Note: A loop that does not terminate is called an infinite loop.

       int a=8; 
       int b=8; 
       while(1) /* 0 means False any other value means True */   
       {        
          if(a > b) 
             break;      /* the break statement "breaks out" of loops and switch statements  */
          if (a == 100) 
             a = 1; 
          else   /* else matches with the closest if (unless {} are used) */
             b = b - 1; 
       } 
  12. The following C program compiles without errors. Write the output produced by this program.

    #include <stdio.h>
     
    void main(void)
    { 
       int i = 3; 
       do 
       { 
         printf("%i ",i-1); 
         i = i - 2; 
       } while( i > 0); 
       printf("\n");
    } 

    ______________ ______________

  13. Complete the following loop to print all the odd numbers from 1 to 99 inclusive as follows:

    1 3 5 7 9 ... 99

      int i;
      for(i = 1; _____________________;  ________________) 
      {  
        
          printf("%i ", ___________________ );
      }




  14. The following C program compiles without errors. Write the output produced by this program.
    Note that abs is used for integer values but fabs is used for values of data type float or double.

    #include <stdio.h>
    #include <math.h>

    void main(void)
    {
        float x = 1.0/3.0; /* float and double data types hold real numbers. double holds more digits than float */
        double y = 1.0/3.0;

        if (x == y)
           printf(" x equals y ");
        else if ( fabs(x - y) < 1.0e-6)
                    printf(" x is close to y ");
               else if (fabs(x-y) < 1.0e-20)
                           printf(" x is very close to y ");
                       else
                            printf(" x is not even close to y! ");

        printf("\n");
    }


    ________________________________________________________________________________________________



Part 2: Doing Loops and Random Numbers

Three types of loops

We often want to write programs that do something over and over again, and for that we use loops. There are three types of loops available. The first type is the while loop, which looks like this:

  while( condition ) 
  {
 
     Do something...    
  } 

Of course, condition has to be replaced by a real C logical condition. As long as the condition is true, the statements in between the braces get repeated.

For example, copy/paste/compile and run the program below.

Open at Unix terminal (Go to Applications, Utilities, Terminal to open a Unix prompt). Type the following commands at the Unix prompt:

cd ( change to your home directory )

mkdir lab8 ( create a new directory named lab8 )

cd lab8 ( make lab8 your new directory )

gedit loop.c & ( & opens the gedit program in another window)


/* The following program generates 5 random integer values from 0 to N. */

  #include <stdio.h>
  #include <time.h>    /* library containing the "time" function */
  #include <stdlib.h>  /* library containing the "rand" function */
  void main(void) 
  {
     int N;
     int Total = 5;
     int counter = 1;
      
     printf("Enter a number: ");
     scanf("%i", &N);
     while(counter <= Total) 
     {
       printf(" %i ", rand()% (N+1) ); /* generate a random number between 0 and N inclusive */
       counter = counter + 1;
     }
     
     printf("\n");
  } 



The function rand() returns an integer value from 0 to RAND_MAX ( a constant equal to 2,147,483,647 on our lab machine).

Answer question #1 on the answer sheet.

A variation of the while loop is the do-while loop.

  do 
  {
     Do something here...
  } while( condition ); 

Notice the semicolon at the end. First the code "Do something here..." is executed then the condition is checked. If the condition is TRUE then the code is executed again else if the condition is FALSE then the loop is finished.



Answer Question #2 on the Answer Sheet.




Often when we write a loop, there's one particular variable whose value determines when the loop stops. For example, in the loops above, the variable counter serves that purpose. So the third type of loop, the for loop, makes it a little easier to control the value of that variable. for loops look like this:

  for( initialize; condition; update ) 
  {
     Do something here...
  } 

initialize, condition, and update have to be replaced by real C statements. Notice that there are always two semicolons between the parentheses of a for loop. A for with the above structure is essentially identical to a while loop like this:

  initialize;
  while( condition ) 
  {
     Do something here...
     update;
  } 

Answer Question #3 on the Answer Sheet.


Part 3 Guessing Game

1. Requirements Specification (Problem Definition)

You will write a program where the computer generates a random integer between 1 and N (for some positive integer N) and the user tries to guess that number. The user will be given an unlimited number of guesses, until the correct number is guessed.

2. Analysis---Refine, Generalize, Decompose the problem definition

Request from the user 'e'asy , 'm'oderate or 'd'ifficult level for the game.
'e' means that the user guesses a number in the range 1 and N=16.
'm' means that the user guesses a number in the range 1 and N=128.
'd' means that the user guesses a number range 1 and N=1024.

Generate an integer value in the approriate range and assign to the variable named target.
Allow the user to guess any number of times until the user guesses the value assigned to the variable target .
If the guess is less than or greater than the target tell the user whether the guess was larger or smaller than the target, and allow the user to guess again.
If the user makes a correct guess tell them and terminate the program.

3. Design---Develop Algorithm

4. Implementation --- Write the "Program" (Code)

If you have closed the editor please reopen,

gedit guess.c & ( the *& makes gedit open in a new window (the background) )

Copy the following piece of code into the guess.c file.

#include <stdio.h>
#include <time.h> /* library containing the "time" function */
#include <stdlib.h> /* library containing the "rand" and "srand" functions */

void main(void)
{
/* declare all variables here */
char choice;
int N;
int guess;
int target;




/* prompt the user to enter the SINGLE character e, m or d */

/* read the character into the variable named choice */

/* use a nested-if or switch statement to assign a value to N */
/* see first flowchart above */








/* using the rand function assign a random integer value from 1 to N to a variable named target */
/* To generate a random integer between a and b you can use the expression: rand()%(b+1 - a) + a */
target = ________________ ;

/* complete the remainder of the program using the second flowchart above */



}



Hints:
To check for choice you can either use a nested if-else statement or a switch statement, which is more compact.
To generate a random integer between a and b you can use the expression: rand()%(b+1 - a) + a
To generate an infinite while or do-while loop try,
while(1)
{

/* your code here */

}
To generate an infinite for loop try for ( ... ; ; ...) where you omit any value between the pair of semicolons.
When you want to execute two or more statements in an if statement you will need to use a pair of curly braces { }. For example to write code that executes if guess = target you write,

if (guess == target)
{
print something
return;
}

To STOP running current job in Linux console, press 'Ctrl' and 'c' at the same time.

5. Run the code

Save your code and then compile your program by typing the following at the Unix prompt:

$ gcc guess.c -o guess
$ ./guess


OR

$ gcc guess.c
$ ./a.out


To see a demo of how your program should work copy the runnable file named 'guess' from the directory ~cs101ta/public_html/labs/lab8. Run this program by typing

 $ ./guess

at the Unix prompt. (assuming the runnable file is already in the current directory)

Make sure your program works properly before you proceed to the next step. If in doubt, ask your TA for help.

Answer question #4 on the answer sheet.


Now, we'd like to modify the program to generate a different random number every time we run the program. To do this you will need to add the statement,

  srand(time(NULL));

immediately after the declarations but before any executable code. The statement srand(time(NULL)); sets the seed (or first value) of the rand() function so that the first random number occurs at "random". Every time you re-run your program rand will not always return the same first random number. The statement above says, seed the random number generator with the current time on the computer clock. The time() function returns the time on the clock when the program is running and is to some degree random, assuming the time is kept down to milliseconds. To read more about srand() and rand() see the course book "Applied C An Introduction and More" pp. 260-261, or simply Google “srand rand”. Then save, compile and run your program.

Answer question #5 on the answer sheet.



Part 4 Using external libraries / OpenGL

1. Requirements Specification (Problem Definition)

In this section, we will learn to use external libraries as part of a C program. One of the most common libraries used in C is the OpenGL graphics library. This is the graphics technology behind many popular video games, such as Quake 3 and Half-Life. OpenGL has also been used to create feature-length films.

You will use some simple OpenGL code to plot and visualize a mathematical function z = y*cos(x)*cos(x)/6.0 where x takes values on the interval [-10,10] and y takes values on the interval [-6,6].

2. Analysis---Refine, Generalize, Decompose the problem definition

The user does not enter any values. The program outputs a plot on a separate window.

3. Design---Develop Algorithm

We give you most of the code. Copy the file named 'lab8.c' from the directory named ~cs101ta/public_html/labs/lab8 . Use the gedit editor and find the code skeleton for the function named myfunction.

4. Implementation --- Write the "Program" (Code)

Step 1. In the function named myfunction in file lab8.c, locate the comment:

/* Draw coordinate axes */
/* write six lines of code, 2 for each line */
/* see step 1. */

The OpenGL function glBegin(GL_LINES) sets up an environment in which every pair of new vertices you draw creates a line. For example, the code:

glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(10.0f, 0.0f, 0.0f);

will create a line from the point (1,0,0) to the point (10,0,0). glVertex3f takes three floating point numbers as arguments.
Remember that if you type a decimal number in C, the default will make that number a double. However, the OpenGL functions you will use in this lab require floats as arguments. This is why you must put an 'f' at the end of each number.
The glVertex3f function has three arguments,
glVertex3f( y coordinate, z coordinate, x coordinate)

The glEnd() function stops the line drawing environment.

Write OpenGL code in the editor to draw the three coordinate axes, each starting at the origin and extending out with length 10.

When you are ready, compile your program by saving it. Test your program by running your program copy/pasting the following to the Unix prompt:

gcc lab8.c -o lab8 -lGL -lGLU `sdl-config --cflags --libs`

lab8



Note, try selecting with your mouse and then middle-clicking to copy. Make sure you copy the single quote (').

You should see a window that looks like this:

You can rotate the 3D image by clicking on it and then using the arrow keys.

Step 2. Locate the comment:

/* your line of code goes here to compute z see step 2. */

Write a single line of C code in the editor to perform the following assignment,
z = y*cos(x)*cos(x)/6.0
We are plotting the point (x,y,z) in OpenGL where z = y*cos(x)*cos(x)/6.0 for values of x in [-10,10] and y in [-6,6]. We use a pair of nested for loops to do this.


Step 3. Locate the comment:
/* your single line of code goes here to plot the point (x,y,z) see step 3. */
/* remember in using glVertex3f( y coordinate , z coordinate , x coordinate */

The OpenGL function glBegin(GL_POINTS) sets up an environment in which every vertex you draw creates an individual point. For example, the code:

glVertex3f(1.0f, 1.0f, 1.0f); 

will draw a point located at (1,1,1).
Write a single line of C code in the editor to plot the single point (x,y,z) using the glVertex3f function.
Remember, the glVertex3f function has three arguments,
glVertex3f( y coordinate, z coordinate, x coordinate)

When you are ready, compile your program by saving it. Test your program by running your program copy/pasting the following to the Unix prompt:

gcc lab8.c -o lab8 -lGL -lGLU `sdl-config --cflags --libs`

lab8



Note, try selecting with your mouse and then middle-clicking to copy. Make sure you copy the single quote (').

You should see a window that looks like this:

You can rotate the 3D image by clicking on it and then using the arrow keys.

Step 4. Locate the comment:

/* your single line of code goes here to use glColor3f to shade plot see step 4. */


Well, we have a 3D plot, but it looks a little dull. Let's add some color. The OpenGL function glColor3f takes 3 float arguments between 0.0 and 1.0. The first argument is the amount of red, the second is the amount of green, and the third is the amount of blue.

glColor3f( red , green , blue )

For example,

glColor3f(0.0f, 0.0f, 1.0f)

would be the color dark blue, since it has no red or green, but is as much blue as possible.
When you call the glColor3f function, everything OpenGL draws afterwards will be the specified color.


Write a sinlge line of C code to:

1. Make the color blue everywhere

2. Also add more red as the height (z value) of the function increases, thus making purple tips (change the amount of red color equal to the value of the variable z)

Compile and run your program. It should look something like this:

You can rotate the 3D image by clicking on it and then using the arrow keys.

Answer question #6 on the answer sheet.




Appendix A: OpenGL functions used in this lab.

glBegin(GL_LINES): Sets up the line drawing environment of OpenGL. Until you call glEnd(), all vertices drawn will be interpreted as endpoints of a line.

glBegin(GL_POINTS): Sets up the point drawing environment of OpenGL. Until you call glEnd(), all vertices drawn will be interpreted as individual points.

glEnd(): Closes any vertex interpreting environment. If you draw vertices after calling glEnd(), they will be ignored.

glVertex3f(float y, float z, float x): Draws a vertex on the point specified by the input arguments.

glColor3f(float red, float green, float blue): Changes the color used to draw OpenGL objects. Each value is a float between 0.0f and 1.0f.