Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #76246 > unrolled thread

Game of life from K&R: question about switch statement

Started byAlla _ <modelling.data@gmail.com>
First post2015-11-17 08:34 -0800
Last post2015-11-17 15:12 -0800
Articles 7 — 7 participants

Back to article view | Back to comp.lang.c


Contents

  Game of life from K&R: question about switch statement Alla _ <modelling.data@gmail.com> - 2015-11-17 08:34 -0800
    Re: Game of life from K&R: question about switch statement Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-17 11:46 -0500
    Re: Game of life from K&R: question about switch statement James Kuyper <jameskuyper@verizon.net> - 2015-11-17 11:56 -0500
      Re: Game of life from K&R: question about switch statement glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-17 20:19 +0000
        Re: Game of life from K&R: question about switch statement "Charles Richmond" <numerist@aquaporin4.com> - 2015-11-19 17:48 -0600
    Re: Game of life from K&R: question about switch statement Stephen Sprunk <stephen@sprunk.org> - 2015-11-17 12:27 -0600
    Re: Game of life from K&R: question about switch statement Keith Thompson <kst-u@mib.org> - 2015-11-17 15:12 -0800

#76246 — Game of life from K&R: question about switch statement

FromAlla _ <modelling.data@gmail.com>
Date2015-11-17 08:34 -0800
SubjectGame of life from K&R: question about switch statement
Message-ID<16998259-e524-4529-94e3-8e17be7041fa@googlegroups.com>
Hello!

Please, take a look a the program from K&R tutorial; it has descriptive 
comments, therefore I will skip adding my ones. I would be grateful 
for the help. 

I am not sure I understand how the switch statement works within 
BuildNextGeneration () function. I read it as:

if a value at the position array[i][j] is '*', then the program
has to choose between 3 cases. Given each case in switch statement should
have a certain value to which the condition is compared, I don't 
understand what 2 or 3 represent: 

if the amount of neighbors, as could be deducted from the comment, then how 
count[i][j] can ever have a value of 2 or 3, if 2 or 3 represent the 
number of neighbors and not values at particular addresses. 

BuildNextGeneration (char array[SIZE][SIZE], int count[SIZE][SIZE])

/* A cell will survive if it has two or three */
/* neighbours. New life will be born to a dead */
/* cell if there are exactly three neighbours */
{
    int i,j;
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            if (array[i][j] == '*')
            {
                switch (count[i][j])
                {
                    case 2 :
                    case 3 : continue;
                    default: array[i][j] = '.';
                             break;
                }
            }
            else
            {
                switch (count[i][j])
                {
                    case 3 : array[i][j] = '*';
                             break;
                    default: continue;
                }
            }
        }
     }
}

Here is the program:

/* */
/* Game of Life */
/* */
/*********************************************************/
/* Based upon an article from Scientific American */
/* in 1970. Simulates the reproduction of cells */
/* which depend on one another. The rules are */
/* that cells will only survive if they have a */
/* certain number of neighbours to support them */
/* but not too many, or there won't be enough */
/* food! */
#include <stdio.h>

#define SIZE 5
#define MAXNUM 15
#define INBOUNDS (a >= 0) && (a < SIZE) && (b >= 0) && (b < SIZE)
#define NORESPONSE 1 
/*********************************************************/
/* Level 0 */
/*********************************************************/
main ()
{
    int count[SIZE][SIZE];
    char array[SIZE][SIZE];
    int generation = 0;
    
    printf ("Game of Life\n\n\n");
    
    InitializeArray(array);
    
    while (NORESPONSE)
    {
        CountNeighbours(array,count);
        BuildNextGeneration(array,count);
        UpdateDisplay(array, ++generation);
        
        printf ("\n\nQ for quit. RETURN to continue.\n");
        
        if(quit())
            break;
    }
}
/**********************************************************/
/* Level 1 */
/**********************************************************/

