2014-05-15 64 views
2

我有一個二維數組,我已經設置所有的細胞進行枚舉類型State.SAFE。現在我想將這些單元格隨機地放置到State.HIT中。所以,我有:把隨機數隨機分爲2D陣列

Random objrandom = new Random(); 

State[][] playField = new State[5][5]; 
int w; 

for (w = 0; w < 5; w++) {     // set all states to SAFE first 
    int h = 0; 
    playField[w][h] = State.SAFE; 

    for (h = 0; h < 5; h++) { 
     playField[w][h] = State.SAFE; 
    } 
} 

for (int i = 0; i < 5; i++) {   // try and set 5 states, randomly, to HIT 
    playField[objrandom.nextInt(5)][objrandom.nextInt(5)] = State.HIT; 
} 

的問題是我每次運行它的時候,所有的細胞是仍然處於安全狀態或命中狀態是隨機分佈的非,即每列的第一行或有超過5個HIT狀態。

+0

它是一個5x5的陣列? –

+0

「objrandom」的類型是什麼?它是「Random」類的一個實例嗎?如果是的話,你如何初始化它? – Shahryar

+0

是的,它是一個5x5陣列,我的意思是有25個陣列元素,所以是5x5?隨機類被初始化:Random objrandom = new Random(); –

回答

0

有你的解決方案的問題,因爲該行playField[objrandom.nextInt(5)][objrandom.nextInt(5)]=...可能導致相同的細胞被引用兩次。我不能確定這是否是你的問題的原因,但它可能至少是其中的一部分。

如果你想解決這個問題,你必須檢查雙命中的情況下,爲不同的隨機對已經改變了細胞的歷史中的每個隨機數,並要求。

我的建議是完全不同的方法。而不是要求改變值的單元格的行和列的索引,隨機應該表示值將改變的概率。

換句話說:

  • 轉到在陣列中的所有單元,(使用nextDouble()
  • 生成0和1之間的隨機值如果該值是該小區應該改變的概率低於(5個細胞的25意味着5/25 = 0.2的概率= 20%),如果有的話,將值設置爲State.HIT,否則設置爲State.SAFE

代碼應看起來像這樣:

Random objrandom = new Random(); 

State[][] playField = new State[5][5]; 

for (int w = 0; w < 5; w++) {    
    for (int h = 0; h < 5; h++) { 
     playField[w][h] = (objrandom.nextDouble() < 0.2d) ? State.HIT : State.SAFE; 
    } 
} 
+0

這並不能保證5個單元格將被設置爲HIT。 – assylias

+0

在你的文章中,只有兩個引用數字5的是:'可以說5,這些單元'和'或者有超過5個HIT狀態',我理解爲:'應該有5個單元,但不應該有更多'。您可以清楚地看到我的解決方案能夠滿足這些要求你應該編輯你的問題,並重新修改需求,因爲它們是不準確的。 – eitanfar

1

如果您確切需要5個單元格設置爲HIT,則不能像這樣使用隨機數,因爲您可能會多次獲取相同的數字。這是我會怎麼做:

public static void main(String[] args) { 
    State[][] playField = new State[5][5]; 

    setStateToSafe(playField); 
    List<Integer> hits = getRandomIndices(5); 
    applyHitStateToIndices(hits, playField); 

    System.out.println(Arrays.deepToString(playField)); 
} 

private static void setStateToSafe(State[][] playField) { 
    for (int w = 0; w < playField.length; w++) { 
    Arrays.fill(playField[w], State.SAFE); 
    } 
} 
private static List<Integer> getRandomIndices(int n) { 
    List<Integer> hits = new ArrayList<>(); 
    for (int i = 0; i < n * n; i++) hits.add(i); 
    Collections.shuffle(hits); 
    return hits.subList(0, n); 
} 
private static void applyHitStateToIndices(List<Integer> hits, State[][] playField) { 
    for (int i = 0; i < hits.size(); i++) { 
    int hitIndex = hits.get(i); 
    int row = hitIndex/playField.length; 
    int column = hitIndex % playField.length; 
    playField[row][column] = State.HIT; 
    } 
} 
+0

謝謝你的詳細回覆。儘管將playField設置爲一定的大小並將隨機的HIT狀態放入其中已經被認爲是現有方法的一部分,這是一種爲用戶初始設置棋盤遊戲的方法,因此我無法在其中創建其他方法。我也不是很瞭解你最後兩種方法對不起,我是編程新手。用SAFE狀態填充數組看起來像是一個更好的選擇,謝謝。 –

+0

@BarneyGorilla你不能*在另一個方法中放置一個方法,但你可以從另一個方法調用一個方法。我只是用自己的方法將每個動作分開,以使事情更清晰。最後,更好的設計是創建一個「PlayField」類,並將所有的邏輯放在類本身中。 – assylias

0

如果小的開銷不會造成大的麻煩,那麼你可以做這樣的事情:

來表示自己場上的一個點創建一個類。

final class Point { 
    public final int x; 
    public final int y; 

    public Point(final int x, final int y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

用所有可能的點填充一個列表,然後洗牌。

List<Point> points = new ArrayList<>(); 
for (int x = 0; x < 5; x++) { 
    for (int y = 0; y < 5; y++) { 
     points.add(new Point(x, y)); 
    } 
} 
Collections.shuffle(points); 

現在第一N(5你的情況),積分將被隨機分組​​,100%不一樣的。

for (int i = 0; i < 5; i++) { 
    Point p = points.get(i); 
    playField[p.x][p.y] = State.HIT; 
} 
+0

聽起來像一個想法。也許我應該嘗試使用for循環以外的其他方法分配隨機數。謝謝 –

+0

如果你「洗牌」你的積分列表,那麼你的積分順序將隨機化。例如'[(0,1),(0,2),(0,3)] - > [(0,2),(0,3),(0,1)]'然後如果迭代這些點,你可以隨機生成這些點,因爲它們是隨機排列的。 –