精華區beta Programming 關於我們 聯絡資訊
在獨自看了Java兩個禮拜後,決定寫支程式來練習,遂想了一個模擬動物行為的程式. 原本是想以物件繼承的方式來寫,例如:獅子是一個物件,繼承自肉食動物,肉食動物 又繼承自動物,動物又繼承自生物,其物件關係如下: 生物<------動物<------肉食性動物<------獅子 (生長) | (移動) | (獵食) (死亡) | (進食) | (繁殖) | (睡眠) | | ---草食性動物<------鹿 | (躲藏) | -----植物<------草 括號內是method 不過寫了一半就放棄以物件的方式來寫, 因為像移動,獵食,躲藏這些method,很抽象,不知如何實作. 如果以thread的方式來寫,不知行不行? 例如一隻獅子,一隻鹿就是一個thread.如可以,該如何寫呢? 本程式run到一半會停住,不知是何原因? 不曉得能否用exception來處理? 附source code 及 html 如下, 還望各位先進們不吝指教. // // SimAnimal ver 1.0 designed by Chen Jong-ming Dec. 21,1998 // 模擬動物程式 1.0版 設計者: 陳中明 1998年12月21日 // E-mail: vchen@iii.org.tw // //本程式模擬動物世界中的繁殖,死亡,弱肉強食. //草食性動物只吃草,肉食性動物只吃肉,雜食性動物則都吃. //動物走過的地方會留下氣味,過一段時間會長出草來. //肉食動物藉由氣味,跟蹤弱小動物;弱小動物也會憑氣味遠離肉食動物. //有些動物(如獅)速度雖快,耐力卻不夠,不能長時間追獵. //有些動物(如鹿)速度雖不快,卻能持久,能長時間全速奔逃. //正常體力的動物是黑色,當體力下降至非黑色時,才需覓食. //動物只要有移動就會降低體力,移動愈快,體力遞減愈多,進食則可恢復體力. //有些動物生育期很短(如兔),能在短時間,繁殖下一代. //有些動物生育期很長(如熊),需較長時間,繁殖下一代. //繁殖需在體力足夠時才可,即體力顏色在黑色及藍色時才可繁殖. //每種動物壽命不一樣,時間一到,就會壽終正寢;體力耗盡也會死亡. // import java.applet.*; import java.awt.*; public class SimAnimal extends Applet { byte map[][][]; static final int xMin=10,xMax=740,yMin=50,yMax=340;//設定動物移動範圍 private Button createLion; private Button createBear; private Button createDeer; private Button createHare; private Button createGrass; private Button SaveQuit; private Button play; byte animal=0; // 9=獅,6=熊,3=鹿,2=兔,-1=草,-98=play,-99=quit int lapse=0;模擬時間 String ai=new String(". hd B L");// 動物圖示 int ac[][]= {// 特性 0<-速度,1<-耐力,2<-生育期,3<-壽命,4<-食性,5=居性 // 6<-現有數量,7<-死亡數量,8<-出生數量 // 0, 1, 2, 3, 4, 5, 6, 7, 8 // 速度,耐力,生育,壽命,食性,棲性,數量,死亡,出生 { 0, 0, 0, 0, 0, 0, 0, 0, 0},//草 { 0, 0, 0, 0, 0, 0, 0, 0, 0},// { 70, -5, 31, 80, 0, 0, 0, 0, 0},//兔,草食 {110, -1, 37, 100, 0, 0, 0, 0, 0},//鹿,草食 { 0, 0, 0, 0, 0, 0, 0, 0, 0},// { 0, 0, 0, 0, 0, 0, 0, 0, 0},// { 70, -5, 46, 110, 2, 0, 0, 0, 0},//熊,雜食 { 0, 0, 0, 0, 0, 0, 0, 0, 0},// { 0, 0, 0, 0, 0, 0, 0, 0, 0},// {120, -6, 41, 120, 1, 0, 0, 0, 0} //獅,肉食 }; public void init() { map=new byte[yMax][xMax][4];// 0<-動物,1<-體力,2<-速度,3<-壽命 createLion=new Button("L獅"); createBear=new Button("B熊"); createDeer=new Button("d鹿"); createHare=new Button("h兔"); createGrass=new Button(".草"); SaveQuit=new Button("Quit"); play=new Button("PLAY"); add(createLion); add(createBear); add(createDeer); add(createHare); add(createGrass); add(SaveQuit); add(play); } public void paint(Graphics g) { g.drawString("獅數量: "+ac[9][6],1,13); g.drawString("熊數量: "+ac[6][6],100,13); g.drawString("鹿數量: "+ac[3][6],550,13); g.drawString("兔數量: "+ac[2][6],650,13); g.drawString("死亡數: "+ac[9][7],1,27); g.drawString("死亡數: "+ac[6][7],100,27); g.drawString("死亡數: "+ac[3][7],550,27); g.drawString("死亡數: "+ac[2][7],650,27); g.drawString("出生數: "+ac[9][8],1,40); g.drawString("出生數: "+ac[6][8],100,40); g.drawString("出生數: "+ac[3][8],550,40); g.drawString("出生數: "+ac[2][8],650,40); for(int r=yMin;r<yMax;r++)//畫出動物 for(int c=xMin;c<xMax;c++) { if(map[r][c][0]!=0&&map[r][c][0]>-2) { if(map[r][c][0]==-1) { g.setColor(Color.green);//草 g.drawString(".",c,r); } else if(map[r][c][0]>0) { if(map[r][c][1]<-50)g.setColor(Color.pink); else if(map[r][c][1]<0)g.setColor(Color.orange); else if(map[r][c][1]<50)g.setColor(Color.yellow); else if(map[r][c][1]<100)g.setColor(Color.blue); else g.setColor(Color.black); g.drawString(""+ai.charAt(map[r][c][0]),c,r); } } if(map[r][c][0]<-1&&lapse%10==0) { map[r][c][0]=-1;//氣味消失,草長出 map[r][c][3]=(byte)ac[0][3]; } } //獵食及逃脫 for(int r=yMin;r<yMax;r++) for(int c=xMin;c<xMax;c++) { if(map[r][c][0]>0||map[r][c][0]==-1) { //動物或草 if((map[r][c][0]>0&&map[r][c][1]<-100)||(--map[r][c][3]<-110)) { //壽終正寢或體力衰竭,死亡 if(map[r][c][0]>0) { //紀錄動物死亡 ac[map[r][c][0]][6]--; ac[map[r][c][0]][7]++; } map[r][c][0]=0; continue; } if(map[r][c][0]==-1)continue; //該動物(位於r,c)要先觀察四週 byte smell=0;//0=觀察週遭,1=嗅氣味 boolean move=false; do { for(int n=1;n<map[r][c][2]/4;n++)//n是觀察範圍,由近而遠 { if(move)break; for(int xx=c-n;xx<c+n;xx++) { if(move)break; if(xx<xMin||xx>xMax)continue; for(int yy=r-n;yy<r+n;yy++) { if(yy<yMin||yy>yMax)continue; //取動物代號之絕對值,如獅是9;獅的氣味-9,abs值是9 byte mm=(byte)Math.abs(map[yy][xx][0]); // 鄰近的動物比自身強悍 || 聞到動物氣味 if(map[yy][xx][0]>map[r][c][0]||(smell==1&&map[yy][xx][0]<-1)) { int acc=ac[mm][4]; //非草食&&比自身強悍 if(acc>0&&mm>map[r][c][0]) { //該處(xx,yy)有獵食動物,準備脫逃 int ex=c+(c>xx?1:-1)*map[r][c][2]/10;//X軸逃脫位移; int ey=r+(r>yy?1:-1)*map[r][c][2]/10;//Y軸逃脫位移; if(Math.abs(map[ey][ex][0])<2&&ex>xMin&&ex<xMax&&ey>yMin&&ey<yMax) { //要落腳的地方沒其他動物 for(int z=0;z<4;z++) map[ey][ex][z]=map[r][c][z];//動物移位 map[r][c][0]=(byte)(-map[r][c][0]);//清除動物先前位置,留下氣味 map[ey][ex][1]-=Math.abs(ey+ex-r-c)/5;//體力遞減 //速度-耐力 map[ey][ex][2]=(byte)(map[ey][ex][2]+ac[map[ey][ex][0]][1]); if(map[ey][ex][2]<ac[map[ey][ex][0]][0]*0.5) //當速度降至50%以下時,再恢復原速 map[ey][ex][2]=(byte)ac[map[ey][ex][0]][0]; } move=true;//動物有移動 break; } } else if(map[r][c][1]<100&&mm<map[r][c][0]) // 聞到動物氣味 || 草 || 動物 if((smell==1&&map[yy][xx][0]<-1)||map[yy][xx][0]==-1||map[yy][xx][0]>0) { //當體力降至100以下,就要獵食,獵物在(yy,xx) int hy=yy,hx=xx,range=map[r][c][2]/10; if(Math.abs(yy-r)<=range&&Math.abs(xx-c)<=range&&smell==0) { //獵物在速度範圍內,吃掉獵物 if(ac[map[r][c][0]][4]!=1&&map[yy][xx][0]==-1) map[r][c][1]++;//非肉食動物,吃草後體力加1 else if(map[yy][xx][0]>0) { //非草食動物 ac[map[yy][xx][0]][6]--;//獵物現有數量減1 ac[map[yy][xx][0]][7]++;//獵物死亡數量加1 //獵食後,體力增加,速度恢復原速 map[r][c][1]=(byte)(map[r][c][1]+map[yy][xx][0]*10); map[r][c][2]=(byte)ac[map[r][c][0]][0]; } else continue;//沒有吃到任何東西,掃描下個位置 } else { //追趕獵物 hx=c+(c>xx?1:-1)*range;//X軸追趕位移; hy=r+(r>yy?1:-1)*range;//Y軸追趕位移; if(hx<xMin||hx>xMax||hy<yMin||hy>yMax)continue; } for(int z=0;z<4;z++) map[hy][hx][z]=map[r][c][z];//動物移位 map[r][c][0]=(byte)(-map[r][c][0]);//清除動物先前位置,留下氣味 //速度-耐力 map[hy][hx][2]=(byte)(map[hy][hx][2]+ac[map[hy][hx][0]][1]); if(map[hy][hx][2]<ac[map[hy][hx][0]][0]*0.5) //當速度降至50%以下時,再恢復原速 map[hy][hx][2]=(byte)ac[map[hy][hx][0]][0]; move=true;//動物有移動 break; } }//for yy }//for xx }//for nn }while(!move&&(++smell<2)); if(!move) { //沒有進食,也沒有脫逃,就亂數漫遊 int rr=(int)((1-2*Math.random())*map[r][c][2]/20); int cc=(int)((1-2*Math.random())*map[r][c][2]/20); int ex=c+cc,ey=r+rr; if((rr!=0||cc!=0)&&ex>xMin&&ex<xMax&&ey>yMin&&ey<yMax) { map[r][c][1]--;//體力遞減 for(int z=0;z<4;z++) map[ey][ex][z]=map[r][c][z];//動物移位 map[r][c][0]=(byte)(-map[r][c][0]);//清除動物先前位置,留下氣味 int age=ac[map[ey][ex][0]][3]-map[ey][ex][3]; int birth=(age%ac[map[ey][ex][0]][2]); if(map[ey][ex][1]>50&&birth==0&&age>0) { //體力足又到生育年齡就生下一代 byte ani=map[ey][ex][0]; map[r][c][0]=ani;//生出幼子 map[r][c][1]=127;//給定幼子體力,127是最大值 map[r][c][2]=(byte)ac[ani][0];//給定幼子速度 map[r][c][3]=(byte)ac[ani][3];//給定幼子壽命 ac[ani][6]++;//增加現有數量 ac[ani][8]++;//增加出生數量 } } } }//if map[r][c][0] }//for c if(animal==-98) { repaint(); for(int delay=0;delay<5000;delay++) g.drawString(""+delay,200,15); } showStatus("模擬時間: "+lapse++); } //選擇動物產生的地點 public boolean mouseDown(Event e,int x,int y) { if(animal==-98)return true; showStatus("mouse"+x+" "+y); if(x<xMin||x>xMax||y<yMin||y>yMax) { showStatus("超出範圍"); return true; } if(map[y][x][0]==0||map[y][x][0]==-1) { byte ani=animal; map[y][x][0]=animal; if(animal==-1)ani=0; map[y][x][1]=127;//體力,127是最大值 map[y][x][2]=(byte)ac[ani][0];//速度 map[y][x][3]=(byte)ac[ani][3];//壽命 ac[ani][6]++;//增加現有數量 repaint(); } else showStatus("該位置有其他動物"); return true; } //選擇要產生的動物 public boolean action(Event e,Object o) { if(e.target==play) { animal=-98; repaint(); } if(e.target==createLion)animal=9; if(e.target==createBear)animal=6; if(e.target==createDeer)animal=3; if(e.target==createHare)animal=2; if(e.target==createGrass)animal=-1; if(e.target==SaveQuit)animal=-99; showStatus("移動滑鼠到你想要產生動物的地方"); return true; } } <html> <head> <title>SimAnimal</title> </head> <body> <hr> <applet code=SimAnimal width=750 height=350> </applet> <hr> </body> </html> --=Smart Mailvchen@iii.org.tw-Thu-Dec-24-14-33-57=-- -- * Origin: ★ 交通大學資訊科學系 BBS ★ <bbs.cis.nctu.edu.tw: 140.113.23.3>