InitializeArray (char array [SIZE][SIZE]) /* Get starting conditions */

{
    int i,j;
    char ch;
    
    printf ("\nEnter starting setup. Type '.' for empty");
    printf ("\nand any other character for occupied.\n");
    printf ("RETURN after each line.\n\n");
    printf ("Array size guide:\n\n");
    
    for (i = 0; i++ < SIZE; printf("%c", '^'));
        printf ("\n\n");
    
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            scanf ("%c", &ch);
            
            if (ch == '.')
            {
                array[i][j] = '.';
            }
            else
            {
                array[i][j] = '*';
            }
        }
        skipgarb();
    }
    printf ("\n\nInput is complete. Press RETURN.");
    skipgarb();
}
/********************************************************/
CountNeighbours (char array[SIZE][SIZE], int count[SIZE][SIZE]) /* count all neighbours */
{
    int i,j;
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            count[i][j] = numalive(array, i, j);
        }
    }
}
/*******************************************************/


BuildNextGeneration (char array[SIZE][SIZE], int count[SIZE][SIZE])
/* A cell will survive if it has two or three */
/* neighbours. New life will be born to a dead */
/* cell if there are exactly three neighbours */
{
    int i,j;
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            if (array[i][j] == '*')
            {
                switch (count[i][j])
                {
                    case 2 :
                    case 3 : continue;
                    default: array[i][j] = '.';
                             break;
                }
            }
            else
            {
                switch (count[i][j])
                {
                    case 3 : array[i][j] = '*';
                             break;
                    default: continue;
                }
            }
        }
     }
}

/*******************************************************/
UpdateDisplay (char array[SIZE][SIZE], int g)
/* print out life array */
{
    int i,j;
    
    printf ("\n\nGeneration %d\n\n", g);
    
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            printf("%c", array[i][j]);
        }
        printf("\n");
    }
}
/*******************************************************/
/* Level 2 */
/*******************************************************/
numalive (char array[SIZE][SIZE], int i, int j)
/* Don't count array[i,j] : only its neighbours */
/* Also check that haven't reached the boundary */
/* of the array */

{
    int a,b,census;
    census = 0;
    
    for (a = (i - 1); (a <= (i + 1)); a++)
    {
        for (b = (j - 1); (b <= (j + 1)); b++)
        {
            if (INBOUNDS && (array[a][b] == '*'))
            {
                census++;
            }
        }
    }
    if (array[i][j] == '*')
        census--;
    
    return (census);
}
/********************************************************/
/* Toolkit input */
/********************************************************/
quit()
{
    char ch;
    
    while (NORESPONSE)
    {
        scanf ("%c",&ch);
        
        if (ch != '\n')
            skipgarb();
        
        switch (ch)
        {
            case 'q' : case 'Q' : return (1);
            default : return (0);
        }
    }
}
/********************************************************/
skipgarb ()
{
    while (getchar() != '\n')
    {
    }
}

Thank you!

[toc] | [next] | [standalone]


#76248

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-11-17 11:46 -0500
Message-ID<n2flgr$f1q$1@dont-email.me>
In reply to#76246
On 11/17/2015 11:34 AM, Alla _ wrote:
> Hello!
>
> Please, take a look a the program from K&R tutorial; it has descriptive
> comments, therefore I will skip adding my ones. I would be grateful
> for the help.
>
> I am not sure I understand how the switch statement works within
> BuildNextGeneration () function. I read it as:
>
> if a value at the position array[i][j] is '*', then the program
> has to choose between 3 cases. Given each case in switch statement should
> have a certain value to which the condition is compared, I don't
> understand what 2 or 3 represent:

     The three cases are "two neighbors," "three neighbors," and "other."
This suggests a switch statement with the general outline:

	switch (neighbors) {
	    case 2:
	        // handle "two neighbor" case
	        break;
	    case 3:
	        // handle "three neighbors" case
	        break;
	    default:
	        // handle "other" case
	        break;
	}

     It turns out that the handling is the same for the two- and three-
