Tell me more ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Conway's Game of Life is the classic example of cellular automation.

Your mission, should you choose to accept it, is to code the shortest Game of Life implementation in your favourite language.

The rules:

  • The grid must be at least 20x20
  • The grid must wrap around (so the grid is like the surface of a Torus)
  • Your implementation must allow the user to input their own starting patterns - the easier you make this, the higher you score.
  • GoL is a bit pointless if you can't see what is happening, so there must be visual output of the automation running!

That's it.

I will pick the winner from the three highest-voted answers, I will base the winning answer on code length, running speed, ease of input and 'flashyness'

So you know I haven't been lazy, here is my effort (click cells for input, double click off-grid to run/stop) - only tested on chrome, UI bugs for maximum golf-age!

JavaScript 1688 819 741 728* 678 Chars!

b=[],r=c=s=20,U=document;onload=function(){for(z=E=0;z<c;++z){b.push(t=[]);for(j=0;j<r;j++)with(U.body.appendChild(U.createElement("button")))t.push(0),id=z+"_"+j,style.position="absolute",style.left=s*j+"px",style.top=s*z+"px",onclick=N}};ondblclick=function(){A=E=!E?setInterval(function(){Q=[];for(z=0;z<c;++z){R=[];for(j=0;j<r;)W=(c+z-1)%c,X=(c+z+1)%c,Y=(r+j-1)%r,Z=(r+j+1)%r,n=b[W][Y]+b[z][Y]+b[X][Y]+b[W][j]+b[X][j]+b[W][Z]+b[z][Z]+b[X][Z],R.push(b[z][j++]?n<4&&n>1:n==3);Q.push(R)}b=Q.slice();$()}):clearInterval(A)};function N(a){E?0:P=a.target.id.split("_"),b[P[0]][P[1]]^=1,$()}function $(){for(z=0;z<c;++z)for(j=0;j<r;)U.getElementById(z+"_"+j).innerHTML=b[z][j++]-0}

Ungolfed version

*thanks to migimaru

