Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Getting Windows for console IO and Process for threading
- #include <windows.h>
- #include<process.h>
- HANDLE Out,In;
- char* Buffer[3],Simulating;
- //Returns the value of the cell at x, y. When bounds are exceeded, it wraps
- int GetCell(x,y)
- {
- return Buffer[0][(x+80)%20+(y+80)%20*20];
- }
- //Sets the cell at x, y
- void SetCell(x,y,l,v)
- {
- Buffer[l][(x+80)%20+(y+80)%20*20]=v;
- }
- //Clears the front buffer and flips the back buffer with the front buffer.
- void SwapBuffer()
- {
- Buffer[2]=Buffer[1];
- Buffer[1]=*Buffer;
- *Buffer=Buffer[2];
- memset(Buffer[1],0,400);
- }
- //The thread that draws the state of the front buffer and enforces the rules of life
- void DrawLoop(i,j,k,l,P)
- {
- while(1) {
- //Avoids 100% CPU usage. Not totally needed for the golfed version, but it's nice
- Sleep(16);
- //Iterates over the buffer and draws the cells to the console
- for(i=0; i<20; ++i)for(j=0; j<20; ++j) {
- COORD a= {i,j};
- SetConsoleCursorPosition(Out,a);
- putchar(Buffer[0][i+j*20]==1?'0':' ');
- }
- //If we're running...
- if(Simulating){
- //Iterate over all the cells
- for(i=0; i<20; ++i)for(j=0; j<20; ++j) {
- //This is the meat of the simulation.
- //This loop finds the sum of the 3x3 square surrounding the current cell
- for(k=i-1,P=0; k<i+2; ++k)for(l=j-1; l<j+2; ++l) {
- P+=GetCell(k,l);
- }
- //Set the front buffer at i, j to...
- SetCell(i,j,1,
- //If there are 2 or 3 neighbors (the sum includes the cell itself, so
- //it could be 3 neighbors and an empty cell that we're looking at or
- //2 neighbors and a living cell we're looking at)
- P==3?
- //Then it's guaranteed to be a living cell
- 1:
- //Otherwise, if the cell we're looking at is living and the sum is 4,
- GetCell(i,j)==1 && P==4?
- //Then it survives since there are 3 neighbors
- 1:
- //If there aren't 2 or 3 neighbors, the cell must die.
- 0);
- }
- SwapBuffer();
- }
- }
- }
- int main(T,x,y,LeftClicked,RightClicked)
- {
- //Draw the border. Totally unecessary, but it looks nice
- for(x=0; x<21; ++x)puts("#####################");
- //Make the buffer
- *Buffer=malloc(800);
- //The first one was double-allocated because malloc(400); is longer than *E+400;
- Buffer[1]=*Buffer+400;
- //Swap the buffer twice to clear them. I();I(); is smaller than memset(*E,0,800);
- SwapBuffer();
- SwapBuffer();
- //Get the handles to the console. The numeric constants represent -10 and -11 respectively
- In=GetStdHandle(STD_INPUT_HANDLE);
- Out=GetStdHandle(STD_OUTPUT_HANDLE);
- //Enable input with the mouse and keyboard. The ORed numeric constants represent 0x10|0x08,
- //or 24 decimal
- SetConsoleMode(In,ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT );
- INPUT_RECORD R;
- LeftClicked=RightClicked=Simulating=0;
- //Just locks down the console size to eliminate the scrollbar. Technically unecessary.
- COORD size= {80,25};
- SetConsoleScreenBufferSize(Out,size);
- //Start the drawing / simulation thread
- _beginthread(DrawLoop,99,0);
- while(1)
- {
- ReadConsoleInput(In,&R,1,&T);
- switch(R.EventType){
- //Keyboard input. Fetches Caps Lock state
- case 1:
- Simulating=R.Event.KeyEvent.dwControlKeyState&128; break;
- //Mouse input
- case 2:
- switch(R.Event.MouseEvent.dwEventFlags) {
- //Mouse moved
- case 1:
- x=R.Event.MouseEvent.dwMousePosition.X;
- y=R.Event.MouseEvent.dwMousePosition.Y;
- //Mouse Clicked. Breaks aren't necessary because the values are always valid, so
- //a fallthrough is totally inconsequential
- case 0:
- LeftClicked=R.Event.MouseEvent.dwButtonState&1;
- RightClicked=R.Event.MouseEvent.dwButtonState&2;
- }
- //Turn on the cell at the mouse position
- if(LeftClicked)SetCell(x,y,0,1);
- //And turn it off
- if(RightClicked)SetCell(x,y,0,0);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement