Java Homework - 樂透下注產生器

記錄一下我寫緯育 Java 班第三份作業的程式碼,共三種作法。

程式碼區塊的 highlight 效果是透過 highlight.js 實現,步驟可參考這支影片,挺容易的。

作法 1

numbersWithout() 負責產生可選擇的號碼這部分,關鍵是使用餘數運算去取得個位數數字,以及將整個數目減去個位數再除以十得到十位數數字。

randomBets() 負責亂數取得 6 個不重複的號碼,想法是每次選中某個號碼後,將後面所有號碼都指定到前一位置,因此選中的號碼被蓋過不見,然後再建立一個新的陣列但長度比原本的減 1,如此之後亂數選擇便不會重複數字。


package junli.hw3;

import java.util.Arrays;
import java.util.Scanner;

//阿文很喜歡簽大樂透(1~49),但他是個善變的人,上次討厭數字是4,但這次他想要依心情決定討厭哪個數字
//請您設計一隻程式,讓阿文可以輸入他不想要的數字(1~9),畫面會顯示他可以選擇的號碼與總數
//(提示:Scanner)
//(進階挑戰:輸入不要的數字後,直接亂數印出6個號碼且不得重複)

public class Lottery {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Lottery aWen = new Lottery();
        Scanner sc = new Scanner(System.in);
        System.out.println("阿文...請輸入你討厭的數字");
        int numNotWanted;
        while(true) {
            numNotWanted = sc.nextInt();
            if (numNotWanted < 1 || numNotWanted > 9) {
                System.out.println("請輸入1~9之間的數字");
            } else {
                break;
            }
        }
        int[] remainingNumbers = aWen.numbersWithout(numNotWanted);
        aWen.showNumbers(remainingNumbers);
        aWen.randomBets(remainingNumbers);

    }

    private int[] numbersWithout(int numNotWanted) {
        int[] array = new int[0];
        for (int i = 1; i <= 49; i++) {
            if (i / 10 == numNotWanted || i % 10 == numNotWanted) {
                continue;
            }
            array = Arrays.copyOf(array, array.length + 1);
            array[array.length - 1] = i;
        }
//        System.out.println(Arrays.toString(array));
        return array;
    }

    private void showNumbers(int[] array) {
        for(int i = 0; i < array.length; i++) {
            System.out.printf("%d\t", array[i]);
            if((i + 1) % 6 == 0) {
                System.out.println();
            }
        }
        System.out.printf("總共有%d個數字可選\n", array.length);
    }

    private void randomBets(int[] array) {
        System.out.print("隨機取6個不重複號碼:");
        int[] copy = Arrays.copyOf(array, array.length);
        // Pick 6 number in 6 loops
        // The picked one will be deleted after each loop
        for(int i = 0; i < 6; i++) {
            int index = (int) (Math.random() * copy.length);
            System.out.printf("%d\t", copy[index]);
            // Shift the elements after the picked number one place forward
            for(int j = index; j < copy.length - 1; j++) {
                copy[j] = copy[j + 1];
            }
            // Make it a new array of size - 1
            copy = Arrays.copyOf(copy, copy.length - 1);
            // System.out.println(Arrays.toString(copy));
        }
    }

}

作法 2

朋友 Peng 的方法。他排除重複號碼的作法是將抽到的號碼加上可選的最大值,然後每次抽取時判斷是否大於最大值。這作法好處是不像我的會在每次迴圈都用 copyOf() 建立新陣列,壞處是無法處理當最大值為 0 或負數的情形。若要維持可選數字的陣列不變,可在最後用迴圈將所有抽過的最大值的元素減去最大值,便還原。


    private void randomBetsNew(int[] array) {
	System.out.print("隨機取6個不重複號碼:");
        int max = findMax(array);

        // Pick 6 number in 6 loops
        for(int i = 0; i < 6; i++) {
            int index = (int) (Math.random() * array.length);
            int pickUp = array[index];
            while (pickUp > max)
            {
                index++;
                index = index > array.length - 1 ? 0 : index;
                pickUp = array[index];
            }

            System.out.printf("%d\t", array[index]);
            array[index] += max;
        }
    }

    private int findMax(int[] array) {
        Arrays.sort(array);
        return array[array.length - 1];
    }

作法 3

在 GeeksforGeeks 查到的,使用 ArrayList 的作法:Generate a random permutation of 1 to N

參考它之後照自己的習慣寫一遍。


import java.util.ArrayList;

    private ArrayList arrayListWithout(int numNotWanted) {
        ArrayList arrayList = new ArrayList<>();
        for(int i = 1; i <= 49; i++) {
            if (i / 10 == numNotWanted || i % 10 == numNotWanted) {
                continue;
            }
            arrayList.add(i);
        }
        return arrayList;
    }
    
    private void showNumbers(ArrayList<Integer> arrayList) {
        for(int i = 0; i < arrayList.size(); i++) {
            System.out.printf("%d ", arrayList.get(i));
            if((i + 1) % 6 == 0) {
                System.out.println();
            }
        }
        System.out.printf("總共有%d個數字可選\n", arrayList.size());
    }

    private void randomBetsArrayList(ArrayList<Integer> arrayList) {
        int numOfPicks = 6; // numOfPicks cannot be larger than arrayList.size(), otherwise the loop won't end
        Integer[] pickedIntegers = new Integer [numOfPicks];
        
        for(int i = 0; i < numOfPicks; i++) {
            int index = (int) (Math.random() * arrayList.size());
            Integer currentPick = arrayList.get(index);
            
            if(!isPickedBefore(currentPick, pickedIntegers)) {
                pickedIntegers[i] = currentPick;
                System.out.printf("%d ", pickedIntegers[i]);
            } else {
                i--; // Pick a duplicate, so re-pick
            }
        }
    }
    
    private boolean isPickedBefore(Integer currentPick, Integer[] pickedIntegers) {
        for(int i = 0; i < pickedIntegers.length; i++) {
            if(currentPick.equals(pickedIntegers[i])) {
                return true;
            }
        }
        return false;
    }

留言

  1. 作者已經移除這則留言。

    回覆刪除
  2. private void randomBetsNew(int[] array) {
    System.out.print("隨機取6個不重複號碼:");

    int max = findMax(array);

    // Pick 6 number in 6 loops
    for(int i = 0; i < 6; i++) {

    int index = (int) (Math.random() * array.length);
    int pickUp = array[index];

    while (pickUp > max)
    {
    index++;
    index = index > array.length - 1 ? 0 : index;
    pickUp = array[index];
    }

    System.out.printf("%d\t", array[index]);
    array[index] += max;
    }
    }

    private int findMax(int[] array) {
    Arrays.sort(array);
    return array[array.length - 1];
    }

    回覆刪除

張貼留言

這個網誌中的熱門文章

那天