share|improve this question
2  
Previously on Stack Overflow: Code Golf: Conway's Game of Life, and be sure to look at the APL implementation link in the comments. – dmckee Aug 14 '11 at 3:07
Ah, I did not see that. But this is slightly different no (save me deleting the work putting the challenge together? – Griffin Aug 14 '11 at 3:15
1  
It's not a problem. Many puzzles already run on Stack Overflow have been done here too, but people will tell you that I am obsessive about linking to similar challenges. – dmckee Aug 14 '11 at 3:17
@Griffin: You can remove all those ; before }s. Also vars can be eliminated at times (if it doesn't break your code). And for one-line fors, ifs etc, you can eliminate the { } completely: for(...) for(...) dosomething(). – pimvdb Aug 14 '11 at 14:21
@pimvdb, cheers, I haven't fully golfed it yet, haven't had the time. just wanted to show that I had a go too, rather than idly setting a challenge. Will golf it to the max soon. – Griffin Aug 14 '11 at 17:53
show 8 more comments

12 Answers

up vote 12 down vote accepted

HTML5 Canvas with JavaScript, 940 639 586 519 characters

<html><body onload="k=40;g=10;b=[];setInterval(function(){c=[];for(y=k*k;y--;){n=0;for(f=9;f--;)n+=b[(~~(y/k)+k+f%3-1)%k*k+(y+k+~~(f/3)-1)%k];c[y]=n==3||n-b[y]==3;r.fillStyle=b[y]?'red':'tan';r.fillRect(y%k*g,~~(y/k)*g,g-1,g-1)}if(v.nextSibling.checked)b=c},1);v=document.body.firstChild;v.width=v.height=g*k;v.addEventListener('click',function(e){b[~~((e.pageY-v.offsetTop)/g)*k+~~((e.pageX-v.offsetLeft)/g)]^=1},0);r=v.getContext('2d');for(y=k*k;y--;)b[y]=0"><canvas></canvas><input type="checkbox"/>Run</body></html>

I always wanted to do something with canvas, so here is my attempt (original version online). You can toggle cells by clicking (also possible in running mode).

You can now also try the new version here.

Unfortunately there is an issue I couldn't work around yet. The online version is 11 characters longer because jsFiddle puts a text node just before the canvas (why?) and thus the canvas is no longer the first child.

Edit 1: Lots of optimisations and restructurings.

Edit 2: Several smaller changes.

Edit 3: Inlined the complete script block plus minor changes.

share|improve this answer
Nice, but change the interval delay to 1 makes it as fast as mine rather than that slow stepping. Also if you want to implement drawing (rather than clicking on each square) you can round the mouse position to the nearest blocksize and fill the rectangle at that point. More characters but more points. – Griffin Aug 15 '11 at 0:32
You can replace new Array('#FFF','#800') with ['#FFF','#800']. – Lowjacker Aug 15 '11 at 15:59
Though saying that about drawing, my super-golfed doesn't allow drawing and is ugly as sin. Haha. You can set your two colours in the s array to tan and red since they are the two colours with the shortest representations - saves you two chars. Also, if possible, put the literal version of j into the interval. I'm sure there's lots more to squeeze out too. – Griffin Aug 19 '11 at 14:46
@Griffin and Lowjacker: thank you very much. I am also pretty sure that you can golf this much more (and have already some ideas). Unfortunately I didn't find the time to do so. A better golfed version will follow tomorrow - I hope... – Howard Aug 19 '11 at 15:07
@Howard Just tried your new version in jsFiddle and it seems to have a mismatched brace somewhere, so it won't run. – Gareth Aug 20 '11 at 10:16
show 4 more comments

Python, 219 chars

I went for maximum golfage, with just enough interface to satisfy the question.

import time
P=input()
N=range(20)
while 1:
 for i in N:print''.join(' *'[i*20+j in P]for j in N)
 time.sleep(.1);Q=[(p+d)%400 for d in(-21,-20,-19,-1,1,19,20,21)for p in P];P=set(p for p in Q if 2-(p in P)<Q.count(p)<4)

You run it like this:

echo "[8,29,47,48,49]" | ./life.py

The numbers in the list represent the coordinates of the starting cells. The first row is 0-19, the second row is 20-39, etc.

Run it in a terminal with 21 rows and it looks pretty snazzy.

share|improve this answer
This totally should have won. I guess 'ease of input' was weighted fairly high. – primo Aug 3 '12 at 10:13
@primo I'd even go so far as to suggest mma should have a separate competition. – luser droog Jan 26 at 4:35

Mathematica - 333

Features:

  • Interactive interface: click cells to make your patterns

  • Nice grid

  • Buttons: RUN, PAUSE, CLEAR

The code is below.

Manipulate[x=Switch[run,1,x,2,CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},{2,2,2}}},
{1,1}},x],3,Table[0,{k,40},{j,40}]];EventHandler[Dynamic[tds=Reverse[Transpose[x]];
ArrayPlot[tds,Mesh->True]],{"MouseClicked":>(pos=Ceiling[MousePosition["Graphics"]];
x=ReplacePart[x,pos->1-x[[Sequence@@pos]]];)}],{{run,3,""},{1->"||",2->">",3->"X"}}]

enter image description here

If you want to get a feel how this runs, 2nd example in this blog is just a more elaborate version (live Fourier analysis, better interface) of the code above. Example should run right in your browser after free plugin download.

share|improve this answer
+1, nice one for having a go. Yeah that's the problem with this site, there are tonnes of old questions which one tends to miss. – Griffin Jul 31 '12 at 13:10

Scala, 1181 1158 1128 1063 1018 1003 999 992 987 characters

import swing._
import event._
object L extends SimpleSwingApplication{import java.awt.event._
import javax.swing._
var(w,h,c,d,r)=(20,20,20,0,false)
var x=Array.fill(w,h)(0)
def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
def top=new MainFrame with ActionListener{preferredSize=new Dimension(500,500)
menuBar=new MenuBar{contents+=new Menu("C"){contents+={new MenuItem("Go/Stop"){listenTo(this)
reactions+={case ButtonClicked(c)=>r= !r}}}}}
contents=new Component{listenTo(mouse.clicks)
reactions+={case e:MouseClicked=>var p=e.point
x(p.x/c)(p.y/c)^=1
repaint}
override def paint(g:Graphics2D){for(j<-0 to h-1;i<-0 to w-1){var r=new Rectangle(i*c,j*c,c,c)
x(i)(j)match{case 0=>g draw r
case 1=>g fill r}}}}
def actionPerformed(e:ActionEvent){if(r){var t=x.map(_.clone)
for(j<-0 to h-1;i<-0 to w-1){d=0
n(i,j)
x(i)(j)match{case 0=>if(d==3)t(i)(j)=1
case 1=>if(d<2||d>3)t(i)(j)=0}}
x=t.map(_.clone)
repaint}}
val t=new Timer(200,this)
t.start}}

