Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / C++

A Fast Version of Conway's Game of Life with Thread and DirectX Draw

Rate me:
Please Sign up or sign in to vote.
4.42/5 (14 votes)
14 Apr 2009CPOL4 min read 57.1K   904   30  
A fast version of Conway's Game of Life with thread and DirectX draw
#define CURSES 0

#include <stdio.h>
#include <stdlib.h>
#if CURSES
#include <curses.h>
#endif
#include "simple.h"


#define LIFE_GRID 20		// Defines the width x height of the arrays used.
//#define N 5		// Defines the number of generations the program should simulate.
int N;
typedef int byte;
#define TRUE  1
#define FALSE 0

#define LASTROW (my_rank == (LIFE_GRID-1))
#define FIRSTROW (my_rank == 0)

void load_init (unsigned int, byte[LIFE_GRID][LIFE_GRID]);
// Function to setup initial generation. 
void step_generation (byte [], int);
// Function to move forward one generation. 
void print_grid (byte [LIFE_GRID][LIFE_GRID]);
// Function to print the array. 
int neighbors ();
// Function to figure the number of neighbors for a given cell. 
void copy_array ();
// Function to copy the contents of one array to another. 
  byte grid[LIFE_GRID][LIFE_GRID];
int main (int argc, char *argv[])
{
  byte *myrow;
//  byte grid[LIFE_GRID][LIFE_GRID];
  int i;
  unsigned int seed;		// Holds the user entered seed for the random number generator. 

  int my_rank, p;

  Init (&argc, &argv);
  my_rank = GetRank ();
  myrow = &grid[my_rank][0];
  p = GetSize ();
  if (p != LIFE_GRID )
  {
    if (my_rank == 0)
    {
      fprintf (stderr, "Wrong number of processes.\nUse -np %d\n", LIFE_GRID );
    }
    Finalize ();
    exit (1);
  }
  if (argc != 3)
  {
    if (my_rank == 0)
    {
      fprintf (stderr,
	"Input number of generations and seed\nUse %s <no.gen.> <seed>\n",
	argv[0]);
    }
    Finalize ();
    exit (2);
  }
  // Get a unsigned int from the user and use it to seed the random number generator. 
  if (0 == my_rank)
  {
    sscanf (argv[1],"%u", &N);
    sscanf (argv[2],"%u", &seed);
    // Print a message to the screen and run load_init to setup the initial generation. 
    printf ("\nGenerating initial grid...\n");
    load_init (seed, grid);
  }
  else
  {
    Recv (INT, myrow, LIFE_GRID, 0);
  }
  Bcast(INT,&N,1,0);
  // Loop to cycle through the different generations. 
  for (i = 1; i <= N; i++)
  {    
    step_generation (myrow, my_rank);	// Call step_generation to generate the next generation. 
    if(my_rank != 0) Send (INT, myrow, LIFE_GRID, 0);
    Barrier();
    if (0==my_rank)
    {
#if CURSES
      sleep(1); 
      move (0, 0);
      printw ("\nGeneration: %i\n\n", i);	// Print the generation number on the screen. 
#else
      printf ("\nGeneration: %i\n\n", i);	// Print the generation number on the screen. 
#endif
      print_grid (grid);		// Call print_grid to display the contents of the array. 
    }
    Barrier();
  }
#if CURSES
  if (0 == my_rank)
  {
    sleep(3);
    endwin();
    printf("\nDone.\n");
  }
#endif
  Finalize ();
  return 0;
}

/*
 *  load_init() is passed the address of an array of characters.  It moves through
 *  each cell in the array, based on a random number provided by the rand() function
 *  it places a * or a space in the given cell of the array.
 */

void load_init (unsigned int seed, byte grid[LIFE_GRID][LIFE_GRID])
{
  int y, x, z;
  byte cell;

  
  srand (seed);
#if CURSES
  initscr();
  printw ("\nGeneration: %i\n\n", 0);	// Print the generation number on the screen. 
#else
  printf ("\nGeneration: %i\n\n", 0);	// Print the generation number on the screen. 
#endif
#if CURSES
  // Print column numbers left to right. 
  printw ("  ");
  for (x = 0; x < LIFE_GRID; x++)
    printw ("%i ", x);
  printw ("\n");
#endif
  for (y = 0; y < LIFE_GRID; y++)
  { 
#if CURSES
    printw ("%i ", y);
#endif
    for (x = 0; x < LIFE_GRID; x++)
    {
      z = (int) (10.0 * rand () / RAND_MAX + 1.0);	// Generates a random number between 0 and 10. 
      if (z < 5)
	grid[y][x] = FALSE;
      else
	grid[y][x] = TRUE;
#if CURSES
      printw("%d ",grid[y][x]); 
#else
      printf("%d ",grid[y][x]);
#endif
    }
    if (y>0) 
    { 
        Send (INT, &grid[y][0], LIFE_GRID, y );
    }
#if CURSES
    printw("\n");
#else
    printf("\n");
#endif
  }
#if CURSES
  refresh();
  sleep(1);
#endif
}

