FONDAMENTI DI INFORMATICA
A.A. 2022/23
CORSI DI LAUREA IN INGEGNERIA AEROSPAZIALE E
INGEGNERIA MECCANICA
SEDE DI FORLÌ
Mirko Ravaioli
e-mail: [email protected]
GIOCO VITA
GIOCO DELLA VITA
Il Gioco della vita (Game of Life in inglese, noto anche solo come Life) è un
automa cellulare sviluppato dal matematico inglese John Conway sul finire degli
anni sessanta. Il Gioco della vita è l'esempio più famoso di automa cellulare: il
suo scopo è quello di mostrare come comportamenti simili alla vita possano
emergere da regole semplici e interazioni a molti corpi, principio che è alla base
dell'ecobiologia, la quale si rifà anche alla teoria della complessità. Del gioco
sono poi state sviluppate versioni con differenti topologie, ad esempio
tridimensionali, differenti regole biologiche, e differenti tipi di cellule.
GIOCO VITA
Si tratta in realtà di un gioco senza giocatori, intendendo che la sua evoluzione è determinata dal suo
stato iniziale, senza necessità di alcun input da parte di giocatori umani. Si svolge su una griglia di
caselle quadrate (celle) che si estende all'infinito in tutte le direzioni; questa griglia è detta mondo.
Ogni cella ha 8 vicini, che sono le celle ad essa adiacenti, includendo quelle in senso diagonale. Ogni
cella può trovarsi in due stati: viva o morta (o accesa e spenta, on e off). Lo stato della griglia evolve in
intervalli di tempo discreti, cioè scanditi in maniera netta. Gli stati di tutte le celle in un dato istante
sono usati per calcolare lo stato delle celle all'istante successivo. Tutte le celle del mondo vengono
quindi aggiornate simultaneamente nel passaggio da un istante a quello successivo: passa così una
generazione.
Le transizioni dipendono unicamente dallo stato delle celle vicine in quella generazione:
‣Qualsiasi cella viva con meno di due celle vive adiacenti muore, come per effetto d'isolamento;
‣Qualsiasi cella viva con due o tre celle vive adiacenti sopravvive alla generazione successiva;
‣Qualsiasi cella viva con più di tre celle vive adiacenti muore, come per effetto di sovrappopolazione;
‣Qualsiasi cella morta con esattamente tre celle vive adiacenti diventa una cella viva, come per effetto
di riproduzione.
GIOCO VITA
GIOCO VITA - MAIN
function main()
% 1 - inizializzare matrice mondo
% 2 - stampa matrice mondo
% 3 - ripeti fino a quando esistono celle vive
% 3.1 - gestione evoluzione al secondo X
% 3.1.1 - data una cella i,j contare celle
vive attorno
% 3.1.2 - se la cella i,j è viva
% 3.1.2.1 - se numVive < 2 or > 3 cella i,j
muore
% 3.1.2.2 - se numVive == 2 or == 3 cella
i,j continua a vivere
% 3.1.3 - se la cella i,j è morta (vuota)
% 3.1.3.1 - se numVive == 3 cella i,j
nasce
% 3.2 - conta numero di celle vive
% 3.3 - visualizza lo stato post evoluzione
% 3.4 - aggiornamento per secondo successivo
end
GIOCO VITA - AGGIUSTAMENTO COORDINATE PER MATRICE “INFINITA”
function [i, j] = checkCoordinate(mondo, i, j)
[nr, nc] = size(mondo);
if i < 1
i = nr;
elseif i > nr
i = 1;
end
if j < 1
j = nc;
elseif j > nc
j = 1;
end
end
GIOCO VITA - CONTEGGIO DEL NUMERO DI CELLE VIVE ATTORNO AD UNA CELLA (I,J)
function num = contaCelleViveAttorno(mondo, curr_i, curr_j);
num = 0;
for i = -1:1
for j = -1:1
if i ~= 0 || j ~= 0
[pi, pj] = checkCoordinate(mondo, curr_i + i, curr_j + j);
if mondo(pi, pj) >= 1
num = num + 1;
end
end
end
end
end
GIOCO VITA - GESTIONE DELL’EVOLUZIONE CELLA AD UN DETERMINATO ISTANTE
function stato = evoluzioneCella(mondo, i, j)
numCelleVicine = contaCelleViveAttorno(mondo, i, j);
stato = mondo(i, j);
if stato >= 1
if numCelleVicine < 2 || numCelleVicine > 3
stato = 2;
else
stato = 1;
end
elseif stato == 0
if numCelleVicine == 3
stato = -1;
else
stato = 0;
end
end
end
GIOCO VITA - AGGIORNAMENTO STATO PRIMA DELLO STEP EVOLUTIVO SUCCESSIVO
function [mondo] = aggiorna(mondo)
[nr, nc] = size(mondo);
for i = 1:nr
for j = 1:nc
switch mondo(i, j)
case -1
mondo(i, j) = 1;
case 2
mondo(i, j) = 0;
end
end
end
end
GIOCO VITA -
function [numCelleVive, numCelleNate, numCelleMorte] = conta(mondo)
numCelleVive = 0;
numCelleNate = 0;
numCelleMorte = 0;
[nr, nc] = size(mondo);
for i = 1:nr
for j = 1:nc
switch mondo(i, j)
case 1
numCelleVive = numCelleVive + 1;
case -1
numCelleNate = numCelleNate + 1;
case 2
numCelleMorte = numCelleMorte + 1;
end
end
end
numCelleVive = numCelleVive + numCelleNate;
end
GIOCO VITA -
function mondo = evoluzione(mondo)
[nr, nc] = size(mondo);
for i = 1:nr
for j = 1:nc
mondo(i, j) = evoluzioneCella(mondo, i, j);
end
end
end
GIOCO VITA -
function visualizza(mondo, step, numCelleVive, numCelleNate, numCelleMorte)
fprintf("STEP: %d" , step);
[nr, nc] = size(mondo);
for i = 1:nr
for j = 1:nc
switch mondo(i, j)
case 1
chr = 'V';
case -1
chr = 'N';
case 2
chr = '+';
otherwise
chr = ' ';
end
fprintf( "%c", chr);
end
fprintf("");
end
fprintf("vive: %d nate: %d morte: %d" , numCelleVive, numCelleNate,
numCelleMorte);
end
GIOCO VITA -
function [mondo, numCelluleVive] = inizializza(nr, nc)
mondo = zeros(nr, nc);
numCelluleVive = 0;
for i = 1:nr
for j = 1:nc
mondo(i, j) = randi(2) - 1;
if mondo(i, j) == 1
numCelluleVive = numCelluleVive + 1;
end
end
end
end
GIOCO VITA - MAIN
function main()
clc;
clear;
maxStep = 100000;
stampaOgni = maxStep;
[mondo, numCelleVive] = inizializza(10, 10);
step = 0;
visualizza(mondo, step, numCelleVive, 0, 0);
while numCelleVive > 0 && step < maxStep
step = step + 1;
mondo = evoluzione(mondo);
[numCelleVive, numCelleNate, numCelleMorte] = conta(mondo);
if numCelleVive == 0
fprintf( "fine vita a step: %d" , step);
break;
elseif numCelleMorte + numCelleNate == 0
visualizza(mondo, step, numCelleVive, 0, 0);
fprintf( "fine evoluzione a step: %d" , step);
break;
elseif mod(step, stampaOgni) == 0
visualizza(mondo, step, numCelleVive, numCelleNate, numCelleMorte);
end
mondo = aggiorna(mondo);
end
end