Ungolfed:

import swing._
import event._

object Life extends SimpleSwingApplication
{
    import java.awt.event._
    import javax.swing._
    var(w,h,c,d,run)=(20,20,20,0,false)
    var x=Array.fill(w,h)(0)
    def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
    def top=new MainFrame with ActionListener
    {
        title="Life"
        preferredSize=new Dimension(500,500)
        menuBar=new MenuBar
        {
            contents+=new Menu("Control")
            {
                contents+={new MenuItem("Start/Stop")
                {
                    listenTo(this)
                    reactions+=
                    {
                        case ButtonClicked(c)=>run= !run
                    }
                }}
            }
        }
        contents=new Component
        {
            listenTo(mouse.clicks)
            reactions+=
            {
                case e:MouseClicked=>
                    var p=e.point
                    if(p.x<w*c)
                    {
                        x(p.x/c)(p.y/c)^=1
                        repaint
                    }
            }
            override def paint(g:Graphics2D)
            {
                for(j<-0 to h-1;i<-0 to w-1)
                {
                    var r=new Rectangle(i*c,j*c,c,c)
                    x(i)(j) match
                    {
                        case 0=>g draw r
                        case 1=>g fill r
                    }
                }
            }
        }
        def actionPerformed(e:ActionEvent)
        {
            if(run)
            {
                var t=x.map(_.clone)
                for(j<-0 to h-1;i<-0 to w-1)
                {
                    d=0
                    n(i,j)
                    x(i)(j) match
                    {
                        case 0=>if(d==3)t(i)(j)=1
                        case 1=>if(d<2||d>3)t(i)(j)=0
                    }
                }
                x=t.map(_.clone)
                repaint
            }
        }
        val timer=new Timer(200,this)
        timer.start
    }
}

The larger part of the code here is Swing GUI stuff. The game itself is in the actionPerformed method which is triggered by the Timer, and the helper function n which counts neighbours.

Usage:

Compile it with scalac filename and then run it with scala L.
Clicking a square flips it from live to dead, and the menu option starts and stops the game. If you want to change the size of the grid, change the first three values in the line: var(w,h,c,d,r)=(20,20,20,0,false) they are width, height and cell size (in pixels) respectively.

share|improve this answer
I found 2 golfing-improvements: import java.awt.event._ and contents+=m("Go",true)+=m("Stop",false)}}, leading to 1093 characters. – user unknown Aug 14 '11 at 19:20
@user unknown Thanks. I found a few improvements myself - down to 1063 now. – Gareth Aug 14 '11 at 19:47
Damn you've been busy. Keep it up! I will be testing answers when a few more people post them. – Griffin Aug 14 '11 at 23:56

Ruby 1.9 + SDL (380 325 314)

EDIT: 314 characters, and fixed a bug with extra cells appearing alive on the first iteration. Upped the grid size to 56 since the color routine only looks at the lowest 8 bits.

EDIT: Golfed down to 325 characters. Grid width/height is now 28 since 28*9 is the largest you can have while still using the value as the background colour. It also processes only one SDL event per iteration now, which obviates the inner loop completely. Pretty tight I think!

The simulation starts paused, with all cells dead. You can press any key to toggle pause/unpause, and click any cell to toggle it between alive and dead. Runs an iteration every tenth of a second.

The wrapping is a bit wonky.

require'sdl'
SDL.init W=56
R=0..T=W*W
b=[]
s=SDL::Screen.open S=W*9,S,0,0
loop{r="#{e=SDL::Event.poll}"
r['yU']?$_^=1:r[?Q]?exit: r['nU']?b[e.y/9*W+e.x/9]^=1:0
b=R.map{|i|v=[~W,-W,-55,-1,1,55,W,57].select{|f|b[(i+f)%T]}.size;v==3||v==2&&b[i]}if$_
R.map{|i|s.fillRect i%W*9,i/W*9,9,9,[b[i]?0:S]*3}
s.flip
sleep 0.1}

