模擬微信搶紅包demo,生成隨機數

熊仙森發表於2018-12-18


概述

經常搶紅包會發現,很大的概率是在一開始得時候搶的紅包越大,越靠後越小(大概率是這種情況,這是我的經驗之談,也不是一定的)。

對於金額是如何確定的,我們可大概猜測是在使用者提交之後就確定的數值,也可以是在使用者每次點選的時候觸發,確定金額。這兩種方式並沒有本質的區別。但是對於金額的確定方式,我猜測是用隨機數生成的。
  
  大概思路一開始的時候,隨機數取值的範圍較大,出現大數的可能性更大。越往後可分配金額越少,故而金額越小(不一定,下面的demo也多次出現後面大金額的情況,我都要懷疑我的猜想了)
  
  下面先解釋一下生成隨機數有兩種方式:Math.random()方法和Random類
  然後再分析一下搶紅包的原始碼

隨機數方法方法

Math.random()方法

該方法預設生成大於等於0.0小於1.0的double型隨機數,即0<=Math.random()<=1.0,雖然只能生成0~1之間的數字,但是隻要是在後面乘上一個範圍值,就可以表示任意範圍的數。

(int)(Math.Random()*n) ===>返回大於等於0小於n的隨機數
m+(int)(Math.Random()*n) ===>返回大於等於m小於m+n(不包括m+n)的隨機數

下面以一個猜數字遊戲來舉例說明

/**
 * 猜數字遊戲
 */
import java.util.Scanner;

public class NumGame {
	public static void main(String[] args) {
		System.out.println("——————猜數字遊戲——————\n");
		int iNum;
		int iGuess;
		Scanner in = new Scanner(System.in);// 建立掃描器物件,用於輸入
		iNum = (int) (Math.random() * 100);// 生成1到100之間的隨機數
		System.out.print("請輸入你猜的數字:");
		iGuess = in.nextInt(); // 輸入首次猜測的數字
		while ((iGuess != -1) && (iGuess != iNum))// 判斷輸入的數字不是-1或者基準數
		{
			if (iGuess < iNum)// 若猜測的數字小於基準數,則提示使用者輸入的數太小,並讓使用者重新輸入
			{
				System.out.print("太小,請重新輸入:");
				iGuess = in.nextInt();
			} else// 若猜測的數字大於基準數,則提示使用者輸入的數太大,並讓使用者重新輸入
			{
				System.out.print("太大,請重新輸入:");
				iGuess = in.nextInt();
			}
		}
		if (iGuess == -1)// 若最後一次輸入的數字是-1,迴圈結束的原因是使用者選擇退出遊戲
		{
			System.out.println("退出遊戲!");
		} else// 若最後一次輸入的數字不是-1,使用者猜對數字,獲得成功,遊戲結束
		{
			System.out.println("恭喜你,你贏了,猜中的數字是:" + iNum);
		}
		System.out.println("\n———————遊戲結束———————");
	}
}

在這裡插入圖片描述

Random類

除了Math類中的random方法外,Java中還提供了一種可以獲取隨機數的方式,那就是Java.util.Random類,該類表示一個隨機數生成器,可以通過例項化一個Random物件來建立一個隨機數生成器。

這種方式例項化物件時,Java編譯器一系統當前時間作為隨機數生辰器的種子,因為每時每刻的時間不可能相同,所以生成的隨機數將不同,但是如果執行速度太快,也會生成兩次執行結果相同的隨機數。

同時還提供了各種型別隨機數的方法,如下表。

方法 返回值 功能描述
nextInt() int 返回一個隨機整數
nextInt(int n) int 返回一個大於0小於n的隨機整數
nextLong() long 返回一個隨機長整型值
nextBoolean() boolean 返回一個隨機布林型值
nextFloat() float 返回一個隨機浮點型值
nextDouble() double 返回一個隨機雙精度型值
nextGaussian() double 返回一個概率密度為高斯分佈的雙精度值

搶紅包!!

import java.text.DecimalFormat;
import java.util.Random;
import java.util.Scanner;

/**
 * 模擬微信搶紅包功能
 */
public class RedBags { //建立一個RedBags類
	public static void main(String[] args) {
		System.out.println("—————————模擬微信搶紅包—————————\n"); 
		Scanner sc = new Scanner(System.in); //控制檯輸入
		System.out.print("請輸入要裝入紅包的總金額(元):"); 
		double total = sc.nextDouble(); //輸入“紅包的總金額”
		System.out.print("請輸入紅包的個數(個):"); 
		int bagsnum = sc.nextInt(); //輸入“紅包的個數”
		double min = 0.01; //初始化“紅包的最小金額”
		Random random = new Random(); //建立隨機數物件random
		DecimalFormat df = new DecimalFormat("###,###,###.##"); //建立DecimalFormat類的物件df,並設定格式
		for (int i = 1; i < bagsnum; i++) { //設定“迴圈”,邊界值是紅包數-1
		//保證後面至少有(bagsnum - i) 個 最小金額可以發
			double safe = (total - (bagsnum - i) * min) / (bagsnum - i); //通過公式模擬數學中的離散模型
			double money = (double) random.nextInt((int) ((safe - min) * 100)) / 100 + min; //根據離散模型得到每個紅包的金額
			total = total - money; //替換total的值
			String temp = df.format(money); //呼叫format()方法,對數字money格式化
			System.out.println("第" + i + "個紅包:" + temp + "元"); //輸出結果
		}
		String left = df.format(total); //呼叫format()方法,對數字total格式化
		//輸出最後一個紅包
		System.out.println("第" + bagsnum + "個紅包:" + left + "元"); //輸出結果
		sc.close(); //關閉控制檯輸入
	}
}

在這裡插入圖片描述

相關文章