# 產生不重複之亂數

## 解題步驟

### 宣告陣列

* 首先宣告一個陣列空間為10的 num變數

  ```
  int[] num = new int[10];
  System.out.print(&quot;數字: &quot;);
  ```
* 透過for 迴圈製作1-10的數字

  ```
  for(int i = 0; i &lt; num.length; i++)
  {
    num[i] = i + 1;
    System.out.print(num[i]+&quot; &quot;);
  }
  ```

### **亂數函式**

* 宣告一個陣列 arr 空間為5
* arr陣列用途為放置亂數

  ```
  int[] arr = new int[5];
  ```
* 首先使用亂數製作0-9的數字n，並放入num陣列<br>

  > 假設亂數產生出 n=2 ，那麼 `num[2] = 3`\
  > 以此類推：`num[0]=1, num[1]=2, num[2]=3, …, num[9]=10`
* 再將 `num[2]` 放入 `arr[0]`

| num | \[0] | \[1] | \[2] | \[3] | \[4] | \[5] | \[6] | \[7] | \[8] | \[9] |
| --- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| 值   | 1    | 2    | 3    | 4    | 5    | 6    | 7    | 8    | 9    | 10   |

| arr | \[0] | \[1] | \[2] | \[3] | \[4] |
| --- | ---- | ---- | ---- | ---- | ---- |
| 值   | 3    | 0    | 0    | 0    | 0    |

> 陣列不會因為取代了前方的值，本值就消失\
> 所以最後方\[9]＝10

```
n = (int)(Math.random()*(10-i));
arr[i] = num[n];
```

* 剛剛是透過亂數產生0-9，現在變成產生0-8；目的是不去取用到num\[9]

  ```
  for(int j = n; j &lt; num.length - 1; j++)
  {
    num[j] = num[j+1];
  }
  ```

> 繼續剛剛的假設，如果產生出 n = 8 那麼 num\[ 8 ]＝10\
> 再把 num\[ 8 ]=10 放到 arr\[1] (此為第二個亂數)。

| num | \[0] | \[1] | \[2] | \[3] | \[4] | \[5] | \[6] | \[7] | \[8] | \[9] |
| --- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| 值   | 1    | 2    | 4    | 5    | 6    | 7    | 8    | 9    | 10   | 10   |

| arr | \[0] | \[1] | \[2] | \[3] | \[4] |
| --- | ---- | ---- | ---- | ---- | ---- |
| 值   | 3    | 10   | 0    | 0    | 0    |

* 以此類推，再產生0-7、0-6、0-5 …

  ```
  int n;
  for(int i = 0; i &lt; arr.length; i++)
  {
   n = (int)(Math.random()*(10-i));
   arr[i] = num[n];
   for(int j = n; j &lt; num.length - 1; j++)
  {
        num[j] = num[j+1];
  }
  }
  return arr;
  ```

### **完整程式碼**

```
public class Example
{
public static void main(String[] args)
{
    int[] num = new int[10];
    System.out.print(&quot;數字: &quot;);

    for(int i = 0; i &lt; num.length; i++)
    {
       num[i] = i + 1;
       System.out.print(num[i]+&quot; &quot;);
    }

    System.out.print(&quot;\n隨機不重複產生5個亂數: &quot;);

    int[] Array;

    Array = getRandom(num);

    for(int i = 0; i &lt; 5; i++)

       System.out.print(Array[i] + &quot; &quot;);
}

public static int[] getRandom(int[] num)
{
    int[] arr = new int[5];
    int n;
    for(int i = 0; i &lt; arr.length; i++)
    {
        n = (int)(Math.random()*(10-i));
        arr[i] = num[n];
        for(int j = n; j &lt; num.length - 1; j++)
        {
            num[j] = num[j+1];
        }
    }
    return arr;
}
}
```

### 後記

本文於 iT邦幫忙曾被提出[討論](https://ithelp.ithome.com.tw/questions/10187671)，在此感謝 fysh711426 替我更近一步的解說，以下為 [fysh711426](https://ithelp.ithome.com.tw/users/20106865/profile) 所示範的程式運行：

初值

```
num 1 2 3 4 5 6 7 8 9 10
arr 0 0 0 0 0
```

random n = 5

```
num 1 2 3 4 5 7 8 9 10 10
arr 6 0 0 0 0
```

random n = 5

```
num 1 2 3 4 5 8 9 10 10 10
arr 6 7 0 0 0
```

random n = 3

```
num 1 2 3 5 8 9 10 10 10 10
arr 6 7 4 0 0
```

`10-i` 是因為要讓每次取 num 陣列的範圍變小，\
以上面結果來說明，可以理解成不要取重複 10 的部分。

`num.length – 1` 是因為在把 num 往前移動時，如果不減一，j 在最尾端時 num\[j+1] 就會超出陣列範圍。
