抽卡模拟系统(包含图形界面,结果可存储到数据库中)
軟件工程的大作業,要求寫一個系統。自己平時玩過一些抽卡手游,類似于《原神》、《FGO》之類的,因此想試一試寫一個類似的程序。
這篇文章受到了這個講解抽卡機制的b站視頻的啟發:
https://www.bilibili.com/video/BV1LE411H79s?from=search&seid=1515395401480087823
另外我也參考了其它作者寫的抽卡程序,在此一并表示感謝。
該程序包含以下功能:
- 自定義☆/☆☆/☆☆☆概率。
- 自定義是否有概率Up,及Up概率的值(0-100%)。
- 自定義是否有大保底,及大保底的數量。
- 單抽。
- 十連抽。
- 小保底(即十連保底)。
- 大保底。
- 圖形界面。
- 數據庫。
概念簡述
概率Up:當Up概率為70%時,若某次抽卡結果是☆☆☆,則該☆☆☆有70%概率是限定☆☆☆,30%概率是普通☆☆☆。
小保底(十連保底):對于十連抽中累計九次都沒出現☆☆/☆☆☆的玩家,使其第十次抽取必為☆☆/☆☆☆中的一種。
大保底:對于抽取次數到達管理員規定的大保底次數的前一次時仍未抽取到up角色的非酋玩家,那么下一次抽取必定獲得☆☆☆角色。
模塊介紹
前三個模塊是主要的核心算法,可以實現除了圖形界面和數據庫的所有功能。
Main模塊中輸入概率、概率Up、保底后運行,可以輸出單抽和十連抽的結果,是我前期進行測試時使用的。
Setting(設置概率、概率Up、保底)
package 抽卡系統; import java.util.Scanner; public class Setting {/** 設置☆/☆☆/☆☆☆概率* 設置是否有概率up* 設置是否有保底*/Scanner sc=new Scanner(System.in); /*-------------------------------------------------------------------------------------------*/ public double [] Chance() {//設置☆/☆☆/☆☆☆概率double[] allchance= new double[3];//創建一個double數組,用于返回所有概率for(int i=0;i<3;i++)allchance[i]=0;System.out.print("請分別設置☆☆/☆☆☆出現概率");System.out.println("(☆概率為100%-☆☆/☆☆☆概率之和)");double twostarchance=0;double threestarchance=0;System.out.print("請分別輸入☆☆/☆☆☆概率(小數):");if (sc.hasNextDouble()) {twostarchance = sc.nextDouble();threestarchance=sc.nextDouble();if(twostarchance+threestarchance>1) {System.out.println("☆☆/☆☆☆概率之和超過100%!");return allchance;//數值不符合要求,退出函數}else if(twostarchance<0||threestarchance<0) {System.out.println("☆☆/☆☆☆概率<0!");return allchance;}} else {System.out.println("輸入的不是小數!");return allchance;}double onestarchance=1-twostarchance-threestarchance;System.out.println("概率分別是:");System.out.println("☆概率:"+onestarchance);System.out.println("☆☆概率:"+twostarchance);System.out.println("☆☆☆概率:"+threestarchance);allchance[0]=onestarchance;allchance[1]=twostarchance;allchance[2]=threestarchance;return allchance;} /*-------------------------------------------------------------------------------------------*/ public double UpChance() {//是否概率Updouble upchance=0;System.out.print("請輸入up概率(小數)(0代表不up):");if (sc.hasNextDouble()) {upchance=sc.nextDouble();if(upchance>1) {System.out.println("Up概率超過100%!");return -1;}else if(upchance<0) {System.out.println("Up概率<0!");return -1;}} else {System.out.println("輸入的不是小數!");return -1;}System.out.println("Up概率是:");System.out.println(upchance);return upchance;} /*-------------------------------------------------------------------------------------------*/ public int MinimumGuarantee() {//是否保底int minimumguarantee=0;System.out.print("請輸入保底數(整數)(0代表無保底):");if (sc.hasNextInt()) {minimumguarantee=sc.nextInt();if(minimumguarantee<0) {System.out.println("保底不可為負數");return -1;}} else {System.out.println("輸入的不是整數!");return -1;}System.out.println("保底數是:");System.out.println(minimumguarantee);return minimumguarantee;} /*-------------------------------------------------------------------------------------------*/ }LuckyDraw(單抽、十連抽算法)
package 抽卡系統;public class LuckyDraw {/** 進行單抽或十連抽* 包含主要抽卡算法*/ public static int counter=0;//類變量,統計已抽次數public static int flag1=0;//類變量,小保底計數器,統計多少抽未出小保底,用來計算小保底(出小保底后清零)public static int flag2=0;//類變量,大保底計數器,統計多少抽未出大保底,用來計算大保底(出大保底后清零) /*-------------------------------------------------------------------------------------------*/ public String[] LuckyDrawTen(double allchance[],double upchance,int minimumguarantee){//十連抽,將結果儲存在字符串數組中String[] result = new String[10];for(int i=0;i<10;i++){result[i]=Draw(allchance,upchance,minimumguarantee);}return result;//返回字符串數組} /*-------------------------------------------------------------------------------------------*/public String LuckyDrawOne(double allchance[],double upchance,int minimumguarantee){//單抽,將結果儲存在字符串中String result=Draw(allchance,upchance,minimumguarantee);return result;//返回字符串} /*-------------------------------------------------------------------------------------------*/ public String Draw(double allchance[],double upchance,int minimumguarantee) {//抽卡算法String str="Null";if(flag2!=minimumguarantee-1&&flag1==9)//十連保底(小保底),條件:不觸發大保底且累計九次都未出☆☆/☆☆☆(flag1=9)//結果:出☆☆/☆☆☆{flag2++;int per=(int) (Math.random() * 101); if(per>=0&&per<=allchance[0]*100+allchance[1]*100) {//出☆☆str="☆☆";flag1=0;//出☆☆,清零小保底計數器counter++;return str;}else {//出☆☆☆,判斷是否是up☆☆☆flag2=0;//出☆☆☆,清零大保底計數器flag1=0;//同時清零小保底計數器int mgper=(int) (Math.random() * 101);if(upchance!=0&&mgper>=0&&mgper<=upchance*100) {//有概率up且抽到概率upstr="限定☆☆☆"; counter++;return str;}else if(upchance==0){//無概率upstr="☆☆☆"; counter++;return str;}else {//有概率up但未抽到str="普通☆☆☆";counter++;return str;}} }else if(minimumguarantee!=0&&flag2==minimumguarantee-1)//大保底,條件:存在大保底且已抽次數等于大保底前一次且仍未出☆☆☆//出☆☆☆{flag2=0;//出☆☆☆,清零大保底計數器flag1=0;//同時清零小保底計數器int mgper=(int) (Math.random() * 101);//判斷是否是限定☆☆☆if(upchance!=0&&mgper>=0&&mgper<=upchance*100) {//有概率up且抽到概率upstr="限定☆☆☆";}else if(upchance==0) {//無概率upstr="☆☆☆";}else{//有概率up但未抽到str="普通☆☆☆";}counter++; return str; }else//隨機判斷概率,出☆/☆☆/☆☆☆{int per=(int) (Math.random() * 101);if(per>=0&&per<=allchance[0]*100) {//出☆str="☆";counter++;flag1++;flag2++;return str;}else if(per>=allchance[0]*100+1&&per<=allchance[0]*100+allchance[1]*100) {//出☆☆str="☆☆";flag1=0;//出☆☆,清零小保底計數器flag2++;counter++;return str;}else {//出☆☆☆,判斷是否是up☆☆☆flag2=0;//出☆☆☆,清零大保底計數器flag1=0;//同時清零小保底計數器int mgper=(int) (Math.random() * 101);if(upchance!=0&&mgper>=0&&mgper<=upchance*100) {//有概率up且抽到概率upstr="限定☆☆☆"; counter++;return str;}else if(upchance==0){//無概率upstr="☆☆☆"; counter++;return str;}else {//有概率up但未抽到str="普通☆☆☆"; counter++;return str;}}}} /*-------------------------------------------------------------------------------------------*/}Main(在控制臺輸出抽卡結果,便于測試)
package 抽卡系統;public class Main {public static void main(String[] args) {Setting s=new Setting();LuckyDraw ld =new LuckyDraw();System.out.println("您的單次抽卡結果是:");System.out.println(ld.LuckyDrawOne(s.Chance(), s.UpChance(), s.MinimumGuarantee()));System.out.println("您的十連抽卡結果是:");String []results=ld.LuckyDrawTen(s.Chance(), s.UpChance(), s.MinimumGuarantee());for(int i=0;i<10;i++) {System.out.println(results[i]);}System.out.println("已抽:"+LuckyDraw.counter);s.sc.close();}}輸出結果
Window(創建窗口)
package 抽卡系統; import java.awt.*;public class Window {public static void main(String[] args) {ComponentInWindow win=new ComponentInWindow();ButtonListener1 bl1=new ButtonListener1();win.setCommandListener1(bl1);ButtonListener2 bl2=new ButtonListener2();win.setCommandListener2(bl2);win.setBackground(Color.white);win.setBounds(400,100,800,800);win.setTitle("抽卡系統"); } }ComponentInWindow(設置組件)
package 抽卡系統; import javax.swing.*; import java.awt.*;public class ComponentInWindow extends JFrame{JTextField ChanceTextField,UpChanceTextField,MinimumGuaranteeTextField;JLabel ChanceLabel,UpChanceLabel,MinimumGuaranteeLabel;JButton OneDrawButton,TenDrawsButton;JTextArea results;CommandListener listener1;public ComponentInWindow(){init();setVisible(true);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}void init() {//初始化,添加組件setLayout(new FlowLayout());//流式布局ChanceTextField=new JTextField(10);//創建三個文本框,來獲取輸入的概率UpChanceTextField=new JTextField(10);MinimumGuaranteeTextField=new JTextField(10);ChanceLabel=new JLabel("概率");//創建三個標簽,表明文本框內容UpChanceLabel=new JLabel("Up概率");MinimumGuaranteeLabel=new JLabel("保底數");add(ChanceLabel);add(ChanceTextField);add(UpChanceLabel);add(UpChanceTextField);add(MinimumGuaranteeLabel);add(MinimumGuaranteeTextField);OneDrawButton=new JButton("單次抽取");//創建兩個按鈕TenDrawsButton=new JButton("十連抽取");add(OneDrawButton);add(TenDrawsButton);results=new JTextArea(38,28);//創建文本區add(results);JScrollPane jsp=new JScrollPane(results);//創建滾動條results.setEditable(false);add(jsp);}void setCommandListener1(CommandListener listener) {//給單抽按鈕添加單抽按鈕監視器this.listener1=listener;listener1.setJTextField(ChanceTextField,UpChanceTextField,MinimumGuaranteeTextField); listener1.setJTextArea(results);OneDrawButton.addActionListener(listener1); }void setCommandListener2(CommandListener listener) {//給十連按鈕添加十連按鈕監視器this.listener1=listener;listener1.setJTextField(ChanceTextField,UpChanceTextField,MinimumGuaranteeTextField);listener1.setJTextArea(results);TenDrawsButton.addActionListener(listener1);}}由于我比較懶,所以用了流式布局。如果你想讓窗口上各組件更加整齊,可以單獨設置各組件的大小和位置。
CommandListener (提供接口,由ButtonListener1和ButtonListener2來實現)
package 抽卡系統; import java.awt.event.*; import javax.swing.*;public interface CommandListener extends ActionListener{public void setJTextField(JTextField fieldtext1,JTextField fieldtext2,JTextField fieldtext3);public void setJTextArea(JTextArea areatext); }ButtonListener1(單抽按鈕監視器)
數據庫的連接和存儲都直接放在了actionPerformed()方法中。如果想要寫的更規范的話可以單獨封裝一下。
不需要的話可以直接刪除“//-------------------------------------------------------”中間的部分。
注:數據庫使用的是SQL Sever。
ButtonListener2(十連按鈕監視器)
同上,偷懶把數據庫的連接和存儲都直接放在了actionPerformed()方法中。
不需要的話可以直接刪除“//-------------------------------------------------------”中間的部分。
注:數據庫使用的是SQL Sever。
輸出結果
數據庫存儲結果
代碼寫的不是很成熟,如果發現了什么問題還請指出,謝謝。
總結
以上是生活随笔為你收集整理的抽卡模拟系统(包含图形界面,结果可存储到数据库中)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用VLC组播测试及VLC收不到UDP组
- 下一篇: mysql面试题1