J2SE 常用 Math.random() 產生 [0.0, 1.0) double,但 CLDC/MIDP 精簡了 Math 類,移除 random()。J2ME 統一使用 java.util.Random 產生偽隨機數。
// 1. 預設種子 = System.currentTimeMillis() (較隨機)
Random r = new Random();
// 2. 固定種子 (可重現序列,利於測試/回放)
Random r = new Random(10010010L);
// 等價於
Random r = new Random(System.currentTimeMillis());
| 方法 | 回傳範圍 | 用途 |
|---|---|---|
nextInt() | int 全範圍 (-2^31 ~ 2^31-1) | 通用整數、位運算 |
nextLong() | long 全範圍 | 64位隨機、ID 生成 |
nextBoolean() | true/false | 布林決策 |
nextFloat() | 0.0f ~ 1.0f | 浮點隨機 (CLDC 1.1+) |
nextDouble() | 0.0 ~ 1.0 | 雙精度浮點 (CLDC 1.1+) |
nextBytes(byte[]) | 填滿陣列 | 密鑰、鹽值、隨機資料 |
int n = 10; // 0-9
int r = Math.abs(random.nextInt() % n);
nextInt() 可能為負,Math.abs() 修正為非負。% n 取模縮小範圍。Integer.MIN_VALUE 取絕對值仍為負 (溢位),極罕見但理論存在。生產環境建議用 random.nextInt() & 0x7FFFFFFF 保證非負。
int min = 10, max = 20; // 10-20 共 11 個數
int range = max - min + 1; // 11
int r = min + (Math.abs(random.nextInt()) % range);
public class RandomUtil {
private static final Random RND = new Random();
// [0, n)
public static int nextInt(int n) {
if (n <= 0) throw new IllegalArgumentException("n must be > 0");
int bits, val;
do {
bits = RND.nextInt() & 0x7FFFFFFF; // 非負
val = bits % n;
} while (bits - val + (n - 1) < 0); // 拒絕採樣消除模數偏差
return val;
}
// [min, max]
public static int nextInt(int min, int max) {
if (min > max) throw new IllegalArgumentException();
return min + nextInt(max - min + 1);
}
// 隨機布林 (可設定機率)
public static boolean nextBoolean(float probability) {
return nextInt(10000) < (probability * 10000);
}
// 從陣列隨機取元素
public static T randomElement(T[] array) {
if (array == null || array.length == 0) return null;
return array[nextInt(array.length)];
}
// 洗牌演算法 (Fisher-Yates)
public static void shuffle(Object[] array) {
for (int i = array.length - 1; i > 0; i--) {
int j = nextInt(i + 1);
Object tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
int dice = RandomUtil.nextInt(1, 6);
int x = RandomUtil.nextInt(0, getWidth() - enemyWidth);
int y = RandomUtil.nextInt(0, getHeight() - enemyHeight);
if (RandomUtil.nextBoolean(0.10f)) {
dropRareItem();
}
Card[] deck = createDeck();
RandomUtil.shuffle(deck);
// 伺服器發送種子
long seed = System.currentTimeMillis(); // 或協商種子
Random worldGen = new Random(seed);
// 客戶端用相同種子生成相同世界
Random 實例,避免頻繁建立物件與種子碰撞。nextBytes(byte[]) 一次填滿陣列,比迴圈 nextInt() 快。Math.abs(random.nextInt()) % n 遇 Integer.MIN_VALUE 產生負數 → 用 & 0x7FFFFFFF 修正。n 非 2 的冪次時,餘數分布不均 → 用拒絕採樣 (見改良版)。new Random() 或混合時間+裝置ID作種子。nextFloat/Double → 僅用 nextInt/Long/Boolean/Bytes。