Aslai

Conways Game of Life (Commented)

Dec 22nd, 2012
614
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //Getting Windows for console IO and Process for threading
  2. #include <windows.h>
  3. #include<process.h>
  4.  
  5. HANDLE Out,In;
  6.  
  7. char* Buffer[3],Simulating;
  8.  
  9. //Returns the value of the cell at x, y. When bounds are exceeded, it wraps
  10. int GetCell(x,y)
  11. {
  12.     return Buffer[0][(x+80)%20+(y+80)%20*20];
  13. }
  14.  
  15. //Sets the cell at x, y
  16. void SetCell(x,y,l,v)
  17. {
  18.     Buffer[l][(x+80)%20+(y+80)%20*20]=v;
  19. }
  20.  
  21. //Clears the front buffer and flips the back buffer with the front buffer.
  22. void SwapBuffer()
  23. {
  24.     Buffer[2]=Buffer[1];
  25.     Buffer[1]=*Buffer;
  26.     *Buffer=Buffer[2];
  27.     memset(Buffer[1],0,400);
  28. }
  29.  
  30. //The thread that draws the state of the front buffer and enforces the rules of life
  31. void DrawLoop(i,j,k,l,P)
  32. {
  33.     while(1) {
  34.         //Avoids 100% CPU usage. Not totally needed for the golfed version, but it's nice
  35.         Sleep(16);
  36.         //Iterates over the buffer and draws the cells to the console
  37.         for(i=0; i<20; ++i)for(j=0; j<20; ++j) {
  38.             COORD a= {i,j};
  39.             SetConsoleCursorPosition(Out,a);
  40.             putchar(Buffer[0][i+j*20]==1?'0':' ');
  41.         }
  42.         //If we're running...
  43.         if(Simulating){
  44.             //Iterate over all the cells
  45.             for(i=0; i<20; ++i)for(j=0; j<20; ++j) {
  46.                 //This is the meat of the simulation.
  47.                 //This loop finds the sum of the 3x3 square surrounding the current cell
  48.                 for(k=i-1,P=0; k<i+2; ++k)for(l=j-1; l<j+2; ++l) {
  49.                     P+=GetCell(k,l);
  50.                 }
  51.                 //Set the front buffer at i, j to...
  52.                 SetCell(i,j,1,
  53.                         //If there are 2 or 3 neighbors (the sum includes the cell itself, so
  54.                         //it could be 3 neighbors and an empty cell that we're looking at or
  55.                         //2 neighbors and a living cell we're looking at)
  56.                         P==3?
  57.                         //Then it's guaranteed to be a living cell
  58.                             1:
  59.                         //Otherwise, if the cell we're looking at is living and the sum is 4,
  60.                             GetCell(i,j)==1 && P==4?
  61.                         //Then it survives since there are 3 neighbors
  62.                             1:
  63.                         //If there aren't 2 or 3 neighbors, the cell must die.
  64.                             0);
  65.             }
  66.             SwapBuffer();
  67.         }
  68.     }
  69. }
  70.  
  71. int main(T,x,y,LeftClicked,RightClicked)
  72. {
  73.     //Draw the border. Totally unecessary, but it looks nice
  74.     for(x=0; x<21; ++x)puts("#####################");
  75.     //Make the buffer
  76.     *Buffer=malloc(800);
  77.     //The first one was double-allocated because malloc(400); is longer than *E+400;
  78.     Buffer[1]=*Buffer+400;
  79.     //Swap the buffer twice to clear them. I();I(); is smaller than memset(*E,0,800);
  80.     SwapBuffer();
  81.     SwapBuffer();
  82.     //Get the handles to the console. The numeric constants represent -10 and -11 respectively
  83.     In=GetStdHandle(STD_INPUT_HANDLE);
  84.     Out=GetStdHandle(STD_OUTPUT_HANDLE);
  85.     //Enable input with the mouse and keyboard. The ORed numeric constants represent 0x10|0x08,
  86.     //or 24 decimal
  87.     SetConsoleMode(In,ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT );
  88.     INPUT_RECORD R;
  89.     LeftClicked=RightClicked=Simulating=0;
  90.     //Just locks down the console size to eliminate the scrollbar. Technically unecessary.
  91.     COORD size= {80,25};
  92.     SetConsoleScreenBufferSize(Out,size);
  93.     //Start the drawing / simulation thread
  94.     _beginthread(DrawLoop,99,0);
  95.     while(1)
  96.     {
  97.         ReadConsoleInput(In,&R,1,&T);
  98.         switch(R.EventType){
  99.         //Keyboard input. Fetches Caps Lock state
  100.         case 1:
  101.             Simulating=R.Event.KeyEvent.dwControlKeyState&128; break;
  102.         //Mouse input
  103.         case 2:
  104.             switch(R.Event.MouseEvent.dwEventFlags) {
  105.             //Mouse moved
  106.             case 1:
  107.                 x=R.Event.MouseEvent.dwMousePosition.X;
  108.                 y=R.Event.MouseEvent.dwMousePosition.Y;
  109.             //Mouse Clicked. Breaks aren't necessary because the values are always valid, so
  110.             //a fallthrough is totally inconsequential
  111.             case 0:
  112.                 LeftClicked=R.Event.MouseEvent.dwButtonState&1;
  113.                 RightClicked=R.Event.MouseEvent.dwButtonState&2;
  114.             }
  115.             //Turn on the cell at the mouse position
  116.             if(LeftClicked)SetCell(x,y,0,1);
  117.             //And turn it off
  118.             if(RightClicked)SetCell(x,y,0,0);
  119.         }
  120.     }
  121. }
RAW Paste Data