2014-09-21 60 views
0

我試圖模擬一羣在網格上移動的簡單實體。如何在網格中表示實體

單個實體將具有特定屬性,並且網格將是方形單元的二維陣列,其可以在任何時間包含從零到多個實體的任何地方。

考慮到我不想過度設計一些東西,但同時又看到顯而易見的簡單解決方案出現問題,那麼什麼類型的數據結構可以適用?

如果我有一個實體數組,其中每個實體都有它的座標,那麼這對填充網格的每一步都很好。但是,如果我想知道關於某個給定位置的信息,那麼這就使得它必須遍歷整個實體數組,以查看該位置是否有實體。 (或者如果我需要知道類似的東西,可以與它相鄰)

而相反(使網格數組跟蹤所有內容)遇到相反的問題,如果我想知道某個實體的具體內容名稱或健身)我需要搜索整個網格數組以找到我正在尋找的實體。

終於有我的第三種方法似乎過度設計:有一個所有的實體和網格數組的數組是一堆指向該單元格中的任何實體的指針數組。在第三部分中,我認爲細胞需要知道哪些實體在其中,實體需要知道它們在哪個細胞中。我甚至不確定是否需要實體知道它們的座標。相對於他們自己的位置,他們只會認識他們的周圍環境然後移動他們可能更有意義。另外,我在JavaScript中這樣做,所以指針可能只在邏輯上可能與一些黑客,我試圖不要過度設計的東西。

回答

0

這些對象,網格和實體,在一個系統中,每個對象只有在連接到另一個時才具有相關性?我的意思是你的實體對象只能用在這個網格中嗎?並且這個網格對象是否只持有實體對象?如果是這樣,那麼你可以把它們連在一起,不僅僅是從電網的角度來看,而且還可以從實體來看。

我假定你的網格由一個主要的網格對象組成,這個網格對象可能由一組行組成,每行都有一組單元格。每個單元當然相當於數組中的一個[x] [y]位置。這些單元中的每一個都有一組實體對象。

如果您將對象創建爲「分層引用」,則在列表中移動將很容易。網格可能有一個行集合,但每行都應該有一個引用它的網格的父屬性。這些行可能有一組單元格,但每個單元格都應該有一個引用其父行的父屬性。並且每個實體對象都應該有一個單元格屬性,指向它所分開的單元格。

當你爲實體創建你的move()函數時,它需要1)從自己當前的細胞實體集合中刪除自己,2)將自己添加到新的細胞集合中,3)更新entity.cell屬性以引用新的細胞。

這是一種結構的一個未經考驗的實體模型,我說的是:

function grid(height, width) { 
    this.rows = []; 

    this.cellAt = function(row, cell) { 
     return this.rows[row].cells[cell]; 
    }; 

    this.entitiesAt = function(row, cell) { 
     return this.cellAt(row, cell).entities; 
    }; 

    this.addRow = function() { 
     var r = new row(this); 
     this.rows.push(r); 
     return r; 
    }; 

    //create the grid in the default size. 
    if (height != null && width != null) { 
     var i, j, r; 
     for (i = 0; i <= height; i++) { 
      r = this.addRow(); 
      for (j = 0; j <= width; j++) 
       r.addCell(); 
     } 
    } 
} 

function row(parentGrid) { 
    this.grid = parentGrid; 
    this.cells = []; 

    this.getIndex = function() { 
     return this.grid.rows.indexOf(this); 
    }; 

    this.addCell = function() { 
     var c = new cell(this); 
     this.cells.push(c); 
     return c; 
    }; 
} 

function cell(parentRow) { 
    this.row = parentRow; 
    this.entities = []; 

    this.getIndex = function() { 
     return this.row.cells.indexOf(this); 
    }; 

    this.addEntity = function(entity) { 
     this.entities.push(entity); 
     entity.cell = this; 
    }; 

    this.removeEntity = function(entity) { 
     var i = this.entities.indexOf(entity); 
     if (i >= 0) this.entities.splice(i, 1); 
     entity.cell = null; 
    }; 

    this.removeEntityAt = function(index) { 
     if (this.entities.length < index && index >= 0) { 
      e = this.entities[index]; 
      this.entities.splice(index, 1); 
      e.cell = null; 
     } 
    }; 
} 

function entity() { 
    this.cell = null; 

    this.getLocation = function() { 
     return { 
      "row" : this.cell.row.getIndex(), 
      "cell" : this.cell.getIndex() 
     }; 
    }; 

    this.move = function(row, cell) { 
     var g = this.cell.row.grid; 
     this.cell.removeEntity(this); 
     g.cellAt(row, cell).addEntity(this); 
    }; 
} 

注:慎用indexOf()。這很有幫助,but not fully cross browser

實際使用情況看起來像這樣。

創建新的網格

var grid1 = new grid(100, 100); 

創建一個新的實體,並把它添加到網格:

var e = new entity(); 
grid1.cellAt(12, 23).addEntity(e); 

移動實體:

e.move(53, 23); 

有可能多了很多這裏。例如,如果這個網格,行,單元和實體對象要表示實際的HTML元素,那麼在創建腳本中可以讓它創建這些HTML元素。例如,創建新行和/或單元格時,可能需要創建一個div元素。讓你有邏輯網格和「物理」元件之間的連接到陣列連接到div的一種方法:

<div data-row="12" data-cell="23"><div> 

底線是,我想創建這些結構和「分級參照」對象將使它更容易在網格中移動。另外,修改這個以支持一個文檔中的多個網格將會非常容易。

+0

這太好了。 (類似於我認爲的第三種方法,但方式更好)感謝您的幫助。而且這個實現教會了我很多jvs – 2014-09-21 06:44:35