ruby game of life program

V

Van Jacques

Finally its right. It seems so obvious now. I thought I could
take this or that shortcut without thinking it thru.
I must be more methodical.
I couldn't quit till I did it.

Now to do some more interesting patterns.

Here it is if you are interested.

===========
# Size of grid;

nn = 8
nnm = nn - 1
nmm = nnm - 1

# Create and Initialize Grid a

a = Array.new
b = Array.new
0.upto( nnm ) do |i|
a = Array.new( nn )
b = Array.new( nn )
a = [0,0,0,0,0,0,0,0]
b = [0,0,0,0,0,0,0,0]
end


# Initial state
a[3][2] = 1
a[3][3] = 1
a[3][4] = 1
a[3][5] = 1


0.upto( nnm ) do |i|
print a
puts ""
end
puts ""

# Apply rules to set a[j] = 0 or 1
# What to do at edges?
# If a cell is off and has 3 living neighbors (out of 8), it will become alive
# in the next generation.
# If a cell is on and has 2 or 3 living neighbors, it survives; otherwise, it
# dies in the next generation. Otherwise no change.

1.upto( 6 ) do |k|
1.upto( nmm ) do |i|
1.upto( nmm ) do |j|


# count n = number of black cells around [j]

n = a[i-1][j-1] + a[i-1][j] + a[i-1][j+1] + a[j-1] + a[j+1] + \
a[i+1][j-1] + a[i+1][j] + a[i+1][j+1]

if (a[j] == 0 and n == 3) then b[j] = 1
elsif (a[j] == 1 && (n != 2 and n != 3)) then b[j] = 0
elsif (a[j] == 0 and n != 3) then b[j] = 0
elsif (a[j] == 1 && (n == 2 or n == 3)) then b[j] = 1
end
end
end

0.upto( nnm ) do |i|
0.upto( nnm ) do |j|
a[j] = b[j]
end
print a
puts ""
end
puts ""

0.upto( nnm ) do |i|
0.upto( nnm ) do |j|
if (a[j] == 0) then print ' '
else print 'X'
end
end
puts ""
end
end



=====
Sylvan Jacques ; (Van)[email protected]
 
J

Josef 'Jupp' SCHUGT

Hi!

* Van Jacques; 2003-11-29, 12:40 UTC:
Finally its right. It seems so obvious now. I thought I could take
this or that shortcut without thinking it thru.
I must be more methodical.
I couldn't quit till I did it.

Here's some suggestions. 'tos' stands for 'the old situations', 'tng'
for 'the next generation'. You could as well use 'last_generation'
and 'next_generation'.

#!/usr/bin/env ruby
N = 7

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0]
}

2.upto(5) { |column|
tos[3][column] = 1
}

0.upto(N) { |row|
print tos[row], "\n"
}
puts

1.upto(6) { |generation|
1.upto(N - 1) { |row|
1.upto(N - 1) { |column|
neighbors = 0
-1.upto(1) { |row_offset|
-1.upto(1) { |column_offset|
unless row_offset == 0 and column_offset == 0
neighbors += tos[row+row_offset][column+column_offset]
end
}
}
if tos[row][column] == 0
tng[row][column] = neighbors == 3 ? 1 : 0
else
tng[row][column] = (neighbors == 2 or neighbors == 3) ? 1 : 0
end
}
}

0.upto(N) { |row|
0.upto(N) { |column| tos[row][column] = tng[row][column] }
print tos[row], "\n"
}
puts

0.upto(N) { |row|
0.upto(N) { |column|
print (tos[row][column] == 0 ? ' ' : 'X')
}
puts
}
}
#done

Wow, that was my first game of life ever :->

Josef 'Jupp' Schugt
 
V

Van Jacques

Thanks for the suggestions. A great improvement. I was thinking about what to do
about the edges when the initial pattern expanded to the edges.
(This initial pattern stays in the middle, and only changes for the first
few generations, but others do all kinds of things, as I'm sure most
people know.) Have you run this? I am going to.
You appear to know the language pretty well.

