Java基礎 第二節 第二十一課

我是小白呀 發表於 2020-11-27

概述

紅包文化源遠流長. 從古時候的紅色紙包, 到手機 App 中的手氣紅包, 紅包作為一種獨特的中華文化傳承至今. 之前的課程中, 我們也編寫過模擬法普通紅包的程式. 那麼今天, 我們將整合基學到的技術和知識, 編寫一個帶介面版的發紅包案例.

目的, 我們上未學習過任何與介面相關的類. 所以, 介面相關程式碼, 已經給出. 請運用所學技術分析並使用.

案例需求

紅包型別:

  1. 普通紅包: 金額均分. 不能整除的, 餘額新增到最後一份紅包中
  2. 手氣紅包: 金額隨機. 各個紅包金額累計與總金額相等

紅包場景:

  • 此案例是模擬群主給群成員法紅包, 群主位元組開啟最後一個紅包

案例分析

OpenMode

OpenMode: 一個介面, 包含一個分配方法, 用來指定紅包型別.

import java.util.ArrayList;

public interface OpenMode {
    /**
     * allocate 方法用於分配紅包
     * @param toalAmount 紅包總金額, 單位為 "分".
     * @param count 紅包個數
     * @return 返回紅包陣列
     */
    public abstract ArrayList<Integer> allocate(int toalAmount, int count);
}

RedPacketFrame

RedPacketFrame: 一個抽象類, 包含了一些屬性, 是紅包案例的介面.

import javax.swing.*;

public class RedPacketFrame extends JFrame {
    // admin: 群主名稱
    public String admin = "馬保國";
    // openMode: 紅包的型別 (普通紅包 / 手氣紅包)
    public OpenMode openMode = null;

    /**
     * 構造方法: 生成紅包介面
     * @param title 介面的標題
     */
    public RedPacketFrame(String title){
        super(title);
        frameInit();  // 介面相關的初始化操作
    }

    // set方法
    public void setAdmin(String admin) {
        this.admin = admin;
    }

    public void setOpenMode(OpenMode openMode) {
        this.openMode = openMode;
    }
}

案例實現

環境搭建

  1. 建立專案: 名稱自定義
  2. 匯入圖片: 將 pic 目錄, 匯入專案中, 與 src 目錄平級
  3. 匯入已知類: 在 scr 下建立一個包, 名稱自定義

基礎程式碼實現

定義 RedPacket 類

定義 RedPacket 類, 繼承 RedPacketFrame. 程式碼如下:

package known;

public class RedPacket extends RedPacketFrame {

    /**
     * 構造方法: 生成紅包介面
     * @param title 介面的標題
     */
    public RedPacket(String title) {
        super(title);
    }
}

定義測試類

定義測試類, 建立 RedPacket 物件. 程式碼如下:

package known;

public class Test {
    public static void main(String[] args) {
        RedPacket redPacket = new RedPacket("大紅包");
    }
}

設定群主名稱

package known;

public class Test {
    public static void main(String[] args) {
        // 建立紅包物件
        RedPacket redPacket = new RedPacket("大紅包");
        // 設定群主名稱
        redPacket.setAdmin("我是馬保國");
    }
}

普通紅包類

普通紅包, 代開方式 Common. 程式碼如下:

package known;

import known.OpenMode;
import java.util.ArrayList;

public class Common implements OpenMode {
    @Override
    public ArrayList<Integer> allocate(int totalAmount, int count) {
        // 建立儲存各個紅包金額的集合
        ArrayList<Integer> list = new ArrayList<>();
        // 定義迴圈次數, 總個數‐1次
        int time = count - 1;
        // 一次計算, 生成平均金額
        int money = totalAmount / count;
        // 迴圈分配
        for (int i = 0; i < time; i++) {
            // 新增到集合中
            list.add(money);
            // 總金額扣除已分配金額
            totalAmount -= money;
        }
        // 剩餘的金額, 為最後一個紅包
        list.add(totalAmount);
        System.out.println("普通紅包金額:" + list);
        // 返回集合
        return list;
        }
}

測試普通紅包

package known;

public class Test2 {
    public static void main(String[] args) {
        // 建立紅包物件
        RedPacket rp = new RedPacket("大紅包");
        // 設定群主名稱
        rp.setAdmin("我是馬保國");
        // 設定紅包型別
        rp.setOpenMode(new Common());  // 普通紅包
    }
}

手氣紅包

本質上, 手氣紅包就是把總金額 totalAmount 隨機分成指定的 count 份. 所以必須規定每一份金額的取值範圍. 如果過範圍太小, 可能導致後分配紅包金額特別大. 反之範圍太大, 可能導致分配夠紅包金額為 0, 不夠分. 可見, 取值範圍的定義規則, 是手氣紅包的關鍵所在.

我們規定: 每一份隨機金額範圍 (除最後一份), 最小值為 1, 最大值為當前剩餘平均金額的兩倍, 單位為 “分”.

計算公式

當前剩餘平均金額 = 剩餘總金額 / 剩餘紅包個數

在這裡插入圖片描述

手氣紅包類

手氣紅包類, 開啟方式 Lucky. 程式碼如下:

package known;

import java.util.ArrayList;
import java.util.Random;

public class Lucky implements OpenMode {
    @Override
    public ArrayList<Integer> allocate(int totalMoney, int count) {
        // 建立儲存各個紅包金額的集合
        ArrayList<Integer> list = new ArrayList<>();
        // 定義迴圈次數, 總個數‐1次
        int time = count - 1;
        // 建立隨機數物件
        Random random = new Random();
        // 迴圈分配
        for (int i = 0; i < time; i++) {
            /*
             * 每次重新計算, 生成隨機金額
             * 隨機範圍: totalMoney / count * 2, totalMoney不斷的減少,
             * count也不斷的減少, 所以這是一個可變化的範圍.
             */
            int money = random.nextInt(totalMoney / count * 2) + 1;
            // 金額新增到集合
            list.add(money);
            // 總金額扣除已分配金額
            totalMoney -= money;
            // 紅包個數‐1
            count--;
        }
        // 剩餘的金額, 為最後一個紅包
        list.add(totalMoney);
        return list;
    }
}

測試手氣紅包

package known;

public class Test3 {
    public static void main(String[] args) {
        // 建立紅包物件
        RedPacket rp = new RedPacket("大紅包");
        // 設定群主名稱
        rp.setAdmin("我是馬保國");
        // 設定紅包型別, 二選一
        // rp.setOpenMode(new Common());  // 普通紅包
        rp.setOpenMode(new Lucky());  // 手氣紅包
    }
}