47 FreeBASIC. Программируем "Жизнь"(программа)
Когда я впервые программировал "Жизнь" на своём
первом компьютере Размер обрабатываемой колонии я тогда задал 40х30 с запасом, а размер экрана был 32х24 клетки. И сносно работало лишь на ассемблере. Но даже в таком малом поле можно было ставить эксперименты исследуя "жизнь".
Сейчас я буду использовать разрешение 1024х768, а клетки буду отображать кружками. Радиус крога 8 пикселей,и два пикселя отступ - на экран поместится 126х94 клеток. Массива 150х150 пока хватит с лихвой.
dim shared life(0 to 151, 0 to 151) as byte
в массиве будут хранится значения: 0-пустая клетка, 1-занята.
Константы для размеров клетки:
const R as integer =4
const K as integer =2
Нам ещё понадобится функция которая находит количество соседей у конкретной клетки.
function s(x as integer, y as integer) as integer
return 2
end function
пока что это функция-заглушка, т.е. она есть, её вызывать можно, но делает она... вернее ничего не делает. При написании программ это часто используют.
В данном случае я быстро хотел получить результат - колонию на экране - подобрать размер клетки и всей колонии.
А теперь можно и написать саму функцию подсчёта. s-соседи, количество соседей.
координаты соседей клетки в (x,y) это уже было в "Морском бое".
А так как в массиве только нули да единицы - значения элементов массива нужно просуммировать.
что же делать если мы нашли пустую клетку у которой трое соседей - нужно эту пустую клетку заселить..., но ведь это повлияет на последующие подсчёты...
Тогда я использовал два массива: один обрабатывался(текущее поколение), а в втором строилось следующее поколение, которое пока никак не влияет на текущее.
Нужно до начала обработки текущего поколения перекопировать предыдущий массив(ранее построенное поколение) в текущий массив(обрабатываемый)
for x=0 to XX+1
for y=0 to YY+1
life(x,y)=lifenew(x,y)
next y
next x
for x=0 to XX+1
for y=0 to YY+1
if s(x,y)=3 and life(x,y)=0 then lifenew(x,y)=1
if (life(x,y)<2 or life(x,y)>3) and life(x,y)=1 then lifenew(x,y)=0
next y
next x
одно поколение прошло, теперь поставим небольшую паузу и перейдём к следующей итерации.(цикл)
dim shared life(0 to 151, 0 to 151) as byte
dim shared lifenew(0 to 151, 0 to 151) as byte
dim as integer x,y,i
const R as integer =4
const K as integer =2
const XX as integer = 126
const YY as integer = 94
function s(x as integer, y as integer) as integer
return life(x-1,y-1)+life(x,y-1)+life(x+1,y-1)+_
life(x-1,y)+life(x+1,y)+_
life(x-1,y+1)+life(x,y+1)+life(x+1,y+1)
end function
screenres 1024,768
lifenew(10,10)=1:lifenew(10,11)=1:lifenew(10,12)=1
lifenew(40,20)=1:lifenew(40,21)=1:lifenew(40,22)=1
do
for x=0 to XX+1
for y=0 to YY+1
life(x,y)=lifenew(x,y)
next y
next x
for x=0 to XX+1
for y=0 to YY+1
if s(x,y)=3 and life(x,y)=0 then lifenew(x,y)=1
if (s(x,y)<2 or s(x,y)>3) and life(x,y)=1 then lifenew(x,y)=0
next y
next x
sleep 500
cls
for x=0 to XX+1
for y=0 to YY+1
if life(x,y)=1 then circle(2*R*x+K,2*R*y+K),R*0.7,2:paint(2*R*x+K,2*R*y+K),2,2
next y
next x
loop while asc(inkey())<>27
программа завершит работу при нажатии ESC
Введём в программу ещё две переменные: поколение(ход) и размер популяции(количество клеток)
do
rpop=0: pok+=1
for x=0 to XX+1
for y=0 to YY+1
life(x,y)=lifenew(x,y)
rpop=rpop+life(x,y)
next y
next x
.....
.....
locate 1,1: print using "pokolenie ###"; pok
locate 2,1: print using "size ###"; rpop
if rpop=0 then print "the end": exit do
loop while asc(inkey())<>27