On the LHS (row = 0) the edges won't be a problem, since -1 in ruby
will wrap around to the RHS. But I haven't thought about what to
do when a live cell reaches the RHS, since when row goes
out of range it will get nil. Maybe I can turn nil into 0.

I will have the same behavior at the top and bottom of the grid too.

=============
 
V

Van Jacques

Josef 'Jupp' SCHUGT said:
#!/usr/bin/env ruby
N = 7

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0]
}
...
Wow, that was my first game of life ever :->

Josef 'Jupp' Schugt

One thing I notice was that I used

a = Array.new
b = Array.new
0.upto( size - 1 ) do |i|
a = Array.new(size, 0)
b = Array.new(size, 0)
end

while you used

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0] }

==========

Is there any difference? It seems easier to use

tos[row] = Array.new(N+1, 0)

rather than

tos[row] = [0, 0, 0, 0, 0, 0, 0, 0] .

Van
 
J

Josef 'Jupp' SCHUGT

Hi!

* Van Jacques; 2003-12-01, 12:52 UTC:
One thing I notice was that I used

a = Array.new
b = Array.new
0.upto( size - 1 ) do |i|
a = Array.new(size, 0)
b = Array.new(size, 0)
end

while you used

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0] }


You seem to be confusing something. In the message I did answer to
you did use

a = Array.new
b = Array.new
0.upto( nnm ) do |i|
a = Array.new( nn )
b = Array.new( nn )
a = [0,0,0,0,0,0,0,0]
b = [0,0,0,0,0,0,0,0]
end

I was assuming you did intentionally implement it in that way (to
better point out the initial values) and so I saw no reson to change
it.

Josef 'Jupp' Schugt
 
V

Van Jacques

"Josef 'Jupp' SCHUGT" <[email protected]> wrote in message news:<20031129174431.GB2320@jupp%gmx.de>...

I decided to handle the edges by making the grid into a torus, using
mod NN,
where I set NN = grid edge, N = NN - 1, in Josef's notation. Then the
part of the
program that decides that next generation becomes

0.upto(N) do |row|
0.upto(N) do |column|
neighbors = 0
-1.upto(1) do |row_offset|
-1.upto(1) do |column_offset|
unless row_offset == 0 and column_offset == 0
i = (row+row_offset) % NN
j = (column+column_offset) % NN
neighbors += tos[j]
end
end
end
if tos[row][column] == 0
tng[row][column] = (neighbors == 3) ? 1 : 0
else
tng[row][column] = (neighbors == 2 or neighbors == 3) ? 1 : 0
end
end
end

============

Since mod NN connects top and bottom, and LHS with RHS, we can do all
the rows and columns
from 0 to N = NN - 1.

I also used a new pattern and more steps or generations.

With NN = 11 = # of rows and cols., I used the initial condition know
as an "acorn";

tos[4][4] = tos[5][6] = tos[6][3] = tos[6][4] = 1
tos[6][7] = tos[6][8] = tos[6][9] = 1

and increased to # of steps to 40. The pattern is much more
interesting, and becomes
stable at step 34.

If one increases NN to 20, and # of steps to several hundred, the
behavior is far more
complex. The variety of behaviors of even simple games of life is
amazing.

I recommend this as a practice program for anyone learning to program.
 
V

Van Jacques

Josef 'Jupp' SCHUGT said:
Hi!

* Van Jacques; 2003-12-01, 12:52 UTC:
One thing I notice was that I used
.....

You seem to be confusing something. In the message I did answer to
you did use

a = Array.new
b = Array.new
0.upto( nnm ) do |i|
a = Array.new( nn )
b = Array.new( nn )
a = [0,0,0,0,0,0,0,0]
b = [0,0,0,0,0,0,0,0]
end

I was assuming you did intentionally implement it in that way (to
better point out the initial values) and so I saw no reson to change
it.

Josef 'Jupp' Schugt


I see. I must have changed it after I made the first post.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top