# 產生不重複之亂數

## 解題步驟

### 宣告陣列

* 首先宣告一個陣列空間為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] 就會超出陣列範圍。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://java.4-x.tw/java-exercise/java-random.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
