Like Tree2Likes

use of rand() for number generation

This is a discussion on use of rand() for number generation within the C Programming forums, part of the General Programming Boards category; I have recently finished coding a random walks type program. In order to generate the randomness I used a time-seeded ...

  1. #1
    Registered User
    Join Date
    Jun 2012
    Posts
    39

    use of rand() for number generation

    I have recently finished coding a random walks type program. In order to generate the randomness I used a time-seeded call of rand(). Now for the most part this seems to work fine, but every so often a loop of mine seems to be caught in what is almost an infinite loop. Is it normal for a loop containing rand() to take so long to generate a restricted random integer? Here is my code....


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main(void){
    int Horiz=0,Vert=0,BoolWplane[10][10],  pointset=0, initpointh=0, initpointv=0, j=0, blockwall[4], right=0, up=0, sum=0;
     char Walkplane[10][10],walkpos='A';
    int direcprim=0;
    
    for(Horiz=0;Horiz<10;Horiz++){
             for(Vert=0;Vert<10;Vert++){
                                       Walkplane[Horiz][Vert]='.';
                                       BoolWplane[Horiz][Vert]=0;
                                                    }
                                                }
    
    srand((unsigned) time(NULL));
    
     while(pointset!=1){
                                if(j==0){
                                       initpointh=rand()%10;
                                       initpointv=rand()%10;
                                       j++;
                                            }
                                if(((initpointh!=0)&&(initpointh!=9))||((initpointv!=0)&&(initpointv!=9)))
                            j--;
                                else
                                   pointset=1;
                               }
    
    Horiz=initpointh;
    Vert=initpointv;
    BoolWplane[Horiz][Vert]=1;
    Walkplane[Horiz][Vert]=walkpos;
    initpointv=0;
    
     while(walkpos<='Y'&&sum!=4){ 
                                                  for(initpointh=0;initpointh<4;initpointh++)
                                                         blockwall[initpointh]=0;
                                                                               
                                                   start:  if(initpointv>0){
                                                                                  blockwall[direcprim]=1;
                                                                                  sum=0;              
                                                                                  }
                                                             up=0;
                                                             right=0;
                                                             direcprim=rand()/(RAND_MAX/5);
                       
                                                             switch(direcprim){
                                                                                       case 0: up++;
                                                                                                   break;
                                                                                       case 1: up--;
                                                                                                   break;
                                                                                       case 2: right++;
                                                                                                   break;
                                                                                       case 3: right--;
                                                                                                   break;
                                                                                        }
                            
          if(((Horiz+right)>9)||((Horiz+right)<0)||((Vert+up)<0)||((Vert+up)>9)){
                                                                                                        continue;
                                                                                                        }
                
                    if(BoolWplane[Horiz+right][Vert+up]==1){               
                                                                               blockwall[direcprim]=1;                            
                                                                               for(initpointh=0;initpointh<4;initpointh++){
                                                                                                                                           if(blockwall[initpointh]==1){
                                                                                                                                                                                 sum++; 
                                                                                                                                                                                 }
                                                                                                                                           }
                                                                               if(sum==4)
                                                                                              {
                                                                                               printf("sum is 4\n");
                                                                                               continue;
                                                                                               }                              
                                                                               else
                                                                                  goto start;
                                                                            }
                                                              
                                  Horiz=Horiz+right;
                                  Vert=Vert+up;                                              
                                  BoolWplane[Horiz][Vert]=1;
                                  Walkplane[Horiz][Vert]=++walkpos;
                                  initpointv++;
      }
    
    for(Horiz=0;Horiz<10;Horiz++){
                  for(Vert=0;Vert<10;Vert++){
                                                          printf(" %c",Walkplane[Horiz][Vert]);
                                                        }
                    printf("\n");
                                                 }
    
    return 0;
    }
    Last edited by Codegeek892; 07-01-2012 at 03:46 PM.

  2. #2
    Registered User
    Join Date
    Jun 2012
    Posts
    39
    Just realized my indentation sucks. Give me a minute and I will fix it.

  3. #3
    Registered User
    Join Date
    Jun 2012
    Posts
    39
    Alright. I've been working on it, but for some reason I can't get all of the empty space out of my indentation. I've tried to set it the best way that I can.

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    2,778
    Reformatted your code. saw no warnings when compiling it.

    Edit: I have never did this type of problem and have no desire to find the bug in your code.
    I just reformatted your code; so, someone else might help you.

    Edit2: If your code has a bug; it would be possible for sum to equal 5 and your code would run a long time before it stops.

    Tim S.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main(void)
    {
    	int Horiz=0,Vert=0,BoolWplane[10][10],pointset=0, initpointh=0, initpointv=0, j=0,blockwall[4], right=0, up=0, sum=0;
    	char Walkplane[10][10],walkpos='A';
    	int direcprim=0;
    
    	for(Horiz=0; Horiz<10; Horiz++)
    	{
    		for(Vert=0; Vert<10; Vert++)
    		{
    			Walkplane[Horiz][Vert]='.';
    			BoolWplane[Horiz][Vert]=0;
    		}
    	}
    
    	srand((unsigned) time(NULL));
    
    	while(pointset!=1)
    	{
    		if(j==0)
    		{
    			initpointh=rand()%10;
    			initpointv=rand()%10;
    			j++;
    		}
    		if(((initpointh!=0)&&(initpointh!=9))||((initpointv!=0)&&(initpointv!=9)))
    			j--;
    		else
    			pointset=1;
    	}
    
    	Horiz=initpointh;
    	Vert=initpointv;
    	BoolWplane[Horiz][Vert]=1;
    	Walkplane[Horiz][Vert]=walkpos;
    	initpointv=0;
    
    	while(walkpos<='Y'&&sum!=4)
    	{
    		for(initpointh=0; initpointh<4; initpointh++)
    			blockwall[initpointh]=0;
    
    start:
    		if(initpointv>0)
    		{
    			blockwall[direcprim]=1;
    			sum=0;
    		}
    		up=0;
    		right=0;
    		direcprim=rand()/(RAND_MAX/5);
    
    		switch(direcprim)
    		{
    		case 0:
    			up++;
    			break;
    		case 1:
    			up--;
    			break;
    		case 2:
    			right++;
    			break;
    		case 3:
    			right--;
    			break;
    		}
    
    		if(((Horiz+right)>9)||((Horiz+right)<0)||((Vert+up)<0)||((Vert+up)>9))
    		{
    			continue;
    		}
    
    		if(BoolWplane[Horiz+right][Vert+up]==1)
    		{
    			blockwall[direcprim]=1;
    			for(initpointh=0; initpointh<4; initpointh++)
    			{
    				if(blockwall[initpointh]==1)
    				{
    					sum++;
    				}
    			}
    			if(sum==4)
    			{
    				printf("sum is 4\n");
    				continue;
    			}
    			else
    				goto start;
    		}
    
    		Horiz=Horiz+right;
    		Vert=Vert+up;
    		BoolWplane[Horiz][Vert]=1;
    		Walkplane[Horiz][Vert]=++walkpos;
    		initpointv++;
    	}
    
    	for(Horiz=0; Horiz<10; Horiz++)
    	{
    		for(Vert=0; Vert<10; Vert++)
    		{
    			printf(" %c",Walkplane[Horiz][Vert]);
    		}
    		printf("\n");
    	}
    
    	return 0;
    }
    Last edited by stahta01; 07-01-2012 at 04:54 PM.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    2,778
    Using the debugger; I found that the line below returns the values 0 to 4.

    But, the switch block does nothing with the value 4. This seems wrong to me.

    Tim S.

    Code:
    direcprim=rand()/(RAND_MAX/5);
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    This is kind of funky
    Code:
    	while(pointset!=1)
    	{
    		if(j==0)
    		{
    			initpointh=rand()%10;
    			initpointv=rand()%10;
    			j++;
    		}
    		if(((initpointh!=0)&&(initpointh!=9))||((initpointv!=0)&&(initpointv!=9)))
    			j--;
    		else
    			pointset=1;
    	}
    As far as I can tell, it's just doing this:
    Code:
    // pick random corner
        initpointh = rand() % 2  ?  0 : 9;
        initpointv = rand() % 2  ?  0 : 9;
    Can you describe, in words, exactly what your program is supposed to do?

    Also, why is there a Walkplane and a BoolWplane? What is blockwall for? What is sum for? What is walkpos and why does it go from 'A' to 'Y'?
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Registered User
    Join Date
    Jun 2012
    Posts
    39
    @stahta01 Thank you for all of your help. I will save the formatted version for future reference on formatting my code for others to read. Also I did not catch the "/5" mistake. I believe that may have been giving me the bug that was causing the infinite loop like behavior. I have put /4 instead to limit the range from 0 to 3. Also may change it to sum<4 instead of sum!=4 to guarantee a break out of the loop in any case.

    @oogabooga The program is supposed to generate a random path through a 10X10 array marking the path with the letters A through Z as it goes. You are not allowed to out of bounds of the array or allowed to visit any space you have already crossed. If no space is left to move, you must stop the path generation. The code you referenced was supposed to create a random initial point along the edge for the start of the path. I have since changed the middle "or" to an "and" to get the desired result.

    The Walkplane array acts to actually have a display for the path. I used the BoolWplane array to act as a record keeper of where the path had already been. The walkpos variable is the actual representation of the current letter being held. Thus if successful, the path actually ends on Z and not Y. Sum is to check if all four spaces around the current position are unavailable.

    I left a lot of my comments out as to overburden my code on here for those reading it.

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Codegeek892 View Post
    The Walkplane array acts to actually have a display for the path. I used the BoolWplane array to act as a record keeper of where the path had already been.
    You don't need two arrays. Since you initialize all cells in Walkplane with ".", you know whether a cell is free or not.

    The rest is imho very hard to follow and too complicated. Since this exercise is also in the book "C Programming: A modern approach" I did it a few weeks ago and my solution of the main part (the while-loop in your program) consists of a comparable switch-statement and 5 if-statements inside a simple for-loop (going through all letters) - all in all about 25 lines.

    Bye, Andreas

  9. #9
    Registered User
    Join Date
    Jun 2012
    Posts
    39
    I am using the same book to teach myself C. Is there anyway I could get a look at the code you wrote as I have NO idea how you did this in less than thirty lines?

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    The trick is to check which of the 4 neighbour cells are available for the current position and then choose randomly one of them. If all 4 neighbours are already taken, break out of the loop.

    Code:
    /* project 8.9 */
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main(void)
    {
        char grid[10][10];
        char directions[3];
        int x, y, direction, len;
        char c;
    
        srand((unsigned) time(NULL));
    
        for (y = 0; y < 10; y++)
            for (x = 0; x < 10; x++)
                grid[y][x] = '.';
        
        /* This always starts at the upper left corner, but you can easily
            change the start to a random position */
        grid[0][0] = 'A';
        x = y = 0;
    
        for (c = 'B'; c <= 'Z'; c++)
        {
            len = 0;
            if (((x - 1) >= 0) && (grid[y][x - 1] == '.'))  // left neighbour cell
                directions[len++] = 'l';
            if (((y - 1) >= 0) && (grid[y - 1][x] == '.'))  // upper neighbour cell
                directions[len++] = 'u';
            if (((y + 1) < 10) && (grid[y + 1][x] == '.'))  // lower neighbour cell  
                directions[len++] = 'd';
            if (((x + 1) < 10) && (grid[y][x + 1] == '.'))  // right neigbour cell
                directions[len++] = 'r';
           
            if (len == 0)     // no neighbour cell left -> we're are stuck
                break;
           
            direction = rand() % len;
            switch (directions[direction])
            {
                case 'u':  grid[--y][x] = c;
                           break;
                case 'd':  grid[++y][x] = c;
                           break;
                case 'l':  grid[y][--x] = c;
                           break;
                case 'r':  grid[y][++x] = c;
                           break;
            }
        }
    
        for (y = 0; y < 10; y++)
        {
            for (x = 0; x < 10; x++)
                printf("%c ", grid[y][x]);
            printf("\n");
        }
    
        return 0;
    }
    Bye, Andreas

  11. #11
    Registered User
    Join Date
    Jun 2012
    Posts
    39
    @AndiPersti

    Thank you for the code. Using your code as an inspiration I modified my code slightly to be a little less bulky. Can you tell me what you think?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main(void)
    {
      int H,V,direction,dvert=0,dhoriz=0,blocked[4],count=0,j=0;
      char Walkplane[10][10],position;
    
     printf("*****Random Walks v2.01*****\n");
    
     for(j=0;j<4;j++)/*array is for checking allowed directions*/
       blocked[j]=0;
    
     for(H=0;H<10;H++){
       for(V=0;V<10;V++){
         Walkplane[H][V]='.';
       }
     }
     
     position='A';/*Variable to hold current letter*/
     H=0;/*Horizontal*/
     V=0;/*vertical*/
     Walkplane[H][V]=position;
    
      srand((unsigned) time(NULL));
    
      while(position<90){ 
       count=0;
       dhoriz=0;
       dvert=0;
      
       direction=rand()%4;
       
       switch(direction){/*direction choosing*/
       case 0: dhoriz++;
               break;
       case 1: dhoriz--;
               break;
       case 2: dvert++;
               break;
       case 3: dvert--;
               break;
                         }
    
      if(!((((H+dhoriz)<=9)&&((H+dhoriz)>=0)&&((V+dvert)>=0)&&((V+dvert)<=9))&&(Walkplane[H+dhoriz][V+dvert]=='.')))
           blocked[direction]=1;
    
      if(blocked[direction]==1){
        for(j=0;j<4;j++){
          if(blocked[j]==1)
            count++;
                       }
        if(count==4)
          break;
        else
          continue;
      }
       
     H=H+dhoriz;
     V=V+dvert;
     Walkplane[H][V]=++position;
    
     for(j=0;j<4;j++)/*array clears every time a successful step through the path is made. thus each step looks at the slots around it as new*/
       blocked[j]=0;
     }
    
      for(H=0;H<10;H++){
       for(V=0;V<10;V++){
         printf(" %c", Walkplane[H][V]);
       }
       printf("\n");
     }
    
     return 0;
    }
    It also has occured to me to use H and V to increment directions in my switch statement. But I wanted to refine my code while still remaining close to the original idea (your code helped me out tremendously in this).
    Last edited by Codegeek892; 07-03-2012 at 05:18 AM.

  12. #12
    Registered User
    Join Date
    Oct 2011
    Posts
    890
    If you want to start at a random position at the edge of the grid:

    There are 2*(width - 1) + 2*(height - 1) cells at the edge of a rectangular width height grid. Remember the corners; don't count them twice. For a 1010 grid, this means you have 36 cells to pick from. In other words:
    Code:
    n = rand() % (2*width + 2*height - 4);
    if (n < width) {
        x = n;
        y = 0;
    } else
    if (n < width + height - 1) {
        x = width - 1;
        y = n - (width - 1);
    } else
    if (n < 2*width + height - 3) {
        x = 2*width + height - 3 - n;
        y = height - 1;
    } else {
        x = 0;
        y = 2*width + 2*height - 4 - n;
    }
    Also, the rand() function provided by standard C libraries is a terribly bad random number generator. It is typically a linear congruential pseudorandom number generator with a relatively short period, and is known to cause problems due to its periodicity.

    Instead, I recommend using the Xorshift algorithm. It is simple, fast, and has 128 bits of state you can initialize however you want (as long as it is not all zeros). For brevity, here is the Wikipedia example implementation slightly rewritten to make seeding possible:
    Code:
    #include <stdint.h>
    
    static uint32_t prng_state[4] = {
        123456789U, 
        362436069U,
        521288629U,
        88675123U
    };
    
    static inline uint32_t prng_u32(void)
    {
        uint32_t  temp;
        temp = prng_state[0] ^ (prng_state[0] << 11U);
        prng_state[0] = prng_state[1];
        prng_state[1] = prng_state[2];
        prng_state[2] = prng_state[3];
        return prng_state[3] = prng_state[3] ^ (prng_state[3] >> 19U) ^ temp ^ (temp >> 8U); 
    }
    In Linux, I recommend simply reading sizeof prng_state bytes from /dev/urandom, until at least one of the values is nonzero. This should yield a very reliably random seed.

    While one can pretty safely use prng_u32()%range to generate a pseudorandom number between 0 and range-1 inclusive, there is a very slight bias towards lower values depending on the range unless it is a power of two. The bias is just ((1<<32) % range) / (1<<32); it only becomes significant for large ranges. For example, at range = 16777217, you get 0.39% more often zeros than you get 16777215.

    Like I said, that does not affect most applications, definitely not a random walker such as discussed in this thread.

    In almost all applications, a small bias towards lower values should not affect anything; it should be within the noise of the distribution anyway. However, if you do statistics or Monte Carlo stuff, you really need a uniform distribution. Then, I recommend tacking on a simple exclusion method:
    Code:
    static uint32_t prng_bitmask(uint32_t range)
    {
        range |= range >> 16U;
        range |= range >> 8U;
        range |= range >> 4U;
        range |= range >> 2U;
        range |= range >> 1U;
        return range;
    }
    
    /* Generate a uniform pseudorandom integer [min, max),
     * or [max, min) if max < min. If max == min, always returns min.
     *
     * Note: This is limited to 32-bit range, i.e. |max - min| <= 4294967295.
    */
    int prng_int(const int min, const int max)
    {
        if (min < max) {
            const uint32_t  range = (uint32_t)(max - min);
            const uint32_t  mask = prng_bitmask(range);
            uint32_t        value;
    
            do {
                value = prng_u32() & mask;
            } while (value >= range);
    
            return min + (int)value;
        } else
        if (max < min) {
            const uint32_t  range = (uint32_t)(min - max);
            const uint32_t  mask = bitmask(range);
            uint32_t        value;
    
            do {
                value = prng_u32() & mask;
            } while (value >= range);
    
            return max + (int)value;
        } else
            return min;
    }
    It is good for the full 32-bit integer range, and max and min can be specified in any order. The helper function generates a bit mask of the bits needed to represent any value within the range (shifted to start from zero; all low bits set, all high bits clear); equal or larger than the maximum value within the range.

    The loop generates an unsigned random number with those bits only, until it gets a value that fits within the range. Since the bitmask is never larger than twice the range, the loops exclude at most half the values on average. If you bother to test it, it is still extremely fast, in many cases still faster than the standard C library rand() function.

    For those who are interested in pseudorandom number generation, the exclusion method does not guarantee an uniform distribution; it only guarantees an uniform distribution when the original pseudorandom number generator generates an uniform distribution with a known number of bits (thus its range must be a power of two). Xorshift does pass the Diehard tests, so I'd trust it when using statistics or Monte Carlo methods.
    Last edited by Nominal Animal; 07-03-2012 at 08:37 AM. Reason: Fixed the comment in the last code snippet.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,308
    Quote Originally Posted by Nominal Animal
    It is good for the full 32-bit integer range, and max and min can be specified in any order. The helper function generates a bit mask of the bits needed to represent any value within the range (shifted to start from zero; all low bits set, all high bits clear); equal or larger than the maximum value within the range.
    I think you made a small typographical error on this line:
    Code:
    const uint32_t  mask = bitmask(range);
    It looks like bitmask should be prng_bitmask.

    Quote Originally Posted by Nominal Animal
    The loop generates an unsigned random number with those bits only, until it gets a value that fits within the range. Since the bitmask is never larger than twice the range, the loops exclude at most half the values on average. If you bother to test it, it is still extremely fast, in many cases still faster than the standard C library rand() function.
    Your exclusion method implementation looks interesting. The version that I am familiar with computes the largest possible range that won't cause bias to be introduced and then rejects numbers generated outside this range. Using rand(), it is something like:
    Code:
    range = max - min;
    range = (RAND_MAX / range) * range;
    do
    {
        value = rand();
    }
    while (value >= range);
    value %= range;
    return min + value;
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Oct 2011
    Posts
    890
    Quote Originally Posted by laserlight View Post
    I think you made a small typographical error on this line:
    Code:
    const uint32_t  mask = bitmask(range);
    It looks like bitmask should be prng_bitmask.
    Correct, it should be prng_bitmask(range). I added the prng_ prefix to some test code I had lying around, just to keep the namespace clean, and missed one spot. Apologies. And thanks for catching it!

    Quote Originally Posted by laserlight View Post
    Your exclusion method implementation looks interesting. The version that I am familiar with computes the largest possible range that won't cause bias to be introduced and then rejects numbers generated outside this range.
    Your method should have a much smaller rejection ratio on average, but it does require a division (or modulus) operation, which tends to be very slow compared to the other operations, especially on embedded architectures. The bit-based one is trivially extensible to 64-bit and larger integers -- especially useful when generating uniform floating-point numbers.

    I suspect, but have not benchmarked, that the bit-based one is faster. I personally use a variant where a structure contains the range, mask, and minimum values, and is set using a different function. For xorshift, you can put the generator state there too (but take care how you derive the seeds then). A helper function takes just the structure, and poops out a suitable pseudorandom number whenever called. As the helper function is just a rejection loop with Xorshift, it tends to be extremely fast -- and like I said earlier, it does pass the Diehard tests.

    For others who might be wondering, the idea is to first move the range so it starts from zero, then create a bit mask which covers the range (all low bits set, all high bits zero). Then you can trivially generate a number with just enough random bits. If the range is not a power of two, the random values with highest bit set may be too large; the too large values are rejected. If the range is just one value over a power of two, then up to just under half the generated numbers are rejected on average. The closer the range is to the next full power of two, the fewer generated numbers get rejected on average; the 50% is just the worst case.

    Quote Originally Posted by laserlight View Post
    Code:
    range = (RAND_MAX / range) * range;
    Do you have optimization issues with that (with older C compilers)? You could always use
    Code:
    if (RAND_MAX % range)
        range -= RAND_MAX % range;
    which at least on GCC-4.6.3 compiles to slightly faster code on x86-64 and x86, trading one imull for a movl and a subl. GCC-4.6.3 does compile your code correctly even with very aggressive optimization, I just don't remember the exact ANSI C or C89 rules wrt. optimization.

    Using the C99 casting rules, where the division in
    Code:
    range = (int)(RAND_MAX / range) * range;
    is guaranteed to be computed at int precision. However, I believe that on all architectures that have a division operation that returns both the result and the quotient, the modulus version is slightly faster, as it trades the multiplication for a subtraction, and most architectures I have are that way. Xorshift itself is such a fast algorithm that if you generate lots and lots of random numbers, the timings do start piling up. They certainly do if you do Monte Carlo stuff.

  15. #15
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Codegeek892 View Post
    Can you tell me what you think?
    Sure :-) (but remember the following are just my humble opinions)

    Code:
    for(j=0;j<4;j++)/*array is for checking allowed directions*/
        blocked[j]=0;
    Since this initialization is right at the beginning you could also initialize the array at the declaration:
    Code:
    int blocked[4] = { 0 };
    Code:
    position='A';/*Variable to hold current letter*/
    Wouldn't "letter" or "current_letter" be a better name for this variable? Then you wouldn't need the comment because the name would be self-explanatory.

    Code:
    if(!((((H+dhoriz)<=9)&&((H+dhoriz)>=0)&&((V+dvert)>=0)&&((V+dvert)<=9))&&(Walkplane[H+dhoriz][V+dvert]=='.')))
       blocked[direction]=1;
    
    if(blocked[direction]==1){
        for(j=0;j<4;j++){
            if(blocked[j]==1)
                count++;
            }
        if(count==4)
          break;
        else
          continue;
    }
    Firstly, I would rewrite the monster if-statement to get rid of the negation (positively written logical expressions are usually easier to understand then negatively ones thus I always seek to avoid a negation if possible). I would also add some white-space for better readability.

    Secondly, you don't need the second if-statement because you know already from the first one if the current direction is possible. Thus you can move everything into the body of the first if. And you can also get rid of the for-loop if you only increment count when blocked[direction] wasn't 1 before.

    Thirdly, you can move the rest of the while-loop (which gets executed only when the direction is valid) into the else body of the monster if-statement and thus get rid of the continue-statement:
    Code:
    if(((H + dhoriz) > 9) || ((H + dhoriz) < 0) || 
       ((V + dvert) > 9) || ((V + dvert) < 0) ||
       (Walkplane[H + dhoriz][V + dvert] != '.'))
    {
       if (blocked[direction] == 0)
       {
           blocked[direction] = 1;
           count++;
       }
       if (count == 4)
           break;
    }
    else
    {
        H=H+dhoriz;
        V=V+dvert;
        Walkplane[H][V]=++position;
        count=0;   // moved from the beginning of the while-loop!
        for(j=0;j<4;j++)/*array clears every time a successful step through the path is made. thus each step looks at the slots around it as new*/
             blocked[j]=0;
    }
    Generally I like to use much whitespace - that's a clear sign that I'm coming from Python :-)
    Instead of
    Code:
    for(H=0;H<10;H++);
    I write
    Code:
    for (H = 0; H < 10; H++);
    but that's a style question and thus debatable :-).

    Bye, Andreas
    Last edited by AndiPersti; 07-03-2012 at 04:04 PM.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 10-05-2009, 11:21 AM
  2. Random number generation
    By parisha in forum C Programming
    Replies: 9
    Last Post: 12-17-2008, 11:00 AM
  3. Help with number generation
    By d-dub in forum C++ Programming
    Replies: 6
    Last Post: 11-23-2006, 10:12 AM
  4. Random number generation
    By Lisa Mowbray in forum C++ Programming
    Replies: 4
    Last Post: 04-30-2002, 01:22 PM
  5. Random Number Generation
    By Unregistered in forum Game Programming
    Replies: 1
    Last Post: 11-21-2001, 04:29 AM

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