neighbors cases, so we can combine those two in the switch:

	switch (neighbors) {
	    case 2:
	    case 3:
	        // handle "two neighbors" or "three neighbors"
	        break;
	    default:
	        // handle "other" case
	        break;
	}

     This could have been written in other ways, like

	if (neighbors == 2 || neighbors == 3) {
	    // handle "two neighbors" or "three neighbors"
	} else {
	    // handle "other" case
	}

... but I'm guessing the point of the lesson is to teach you about
the switch statement.  Too bad you've not been given a more compelling
example.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#76251

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-17 11:56 -0500
Message-ID<n2fm3p$iau$1@dont-email.me>
In reply to#76246
On 11/17/2015 11:34 AM, Alla _ wrote:
> Hello!
> 
> Please, take a look a the program from K&R tutorial; it has descriptive 
> comments, therefore I will skip adding my ones. I would be grateful 
> for the help. 
> 
> I am not sure I understand how the switch statement works within 
> BuildNextGeneration () function. I read it as:
> 
> if a value at the position array[i][j] is '*', then the program
> has to choose between 3 cases. Given each case in switch statement should
> have a certain value to which the condition is compared, I don't 
> understand what 2 or 3 represent: 
> 
> if the amount of neighbors, as could be deducted from the comment, then how 
> count[i][j] can ever have a value of 2 or 3, if 2 or 3 represent the 
> number of neighbors and not values at particular addresses.