/*
 *  step_generation() is passed the address of an array of characters.  It also sets
 *  up an array of the exact same size as the one whose address was passed.  The
 *  function moves through each cell in the array, calling neighbors() to get
 *  the number of neighbors the current cell has.  Based on the data from neighbors()
 *  and the rules of Life, it either places a * or space in the corresponding cell
 *  of the second array.  Once the function has finished, it calls copy_array() to
 *  copy the contents of the second array into the first array.
 */

void step_generation (byte *myrow, int my_rank)
{
  int x, i;
  byte *prevrow, *nextrow, newrow[LIFE_GRID];
  prevrow = myrow - LIFE_GRID;
  nextrow = myrow + LIFE_GRID;
  if (!FIRSTROW)
  {
//        printf("Process %d sending info to process %d\n",my_rank,my_rank-1);
	Send (INT, myrow, LIFE_GRID, my_rank - 1);
//        printf("Process %d sent info to process %d\n",my_rank,my_rank-1);
	Recv (INT, prevrow, LIFE_GRID, my_rank - 1);
//        printf("Process %d received info from process %d\n",my_rank,my_rank-1);
  }
  if (!LASTROW)
  {
//        printf("Process %d sending info to process %d\n",my_rank,my_rank+1);
	Send (INT, myrow, LIFE_GRID, my_rank + 1);
//        printf("Process %d sent info to process %d\n",my_rank,my_rank+1);        
	Recv (INT, nextrow, LIFE_GRID, my_rank + 1);
//        printf("Process %d received info from process %d\n",my_rank,my_rank+1);
  }
  // now, count the neighbors
  for(i=0; i < LIFE_GRID; i++)
  {
      x = 0;
      if (!FIRSTROW) 
      {
        if(i!=0) x+=prevrow[i-1];
        x+=prevrow[i];
        if(i!=LIFE_GRID-1) x+=prevrow[i+1]; 
      }
      if (!LASTROW) 
      {
        if(i!=0) x+=nextrow[i-1];
        x+=nextrow[i];
        if(i!=LIFE_GRID-1) x+=nextrow[i+1]; 
      }
      if(i!=0) x+=myrow[i-1];
      if(i!=LIFE_GRID-1) x+=myrow[i+1]; 
      if (myrow[i] == TRUE)	// If the cell has an organism in it now. 
      {
	if ((x == 2) || (x == 3))
	  newrow[i] = TRUE;
	else
	  newrow[i] = FALSE;
      }
      else			// If the cell is empty. 
      {
	if (x == 3)
	  newrow[i] = TRUE;
	else
	  newrow[i] = FALSE;
      }
//      printf("%d, %d, %d, %d\n", my_rank, i, x, newrow[i]);
  }
  for(i=0; i < LIFE_GRID; i++) myrow[i] = newrow[i];
}

/*
 *	print_grid() is passed the address of an array of characters.  It moves through this
 *	array printing each character to the display.  It also prints cell numbers across the
 *	top, and along the left side of the output.
 */

void print_grid (byte grid[LIFE_GRID][LIFE_GRID])
{
  int y, x;
  byte cell;
#if CURSES
#define PRINT printw
#else
#define PRINT printf
#endif
  // Print column numbers left to right. 
  PRINT ("  ");
  for (x = 0; x < LIFE_GRID; x++)
    PRINT ("%i ", x);
  PRINT ("\n");

  // Print a row number and the contens of that row. 
  for (y = 0; y < LIFE_GRID; y++)
  {
    PRINT ("%i ", y);
    if (y > 0) Recv (INT, &grid[y][0],LIFE_GRID, y);
    for (x = 0; x < LIFE_GRID; x++)
    {
      if (grid[y][x] == TRUE)
	PRINT ("* ");
      else
	PRINT ("  ");
    }
    PRINT ("\n");
  }
#if CURSES
  refresh();
#endif
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder SmartTick Software Inc.
Canada Canada
Jerry Jiang(BOLIANG JIANG)

A passionate software developer since 1992

Education:Master of Computer Science.

jerry@smarttick.com

Comments and Discussions