Looks like this:

Screenshot of the app in action

Fun challenge! I welcome any improvements anybody can see.

share|improve this answer
Nice try but I can see straight away that you've gone wrong. You can't have a pattern like that in GoL. Have another read of the rules: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules – Griffin Aug 1 '12 at 8:01
@Griffin I think the screenshot was taken after pausing and toggling some cells manually - I'll check the rules again, though. Thanks! – chron Aug 2 '12 at 0:44
@Griffin cant the seed pattern be in any possible configuration? – ardnew Aug 8 '12 at 4:30

Scala - 799 chars

Run as a script. A mouse click on a square toggles it on or off and any key starts or stops generation.

import java.awt.Color._
import swing._
import event._
import actors.Actor._
new SimpleSwingApplication{var(y,r,b)=(200,false,Array.fill(20,20)(false))
lazy val u=new Panel{actor{loop{if(r){b=Array.tabulate(20,20){(i,j)=>def^(i:Int)= -19*(i min 0)+(i max 0)%20
var(c,n,r)=(0,b(i)(j),-1 to 1)
for(x<-r;y<-r;if x!=0||y!=0){if(b(^(i+x))(^(j+y)))c+=1}
if(n&&(c<2||c>3))false else if(!n&&c==3)true else n}};repaint;Thread.sleep(y)}}
focusable=true
preferredSize=new Dimension(y,y)
listenTo(mouse.clicks,keys)
reactions+={case e:MouseClicked=>val(i,j)=(e.point.x/10,e.point.y/10);b(i)(j)= !b(i)(j)case _:KeyTyped=>r= !r}
override def paintComponent(g:Graphics2D){g.clearRect(0,0,y,y);g.setColor(red)
for(x<-0 to 19;y<-0 to 19 if b(x)(y))g.fillRect(x*10,y*10,9,9)}}
def top=new Frame{contents=u}}.main(null)
share|improve this answer

Mathematica, 123 characters

A very rudimentary implementation that doesn't use Mathematica's built-in CellularAutomaton function.