For any given location in the array, i and j, there are eight different
locations which are considered to be neighboring: array[i-1][j-1],
array[i-1][j], array[i-1][j+1], array[i][j-1], array[i][j+1,
array[i+1][j-1], array[i+1][j], array[i+1][j+1].  This definition is
adjusted appropriately at the edges and corners of the array, where some
of the locations that would ordinarily be considered neighbors, don't
actually exist.

The count array gets filled in with the count of the number of
neighboring locations that are currently occupied. It can therefore be
any number from 0 to 8. In particular, if 2 or 3 of the neighboring
locations are occupied, then count can be either 2 or 3. This seems
pretty obvious - why did you think the count could not be either 2 or 3?

A much more interesting question is why those particular values were
chosen. Those values are part of the definition of the "Game of Life".
They were chosen because it was discovered that with those particular
values, the dynamics of the game get very interesting. You can
experiment by adding or removing cases to each switch statement, and see
what happens. For most of the possibilities, the results are pretty boring.

The "Game of Life" is one particular example of a general category
called cellular automata. If you change the cases in each switch
statement, you generate a different cellular automaton. Cellular
automata are very well studied, there's lots of literature you can
review, and it's relatively easy to experiment with them on your own.

However, judging from your questions, you're not quite ready to write
cellular automata code. Make sure you understand the basics of C first -
then you can have lots of fun exploring this subject. It's a good way to
learn basic programming skills - but before you can start, you first
need to master even more basic skills, which you haven't done yet.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#76288

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-11-17 20:19 +0000
Message-ID<n2g25a$4jk$1@speranza.aioe.org>
In reply to#76251
James Kuyper <jameskuyper@verizon.net> wrote:
> On 11/17/2015 11:34 AM, Alla _ wrote:

(snip)
>> Please, take a look a the program from K&R tutorial; it has descriptive 
>> comments, therefore I will skip adding my ones. I would be grateful 
>> for the help. 
 
(snip) 
> For any given location in the array, i and j, there are eight different
> locations which are considered to be neighboring: array[i-1][j-1],
> array[i-1][j], array[i-1][j+1], array[i][j-1], array[i][j+1,
> array[i+1][j-1], array[i+1][j], array[i+1][j+1].  This definition is
> adjusted appropriately at the edges and corners of the array, where some
> of the locations that would ordinarily be considered neighbors, don't
> actually exist.

The tradition for game of life is a torodial world. When you go off
one direction, such as +y or -y, it wraps around. The other direction
(+x or -x) it wraps with an offset of 1. 

Sometimes it is simplified to save work of the programmer.

In the jury assembly room for the City of Seattle courts there is
a big panel with elevator buttons that plays the game of life.
I think it doesn't use the toroidal coordinate system, though.

-- glen

[toc] | [prev] | [next] | [standalone]


#76574

From"Charles Richmond" <numerist@aquaporin4.com>
Date2015-11-19 17:48 -0600
Message-ID<n2lmvl$3eq$1@dont-email.me>
In reply to#76288
"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message 
news:n2g25a$4jk$1@speranza.aioe.org...
> James Kuyper <jameskuyper@verizon.net> wrote:
>> On 11/17/2015 11:34 AM, Alla _ wrote:
>
> (snip)
>>> Please, take a look a the program from K&R tutorial; it has descriptive
>>> comments, therefore I will skip adding my ones. I would be grateful
>>> for the help.
>
> (snip)
>> For any given location in the array, i and j, there are eight different
>> locations which are considered to be neighboring: array[i-1][j-1],
>> array[i-1][j], array[i-1][j+1], array[i][j-1], array[i][j+1,
>> array[i+1][j-1], array[i+1][j], array[i+1][j+1].  This definition is
>> adjusted appropriately at the edges and corners of the array, where some
>> of the locations that would ordinarily be considered neighbors, don't
>> actually exist.
>
> The tradition for game of life is a torodial world. When you go off
> one direction, such as +y or -y, it wraps around. The other direction
> (+x or -x) it wraps with an offset of 1.
>
> Sometimes it is simplified to save work of the programmer.
>
> In the jury assembly room for the City of Seattle courts there is
> a big panel with elevator buttons that plays the game of life.
> I think it doesn't use the toroidal coordinate system, though.
>

Spare Time Gizmos also sold an electronic project that would play the game 
of life in a picture frame using individual LED's for the cells.

-- 

numerist at aquaporin4 dot com

[toc] | [prev] | [next] | [standalone]


#76261

FromStephen Sprunk <stephen@sprunk.org>
Date2015-11-17 12:27 -0600
Message-ID<n2freu$adq$1@dont-email.me>
In reply to#76246
On 17-Nov-15 10:34, Alla _ wrote:
> Please, take a look a the program from K&R tutorial; it has
> descriptive comments, therefore I will skip adding my ones. I would
> be grateful for the help.
> 
> I am not sure I understand how the switch statement works within 
> BuildNextGeneration () function. I read it as:
> 
> if a value at the position array[i][j] is '*', then the program has
> to choose between 3 cases. Given each case in switch statement
> should have a certain value to which the condition is compared, I
> don't understand what 2 or 3 represent:
> 
> if the amount of neighbors, as could be deducted from the comment,
> then how count[i][j] can ever have a value of 2 or 3, if 2 or 3
> represent the number of neighbors and not values at particular
> addresses.

Based on how your question is worded, I suspect you're confusing
array[i][j], which contains a cell's current liveness (a boolean value
with '*' as true and '.' as false), with count[i][j], which contains
that same cell's number of live neighbors (an integer value).  They are
distinct arrays that contain different information.

Personally, I'd have used a single array of struct containing both
liveness and neighbor counts, but if the tutorial hasn't introduced
structs yet, this design is a reasonable alternative.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#76324

FromKeith Thompson <kst-u@mib.org>
Date2015-11-17 15:12 -0800
Message-ID<lnwptgi5kg.fsf@kst-u.example.com>
In reply to#76246
Alla _ <modelling.data@gmail.com> writes:
> Please, take a look a the program from K&R tutorial; it has descriptive 
> comments, therefore I will skip adding my ones. I would be grateful 
> for the help. 
[...]

As discussed in another thread, this tutorial is *not* associated with
the K&R books.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web