2017-08-25 77 views
1

因此,我正在製作一個模擬類似生命的細胞自動機的程序,但我在計算細胞活的鄰居時使用了一些方法。問題是我希望能夠改變網格如何環繞 - 也就是說,它是否從左到右包圍從左到右(即圓柱形),從頂部到底部從左到右(即環形)或根本不是(即,平坦的) - 我無法弄清楚如何使我的方法說明。這是我到目前爲止有:如何使用環繞計數細胞自動機中的細胞鄰居

public int getLiveNeighbors(int row, int col) 
{ 
    int count = 0; 

    // "topology" is an int that represents wraparound: 
    // 0 = flat; 1 = cylindrical; 2 = toroidal 
    int top = topology != 2 ? row - 1 : (row + ROWS - 1) % ROWS; 
    int bottom = topology != 2 ? row + 1 : (row + 1) % ROWS; 
    int left = topology != 0 ? (col + COLS - 1) % COLS : col - 1; 
    int right = topology != 0 ? (col + 1) % COLS : col + 1; 

    for (int r = top; r < bottom + 1; r++) 
     for (int c = left; c < right + 1; c++) 
      if (!(r == row && c == col) && getCell(r, c).equals(LIVE)) 
       count++; 
} 

的關鍵,我認爲,是for -loop的if語句來 - 必須有某種方式來檢查rc是否的邊界內網格,同時牢記「邊界」的定義將根據網格是否/如何環繞而變化。在過去,我已經通過對八個不同的if-陳述分別檢查由原始細胞的鄰域組成的八個細胞中的每一個而有三個不同的組(每個環繞設置一個)正如你可以想象的那樣,它不是很漂亮,但至少它工作。

我不是很擅長解釋我自己的代碼,所以我希望這不是太混亂 - 我自己感覺有點傻(哈哈)。如果有人有任何問題,隨時問!

回答

0

你可能已經有一個像Board這樣的類,像getCell(x, y)這樣的方法(至少這種方法存在於你的代碼中)。

我只是讓這種方法在某種意義上寬鬆,它將接受負xyxy大於或等於COLSROWS。因此,您只需重複col - 1col + 1row - 1row + 1(減號爲colrow),而不用擔心這些座標會「全盤」。這是Board正確執行座標查找的任務。

什麼讓你的代碼更難以處理不同的拓撲在一個地方。這很難遵循。

您可以通過實施Board的不同子類來簡化操作,如CylindricalBoard,ToroidalBoardFlatBoard。每個子類都會實現getCell的不同,但在子類的上下文中,它將顯而易見。

0

您正在尋找的Strategy Pattern

有常見的情況時,班他們的行爲只是有所不同。對於這種情況,在單獨的類中分離算法是一個好主意,以便能夠在運行時選擇不同的算法。

在這種情況下,你想是這樣的(以下簡稱爲清楚起見):

class Point { 
    int x; 
    int y; 
} 
interface WrapStrategy { 
    Point moveUp(Point p); 
    Point moveDown(Point p); 
    Point moveLeft(Point p); 
    Point moveRight(Point p); 
} 
class CylinderWrapping implements WrapStrategy { 
    int height; 
    int circumference; 
    Point moveUp(Point p) { 
     if (p.y <= 0) 
      return null; // cannot move up 
     return new Point(p.x, p.y - 1); 
    } 
    Point moveDown(Point p) { 
     if (p.y >= height - 1) 
      return null; // cannot move down 
     return new Point(p.x, p.y + 1); 
    } 
    Point moveLeft(Point p) { 
     if (p.x <= 0) 
      return new Point(circumference - 1, p.y); 
     return new Point(p.x - 1, p.y); 
    } 
    Point moveRight(Point p) { 
     if (p.x >= circumference - 1) 
      return new Point(0, p.y); 
     return new Point(p.x + 1, p.y); 
    } 
} 
0

試試這個:

import java.awt.Point; 

public class Neighbours { 

    public static void main(String[] args) { 
     Neighbours inst=new Neighbours(); 
     int r=3;//<ROWS 
     int c=3;//<COLS 
     for(int i :new int[]{0,1,2}){ 
      inst.type=i; 
      System.out.format("There are %d neighbours of point (%d,%d), topography type %d\n", inst.countLiveNeighbours(r, c), c, r,i); 
     } 
    } 

    int ROWS=4; 
    int COLS=4; 
    int type=0;//0=flat, 1=cylinder, 2=toroid 

    /** 
    * Is x,y a neighbour of r,c? 
    * @return coordinates of neighbour or null 
    */ 
    Point neighbour(int x, int y, int r, int c){ 
     if((x==c)&&(y==r)) 
      return null; 
     switch (type){ 
/*this is wrong for the reasons explained below 
     case 0: return ((x<COLS)&&(y<ROWS)) ? new Point (x,y) : null; 
     case 1: return y<ROWS ? new Point(x%COLS,y) : null; 
     case 2: return new Point(x%COLS,y%ROWS); 
*/ 
//replacement statements produce the correct behaviour 
    case 0: return ((x<COLS)&&(x>-1)&&(y<ROWS)&&(y>-1)) ? new Point (x,y) : null; 
    case 1: return ((y<ROWS)&&(y>-1)) ? new Point(Math.floorMod(x,COLS),y) : null; 
    case 2: return new Point(Math.floorMod(x,COLS),Math.floorMod(y,ROWS)); 
     } 
     return null; 
    } 

    int countLiveNeighbours(int r, int c){ 
     int result=0; 
     for(int x=c-1; x<c+2; x++) 
      for(int y=r-1; y<r+2; y++){ 
       Point p=neighbour(x,y,r,c); 
       if(live(p)){ 
        System.out.format("\tpoint (%d,%d)\n",(int)p.getX(),(int)p.getY()); 
        result++; 
       } 
      } 
     return result; 
    } 

    boolean live(Point p){ 
     boolean result=true; 
     if(p==null) 
      return false; 
     //perform tests for liveness here and set result 
     return result; 
    } 
} 
+0

好,我也去了快這裏是因爲x和y的負指數情況(網格從0,0開始)。另外,事實證明Java%操作符返回一個餘數而不是一個合適的模數。這與負數有關(例如-1%4 = -1而不是3)。 Math.floorMod會產生正確的行爲。請參閱上面的替換案例聲明。 – stegzzz