① 請高手用C++編寫程序—生命游戲
#include<iostream>
usingnamespacestd;
#include<time.h>
#defineM70
#defineN20
voidmShow(inta[N+2][M+2])
{inti,j;
for(i=0;i<N;i++,cout<<endl)
for(j=0;j<M;j++)
if(a[i+1][j+1])cout<<'*';
elsecout<<'.';
//cout<<(a[i+1][j+1])?('*'):('');
}
intmJge(inta[N+2][M+2])
{inti,j,k,s,*p[9],b[N][M];
for(i=0;i<N;i++)
{
p[0]=p[4]=p[5]=&a[i+1][1];p[4]--;p[5]++;//123
p[1]=p[2]=p[3]=p[0]-M-2;p[1]--;p[3]++;//405
p[6]=p[7]=p[8]=p[0]+M+2;p[6]--;p[8]++;//678
for(j=0;j<M;j++)
{for(k=1,s=0;k<9;k++)s+=(*p[k]);
b[i][j]=*p[0];
if(s>=3)b[i][j]=1;
elseif(s<2)b[i][j]=0;
for(k=0;k<9;k++)p[k]++;
}
}
for(i=0,s=1;i<N;i++)for(j=0;j<M;j++){a[i+1][j+1]=b[i][j];if(b[i][j]==0)s=0;}
returns;
}
voidmain()
{
inta[N+2][M+2],b[N][M],*p[9];
intt,i,j,k;
for(i=0;i<N+2;i++)for(j=0;j<M+2;j++)a[i][j]=0;
srand((unsignedint)time(NULL));
for(i=0;i<N;i++)for(j=0;j<M;j++){k=rand()%100;a[i+1][j+1]=(k>=77)?(1):(0);}
cout<<"--------T=0--------"<<endl;mShow(a);
k=0;t=0;
while(!k)
{k=mJge(a);t++;
cout<<"--------T="<<t<<"--------"<<endl;mShow(a);
}
}
a數組比實際要的數組大一圈,大出來的一圈永恆等於0,作為邊界,省得計算8連通數據時數組越界
b數組用於計算本次的結果,計算完成後復制、覆蓋a數組中間部分作為結果
主程序做直到所有空間都被活細胞占滿情況停止
以下是設置M=10,N=5的測試部分結果
② 求C語言命令行程序的「生命游戲」代碼
I don't know的這個答案在網上隨處可見,而且並不符合樓主的要求。
這個程序並不復雜,用1個2維數組來保存列表的信息,用2個循環嵌套來遍歷數組中的每個元素,然後計算每個元素周圍共有多少個'*',並根據規則為這個元素重新賦值。計算每個元素周圍'*'的數量我是用2個循環嵌套來實現的,因為不象I don't know給出的程序那樣邊緣的元素不參與變化,所以需要判斷是否會超出范圍。
#include <stdio.h>
void input(char [][21],int,int);
void output(char [][21],int);
int trans(char [][21],int,int);
int main()
{
int row,col,ret,i;
char tab[20][21];
for(;;)
{
printf("輸入行數和列數(行,列):");
ret=scanf("%d,%d",&row,&col);
if(ret==2 && (9<=row && row<=20) && (9<=col && col<=20))
break;
else
printf("輸入錯誤!請重新輸入!\n");
fflush(stdin);
}
input(tab,row,col);
for(i=0;i<10;i++)
{
if(trans(tab,row,col))
output(tab,row);
else
break;
}
return 0;
}
void input(char tab[][21],int row,int col)
{
int i,j,c;
for(c=0;c!=col;)
{
printf("輸入列表:\n");
for(i=0;i<row;i++)
{
scanf("%s",tab[i]);
for(c=j=0;tab[i][j];j++)
{
if(tab[i][j]=='*' || tab[i][j]=='.')
c++;
else
break;
}
if(c!=col)
{
printf("輸入錯誤!請重新輸入!\n");
break;
}
}
fflush(stdin);
}
}
void output(char tab[][21],int row)
{
int i;
printf("輸出列表:\n");
for(i=0;i<row;i++)
printf("%s\n",tab[i]);
}
int trans(char tab[][21],int row,int col)
{
int i,j,x,y,c,change=0;
char t[20][20];
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
{
for(c=0,x=i-1;x<=i+1;x++)
{
if(x<0 || x>=row)
continue;
for(y=j-1;y<=j+1;y++)
{
if(y<0 || y>=col || (x==i && y==j))
continue;
if(tab[x][y]=='*')
c++;
}
}
t[i][j]=(c==3 || tab[i][j]=='*' && c==2)?'*':'.';
if(tab[i][j]!=t[i][j])
change=1;
}
}
for(i=0;i<row;i++)
for(j=0;j<col;j++)
tab[i][j]=t[i][j];
return change;
}
③ Matlab中生命游戲代碼每一行的注釋
clc
clearall
closeall
m=30;n=30;p=.7;h=100;
%%
%生成30*30矩陣a,a的值根據隨機數是否大於閾值0.7決定為1或0。
forx=1:m
fory=1:n
r=rand(1);%rand產生的是0到1(不包括1)的隨機數。
ifr>p
a(x,y)=1;
elsea(x,y)=0;
end
end
end
%%
forx=1:m
fory=1:n
ifa(x,y)==1
fx=[x-1,x-1,x,x];
fy=[y-1,y,y,y-1];
fill(fx,fy,'g');
%fill將點[x1,y1],[x2,y2],[x3,y3],[x4,y4]按序連線,後形成的圖像進行填充,參數『g』表示綠色。
%[x1,y1],[x2,y2],[x3,y3],[x4,y4]對應寫成[x1x2x3x4][y1y2y3y4],holdon表示畫在一幅圖上。
holdon
else
end
end
end
%即如果a(1,1)值為1,就在圖像上在(1,1)點左下方畫一個單位為1綠色的正方形。
%這一塊可以不要,因為畫圖後被黑底覆蓋。
%%
fork=1:h%運行100次
fx=[0,m,m,0];fy=[0,0,n,n];fill(fx,fy,'k'),holdon%畫一個30*30黑底
forx=2:m-1
fory=2:n-1
b(x,y)=a(x-1,y-1)+a(x-1,y)+a(x-1,y+1)+a(x,y-1)+a(x,y+1)+a(x+1,y-1)+a(x+1,y)+a(x+1,y+1);
%根據生命游戲規,取矩陣a元素(x,y)周圍八個元素值的和,因為最外邊一圈元素周圍沒有八個相鄰元素,
%所以不考慮,x、y范圍2:m-1、2:n-1。
ifb(x,y)==2,c(x,y)=a(x,y);
%如果(x,y)周圍存在2個1,即游戲意義2個活細胞,則這個細胞下一刻生死與原來生死有關。
elseifb(x,y)==3,c(x,y)=1;
%如果(x,y)周圍存在3個1,即游戲意義2個活細胞,則這個細胞下一刻必存活(這里我假設1是存活)。
elsec(x,y)=0;
%如果(x,y)周圍存在活細胞不是這兩個值,即太多或太少,則這個細胞下一刻必死亡(這里我假設0是死亡)。
end
end
end
%%
c(1:m,1)=a(1:m,1);
c(1:m,n)=a(1:m,n);%加上兩側的兩列
c(1,1:n)=a(1,1:n);%此處我感覺還應該加上最上最下兩行,原程序沒有。否則缺少的部分值為零,顯示一直為黑。
c(m,1:n)=a(m,1:n);%注意矩陣表示與畫圖等於進行了矩陣的轉置,缺少矩陣上下兩行則左右兩側顯示為黑。
forx=1:m
fory=1:n
ifc(x,y)==1
fx=[x-1,x-1,x,x];fy=[y-1,y,y,y-1];fill(fx,fy,'g'),holdon
else
end
end
end
%畫出c,同上畫a
pause(.05)%暫停0.05秒,觀察變化過程
a=c;%將c賦值給a,即將此時的c當作前一時刻a,繼續循環畫圖
end
%這個過程就是先生成一個隨機30*30矩陣a,對a矩陣中間29*29部分根據生命游戲規則進行運算並顯示,循環100次。
%可以發現最外邊一圈圖形是不變的。
④ 如何用c語言編生命游戲程序
寫了這么多,記得追點分啊~~~~~`
這個問題分解為兩部分
1、用什麼方式表示某時刻有哪些細胞是活的
一種簡單的想法是用一個二位數組將某時刻所有的細胞的狀態都記錄下來,不過這樣的內存開銷太大,同時又給細胞網格設定了界限,而且效率也並不高
比較好的做法是用一個線形表int list[][2]來記錄某時刻的所有的活細胞的坐標,同時用一個整數int n記錄當前的活細胞數量
2、如何從某時刻的狀態推導出下一時刻有哪些細胞為活的
根據規則,顯然,某時刻某個細胞是否活著完全取決於前一時刻周圍有多少活著的細胞,以及該時刻該細胞是否活著
因此,推導下一時刻狀態時,根據當前list中的活細胞,可以得到該時刻有哪些細胞是與活細胞相臨的,進而得知這些細胞在該時刻與多少個活細胞相臨,於是可以知道下一時刻有哪些細胞是活的
具體實現時,需要一個能夠儲存坐標並給每個坐標附帶了一個計數器(記錄該坐標的細胞與多少個活細胞相臨)和一個標志(0或1,表示當前該坐標的細胞是活是死)的容器,假設為T,容器T的功能是檢查某個坐標是否在其中,以及向其中添加帶有某個標志某個坐標並將該坐標的計數器清零,以及將某個坐標的計數器累進一
比如,假設已經定義了
struct Container
{
...
};//容器類型
void Clear(Container *T);//清空容器T
int Exist(Container *T,int x,int y);//返回坐標(x,y)是否存在於T中
void Insert(Container *T,int x,int y,int flag);//將標志為flag的坐標(x,y)加入T
void Add(Container *T,int x,int y);//將坐標(x,y)的計數器累加
void Promote(Container *T,int *n,int list[][2]);//將容器中所有計數器值為3的坐標以及所有計數器為2並且標志為1的坐標添加到list中,並將其個數記錄於n
此外,為了方便找出某個坐標的所有相鄰坐標,設置以下方向常量
const int dir[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,1},{1,-1},{-1,-1}};
那麼,從某時刻狀態生成下一時刻狀態的主要代碼如下
...
Container T;
int i,j;
...
Clear(&T);
for (i=0;i<n;i++) Insert(&T,list[i][0],list[i][1],1);
for (i=0;i<n;i++)
for (j=0;j<8;j++)
{
int x,y;
x=list[i][0]+dir[j][0];
y=list[i][1]+dir[j][1];
if (!Exist(&T,x,y)) Insert(&T,x,y,0);
Add(&T,x,y);
}
Promote(&T,&n,list);
...
關於容器T如何實現,一種簡單的思路是用線形表並將元素有序記錄,不過這樣的查找/插入效率難以兼顧
用哈希表的話,最後的Promote很難實現
塊狀鏈表可以兼顧查找與插入的效率,但是寫起來太惡心,效率也不是特別高
個人認為,最佳的解決方案是用平衡二叉搜索樹,常見的AVL樹或者紅黑樹什麼的,不過寫起來也太麻煩。
這里強烈推薦Size Balanced Tree,由中國一位現在讀高二的高中生所發明,原理清晰,效率高,實現簡單