ListAnimate@NestList[ImageFilter[If[3<=Total@Flatten@#<=3+#[[2]][[2]],1,0]&,#,1]&,Image[Round/@RandomReal[1,{200,200}]],99]
share|improve this answer

C 1063 characters

As a challenge, I did this in C using the golf-unfriendly Windows API for real time IO. If capslock is on, the simulation will run. It will stay still if capslock is off. Draw patterns with the mouse; left click revives cells and right click kills cells.

#include <windows.h>
#include<process.h>
#define K ][(x+80)%20+(y+80)%20*20]
#define H R.Event.MouseEvent.dwMousePosition
#define J R.Event.MouseEvent.dwButtonState
HANDLE Q,W;char*E[3],O;Y(x,y){return E[0 K;}U(x,y,l,v){E[l K=v;}I(){E[2]=E[1];E[1]=*E;*E=E[2];memset(E[1],0,400);}A(i,j,k,l,P){while(1){Sleep(16);for(i=0;i<20;++i)for(j=0;j<20;++j){COORD a={i,j};SetConsoleCursorPosition(Q,a);putchar(E[0][i+j*20]==1?'0':' ');}if(O){for(i=0;i<20;++i)for(j=0;j<20;++j){for(k=i-1,P=0;k<i+2;++k)for(l=j-1;l<j+2;++l){P+=Y(k,l);}U(i,j,1,P==3?1:Y(i,j)==1&&P==4?1:0);}I();}}}main(T,x,y,F,D){for(x=0;x<21;++x)puts("#####################");E[0]=malloc(800);E[1]=E[0]+400;I();I();W=GetStdHandle(-10);Q=GetStdHandle(-11);SetConsoleMode(W,24);INPUT_RECORD R;F=D=O=0;COORD size={80,25};SetConsoleScreenBufferSize(Q,size);_beginthread(A,99,0);while(1){ReadConsoleInput(W,&R,1,&T);switch(R.EventType){case 1:O=R.Event.KeyEvent.dwControlKeyState&128;break;case 2:switch(R.Event.MouseEvent.dwEventFlags){case 1:x=H.X;y=H.Y;case 0:F=J&1;D=J&2;}if(F)U(x,y,0,1);if(D)U(x,y,0,0);}}}

The compiled EXE can be found here

Edit: I've commented up the source. It's available Here

share|improve this answer
I'd love to see a commented version of this! – luser droog Dec 21 '12 at 2:50
Sure, if I can remember what I was thinking... =p – Aslai Dec 22 '12 at 23:18
@luserdroog Here it is pastebin.com/BrX6wgUj – Aslai Dec 22 '12 at 23:59
Awesome. Thank you. – luser droog Dec 23 '12 at 0:47

C# - 675 chars

I've always wanted to write a version of this program. Never knew it would only take a lazy half hour for a quick and dirty version. (Golfing it takes much longer, of course.)

using System.Windows.Forms;class G:Form{static void Main(){new G(25).ShowDialog();}
public G(int z){var g=new Panel[z,z];var n=new int [z,z];int x,y,t;for(int i=0;i<z;
i++)for(int j=0;j<z;j++){var p=new Panel{Width=9,Height=9,Left=i*9,Top=j*9,BackColor
=System.Drawing.Color.Tan};p.Click+=(s,a)=>p.Visible=!p.Visible;Controls.Add(g[i,j]=
p);}KeyUp+=(s,_)=>{for(int i=0;i<99;i++){for(x=0;x<z;x++)for(y=0;y<z;y++){t=0;for(int 
c=-1;c<2;c++)for(int d=-1;d<2;d++)if(c!=0||d!=0){int a=x+c,b=y+d;a=a<0?24:a>24?0:a;b=
b<0?24:b>24?0:b;t+=g[a,b].Visible?0:1;}if(t==3||t>1&&!g[x,y].Visible)n[x,y]=1;if(t<2
||t>3)n[x,y]=0;}for(x=0;x<z;x++)for(y=0;y<z;y++)g[x,y].Visible=n[x,y]<1;Update();}};}}

Usage

  • Enter a starting pattern by clicking cells to turn them on (alive).
  • Start the game by pressing any keyboard key.
  • The game runs for 99 generations every time a key is pressed (I could have made it 9 to save a char, but that seemed too lame).

Golfing compromises

  • You can only turn cells on with the mouse, not off, so if you make a mistake you have to restart the program.
  • There are no grid lines, but that doesn't hurt playability too much.
  • Update speed is proportional to CPU speed, so on very fast computers it will probably be just a blur.
  • Living cells are red because "black" uses 2 more characters.
  • The smallness of the cells and the fact that they don't use up all the form space are also character-saving compromises.
share|improve this answer

There's an easy cop-out to this in Mathematica, 115 characters:

ListAnimate[ArrayPlot/@CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},
{2,2,2}}},{1,1}},{RandomInteger[1,{9,9}],0},90]]
share|improve this answer
Mathematica is fine, but as the rules state the program must allow the user to input their own patterns. This rule is intentional since a few languages allow short implementations like this but with no user interaction. Sure you can put your own array in there, but it's not gonna win. – Griffin Aug 14 '11 at 23:58
"input" in Mathematica is mostly through the notebook interface, so I don't think "user interaction" is really possible. You just replace the RandomInteger argument to the CellularAutomaton function with whatever you want, and re-evaluate the code. – Bean Aug 15 '11 at 0:16
User interaction is possible. The most simplistic method I can think of right now is an array of buttons. Give it a go man. – Griffin Aug 15 '11 at 0:19

Postscript 529 515

Started with the example from Rosetta Code. Invoke with a filename argument (gs -- gol.ps pulsar), the file containing 20*20 binary numbers (separated by space). Infinite loop: draw board, wait for enter, calculate next generation.

