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;
}
作者已經移除這則留言。
回覆刪除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];
}
Thanks!
刪除