[/f ARGUMENTS 0 get(r)file/n 20>>begin[/m
n 1 sub/b[n{[n{f token pop}repeat]}repeat]/c 400
n div/F{dup 0 lt{n add}if dup n ge{n sub}if}>>begin{0
1 m{dup 0 1 m{2 copy b exch get exch get 1 xor setgray
c mul exch c mul c c rectfill dup}for pop pop}for
showpage/b[0 1 m{/x exch def[0 1 m{/y exch def 0
y 1 sub 1 y 1 add{F dup x 1 sub 1 x
1 add{F b exch get exch get 3 2 roll add exch
dup}for pop pop}for b x get y get sub b x get y get
0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq
or{1}{0}ifelse}ifelse}for]}for]def}loop

Spaced, with a few stack comments (just the ones I needed).

[
/f ARGUMENTS 0 get(r)file
/n 20
/sz 400
%/r{rand 2147483647 div}
>>begin
[
/m n 1 sub
/b[
%n{[n{r .15 le{1}{0}ifelse}repeat]}repeat
 n{[n{f token pop}repeat]}repeat
]
/c sz n div
/F{dup 0 lt{n add}if dup n ge{n sub}if}
>>begin
{
    0 1 m{dup % y y
    0 1 m{ % y y x
        2 copy b exch get exch get 1 xor setgray
        c mul exch c mul c c rectfill
        dup 
    }for pop pop}for
    pstack
    showpage
    /b[0 1 m{/x exch def
      [0 1 m{/y exch def
          0   
          y 1 sub 1 y 1 add{F dup %s y y
          x 1 sub 1 x 1 add{F %s y y x
              b exch get exch get %s y bxy
              3 2 roll add exch %s+bxy y
              dup %s y y
          }for pop pop}for
          b x get y get sub
          b x get y get
          0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq or{1}{0}ifelse}ifelse
      }for]
      }for]def
}loop

pulsar data file:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
share|improve this answer

Python, 589 bytes

Mouse buttons: left - put a cell, right - remove a cell, middle - start/stop.

from Tkinter import*
import copy
z=range
F=50
T=Tk()
S=9
f=[F*[0]for i in'7'*F]
c=Canvas(T,width=S*F,height=S*F)
c.pack()
def p(x,y,a):f[y][x]=f[y][x]or c.create_oval(x*S,y*S,x*S+S,y*S+S)if a else c.delete(f[y][x])
r=1
def R(e):global r;r=1-r
exec("c.bind('<Button-%i>',lambda e:p(e.x/S,e.y/S,%i));"*2%(1,1,3,0))
c.bind('<Button-2>',R)
def L():
 T.after(99,L)
 if r:return
 g=copy.deepcopy(f)
 for y in z(F):
	for x in z(F):
	 n=8
	 for j in z(-1,2):
		for i in z(-1,2):
		 if i or j:n-=not g[(y+j)%F][(x+i)%F]
	 if 1<n<4:
		if n==3and not g[y][x]:p(x,y,1)
	 else:p(x,y,0)
L()
T.mainloop()

And here is a version where you can drag mouse to draw. Graphics are a bit more pleasant.

from Tkinter import*
import copy
z=range
F=50
T=Tk()
S=9
f=[F*[0]for i in'7'*F]
c=Canvas(T,bg='white',width=S*F,height=S*F)
c.pack()
def p(x,y,a):f[y][x]=f[y][x]or c.create_rectangle(x*S,y*S,x*S+S,y*S+S,fill='gray')if a else c.delete(f[y][x])
r=1
def R(e):global r;r=1-r
exec("c.bind('<Button-%i>',lambda e:p(e.x/S,e.y/S,%i));c.bind('<B%i-Motion>',lambda e:p(e.x/S,e.y/S,%i));"*2%(1,1,1,1,3,0,3,0))
c.bind('<Button-2>',R)
def L():
 T.after(99,L)
 if r:return
 g=copy.deepcopy(f)
 for y in z(F):
  for x in z(F):
   n=8
   for j in z(-1,2):
    for i in z(-1,2):
     if i or j:n-=not g[(y+j)%F][(x+i)%F]
   if 1<n<4:
    if n==3and not g[y][x]:p(x,y,1)
   else:p(x,y,0)
L()
T.mainloop()
share|improve this answer
This doesn't follow the game of life rules correctly. – Steven Rumbalski Aug 23 '11 at 13:23
1  
@StevenRumbalski: Oh really? – BlaXpirit Aug 23 '11 at 14:00
2  
really. You have an indentation error in your second version. The section starting with if 1<n<4: should be indented at the same level as for j in z(-1,2): – Steven Rumbalski Aug 23 '11 at 18:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.