您好,登錄后才能下訂單哦!
游戲規則
從撲克中每次取出4張牌。使用加減乘除,第一個能得出24者為贏。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求編程解決24點游戲。
基本要求
解表達式基本思路
采用窮舉法列舉每一種存在的可能,接著判斷是否值為24,如果等于24,則將表達式存入Set集合,最終遍歷Set集合即可得到所有表達式。具體思路如下:
1.采用隨機數生成4個符合要求的數據,假設四個數據為n1,n2,n3,n4 。
2.把數據相互組合可以得到如下組合:n1和n2 ,n1和n3,n1和n4,n2和n3,n2和n4,n3和n4
3.將上面的組合進行各種可能的運算例如:n1+n2,n1-n2,n2-n1,n1*n2,n1/n2,n2/n1等等。
4.把上面組合計算出來的結果存入進對應的數組中例如:組合相加的結果存入add數組,相減的結果存入sub數組……最終將這些數組存入一個list集合中,目的是為了方便通過循環遍歷出每一種組合。
5.通過循環去遍歷每一種組合,把這些組合在一起進行相加,相減等運算,記錄結果為24的表達式。在這里需要注意的是,因為數組得值為兩個數字的運算結果,所以需要根據當前循環變量的值和list集合以及數組存入數據的順序去把表達式格式化成四個數字組成的表達式,否則表達式只有兩個數字。
玩家運算基本思路
在java中使用Timer和Canender即可實現定時的功能,而判斷表達式是否正確,在java中使用Script引擎調用eval方法即可判斷表達式的值是否正確,具體思路如下:
1.初始化生命值,和分數
2.由系統給出四個數字
3.玩家給出答案
4.判斷給出的答案中的數字和系統給出的數字是否吻合,如果吻合進入5,否則,生命值減一。
5.借助Timer類的schedule()判斷是否超時,如果沒有超時,進入6,否則,生命值減一。
6.借助script引擎的eval()方法可以判斷表達式是否正確,如果正確,分數加一,否則,生命值減一。
當生命值大于0時執行2,3,4,5,6操做,否則將當前分數寫入文件。
流程圖如下圖所示
編碼
Game類,主要實現由系統隨機生成數據,并計算可能的表達式
為了避免除零異常采用了float類型的數組進行存儲
import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Random; import java.util.Scanner; import java.util.Set; /** * * Title: Test Description: 1. 采用隨機數生成4個符合要求的數據,假設四個數據為n1,n2,n3,n4 。 * 2.把數據相互組合可以得到如下組合:n1和n2 ,n1和n3,n1和n4,n2和n3,n2和n4。 * 3.將上面的組合進行各種可能的運算例如:n1+n2,n1-n2,n2-n1,n1*n2,n1/n2,n2/n1等等。 * 4.把上面組合計算出來的結果存入進對應的數組中例如:組合相加的結果存入add數組,相減的結果存入sub數組……最終將這些數組存入一個list集合中,目的是為了方便通過循環遍歷出每一種組合。 * 5.通過循環去遍歷每一種組合,把這些組合在一起進行相加,相減等運算,記錄結果為24的表達式 * @author jianglei */ public class Game { static Set<String> set = new HashSet<String>();// 使用Set存儲算式表達式可以避免有重復的結果 float[] data = new float[4];// 存放數據的集合 float[] add = new float[6];// 存放組合相加的結果的集合 float[] sub1 = new float[6];// 存放相減的結果(兩個數相減的結果存在兩種可能) float[] sub2 = new float[6];// 存放相減的結果 float[] mul = new float[6];// 存放相乘 float[] div1 = new float[6];// 存放相除(兩個數相除的結果存在兩種可能) float[] div2 = new float[6];// 存放相除 List<float[]> list = new ArrayList<float[]>();// 存放組合結果運算的集合 /** * * Title: combine * </p> * Description: 該方法用來獲取每兩個數字的組合組合, 用1代表第一個數字,2代表第二個數字....共有六種組合方式,分別如下: * 1和2,1和3,1和 4,2和 3,2和 4,3和 4 在上面的組合中,每一種組合都對應著 加減乘除 這四種運算 * 將上述的組合的每種計算結果存入上面聲明的集合 */ public void conbine(float n1, float n2, float n3, float n4) { add[0] = n1 + n2; add[1] = n1 + n3; add[2] = n1 + n4; add[3] = n2 + n3; add[4] = n2 + n4; add[5] = n3 + n4; sub1[0] = n1 - n2; sub1[1] = n1 - n3; sub1[2] = n1 - n4; sub1[3] = n2 - n3; sub1[4] = n2 - n4; sub1[5] = n3 - n4; sub1[5] = n3 + n4; sub2[0] = n2 - n1; sub2[1] = n3 - n1; sub2[2] = n4 - n1; sub2[3] = n3 - n2; sub2[4] = n4 - n2; sub2[5] = n4 - n3; mul[0] = n2 * n1; mul[1] = n3 * n1; mul[2] = n4 * n1; mul[3] = n3 * n2; mul[4] = n4 * n2; mul[5] = n4 * n3; div1[0] = n1 / n2; div1[1] = n1 / n3; div1[2] = n1 / n4; div1[3] = n2 / n3; div1[4] = n2 / n4; div1[5] = n3 / n4; div2[0] = n2 / n1; div2[1] = n3 / n1; div2[2] = n4 / n1; div2[3] = n3 / n2; div2[4] = n4 / n2; div2[5] = n4 / n3; list.add(add);// 把各種組合加入到list集合中,方便通過循環來遍歷每一種組合方式 list.add(sub1); list.add(sub2); list.add(mul); list.add(div1); list.add(div2); } public void getData() { Random r = new Random(); // 獲取1——13的的數字的集合 data[0] = r.nextInt(12) + 1; data[1] = r.nextInt(12) + 1; data[2] = r.nextInt(12) + 1; data[3] = r.nextInt(12) + 1; System.out.print("四個數字為:"); for (float f : data) switch ((int) f) {// 將11,12,13,1變成J,Q,K,A case 1: System.out.print("A" + " "); break; case 11: System.out.print("J" + " "); break; case 12: System.out.print("O" + " "); break; case 13: System.out.print("K" + " "); break; default: System.out.print((int) f + " "); break; } System.out.println(); boolean flag = false;// 通過該變量去判斷是否存在表達式 conbine(data[0], data[1], data[2], data[3]); for (int a = 0; a < 3; a++) {// 有種組合方式,分別遍歷每一種組合方法 for (int b = 0; b < 6; b++) {// 窮舉每一個組合和他們之間的運算 for (int c = 0; c < 6; c++) {// 判斷每一種組合的每一種運算結果是否等于24 if ((list.get(b)[a] + list.get(c)[5 - a]) == 24) { DataFormat.judge(a, b, c, data, "+", set); flag = true; } // 減法 if ((list.get(b)[a] - list.get(c)[5 - a]) == 24) { DataFormat.judge(a, b, c, data, "-", set); } if ((list.get(b)[5 - a] - list.get(c)[a]) == 24) { DataFormat.judge(a, b, c, data, "-", set); flag = true; } // 乘法 if ((list.get(b)[a] * list.get(c)[5 - a]) == 24) { DataFormat.judge(a, b, c, data, "*", set); flag = true; } // 除法 if ((list.get(b)[a] / list.get(c)[5 - a]) == 24) { DataFormat.judge(a, b, c, data, "/", set); flag = true; } if ((list.get(b)[5 - a] / list.get(c)[a]) == 24) { DataFormat.judge(a, b, c, data, "/", set); flag = true; } } } } if (!flag) System.out.println("沒有表達式滿足條件"); }
AutoGame類主要實現由系統給定數值,用戶輸入表達式來根據結過進行計分,并將分數寫入文件
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.Date; import java.util.Random; import java.util.Scanner; import java.util.Timer; import java.util.TimerTask; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class AutoGame { static boolean flag = true;//該變量標識是否超時 static int life = 3;//初始化生命值 static int score=0;//初始化分數 /** *開始游戲的方法,該方法通過當前生命值判斷是否結束 */ public void start() throws IOException { Calendar date = Calendar.getInstance();//實例化Calendar對象 while(life>0) {//當生命值大于0才會進行 flag=true;//初始化分數標記 date.setTime(new Date()); date.add(Calendar.SECOND, 20);//設置限定時間 Timer timer = new Timer(); //當達到限定時間將會執行run()方法,即把全局變量flag變為false timer.schedule(new RemindTask(), date.getTime()); int answer = answer(); switch(answer) { case -1: System.out.println("表達式錯誤!! 當前生命值為"+life+" 分數為:"+score); break; case -2: System.out.println("輸入超時!! 當前生命值為"+life+" 分數為:"+score); break; case -3: System.out.println("結果錯誤!! 當前生命值為"+life+" 分數為:"+score); break; case 1: System.out.println("正確,得到1分獎勵!! 當前生命值為"+life+" 分數為:"+score); break; } System.out.println("----------"); } System.out.println("游戲結束……分數為: "+score);//循環結束也就是生命值為0,打印游戲結束 saveScore(score);//將玩家當前分數存入文件 return; } /** * * Title: getData</p> * Description:給定任意的數據 * @return */ private float[] getData() { float[] data = new float[4]; Random r = new Random();//隨機生成四個數據存入數組中 data[0] = r.nextInt(12) + 1; data[1] = r.nextInt(12) + 1; data[2] = r.nextInt(12) + 1; data[3] = r.nextInt(12) + 1; System.out.print("四個數字為:"); for (float f : data) switch ((int) f) { case 1: System.out.print("A" + " "); break; case 11: System.out.print("J" + " "); break; case 12: System.out.print("O" + " "); break; case 13: System.out.print("K" + " "); break; default: System.out.print((int) f + " "); break; } System.out.println("請開始作答,時間20秒"); return data; } /** * * Title: answer</p> * Description:根據用戶輸入返回false或true * 1.輸入不含給定值,返回FALSE * 2.輸入超時,返回false * 3.輸入表達式的值不為24,返回false * 否則,返回true * @return -1代表輸入的表達式與系統給出的數字不吻合 * @return -2代表用戶計算結果超時 * @return -3代表結果錯誤 * @return 1代表用戶計算正確 */ public int answer() { Scanner sc = new Scanner(System.in); float[] data = getData();//獲取給定的數據 //獲取script引擎,調用eval()方法來判斷表達式是否正確 ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn"); String exper = sc.next(); try { String res = String.valueOf(scriptEngine.eval(exper)); for (int i = 0; i < data.length; i++) if (!exper.contains(data[i] + "")) {//輸入的表達式不含給定的值 life--; return -1; } if(!flag) {//判斷超時 life--; return -2; } if (res.equals("24")) {//回答正確并且沒有超時 score++;//分數加一 return 1; } life--; } catch (ScriptException e) { System.out.println("表達式輸入不合法"); } return -3; } /** * Title: saveScore</p> * Description: 該方法表示將玩家當前分數存入TopList.txt文件 * @param score 需要存入的分數 * @throws IOException */ public static void saveScore(int score) throws IOException { FileOutputStream fos = new FileOutputStream("e:/TopList.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write((score+"").getBytes());//把分數寫入文件 bos.close(); } public static void main(String[] args) throws IOException { saveScore(1); } } /** * * Title: RemindTask * Description:該TimerTask并且重寫run()可以實現在指定的定時時間執行run方法的內容 * @author jianglei */ class RemindTask extends TimerTask { @Override public void run() { AutoGame.flag = false;//當超時會把全局變量flag變為false } }
DataFormat類根據a b c是三個循環變量將兩個組合數字的運算格式化成四個數字的表達式
由于代碼比較長,在這里只留一種情況的,其余的情況與它類似
import java.util.Set; /** * * Title: GetFoamat * Description: 該類通過在循環中的a b c的值判斷出當前所參與運算的值與參加運算的符號,假設四個值為n0,n1,n2,n3 * 形參 a、b、c為循環變量,形參n數組為參與運算的四個數字,形參op表示當前進行的運算類型,形參set為存儲結果的容器 */ public class DataFormat { public static void judge(int a,int b,int c,float[]n,String op,Set<String> set) { StringBuilder sb = new StringBuilder(); if(a==0) {//n0和n1 與n2和n3之間的運算 if(b==0) {//n0+n1 if(c==0) {//n2+n3 sb.append("(").append(n[0]).append("+").append(n[1]).append(")").append(op).append("(").append(n[2]).append("+").append(n[3]).append(")").append("=24"); }if(c==1) {//n2-n3 sb.append("(").append(n[0]).append("+").append(n[1]).append(")").append(op).append("(").append(n[2]).append("-").append(n[3]).append(")").append("=24"); }if(c==2) {//n3-n2 sb.append("(").append(n[0]).append("+").append(n[1]).append(")").append(op).append("(").append(n[3]).append("-").append(n[2]).append(")").append("=24"); }if(c==3) {// n2*n3 sb.append("(").append(n[0]).append("+").append(n[1]).append(")").append(op).append("(").append(n[2]).append("*").append(n[3]).append(")").append("=24"); }if(c==4) {// n2/n3 sb.append("(").append(n[0]).append("+").append(n[1]).append(")").append(op).append("(").append(n[2]).append("/").append(n[3]).append(")").append("=24"); }if(c==5) {// n3/n2 sb.append("(").append(n[0]).append("+").append(n[1]).append(")").append(op).append("(").append(n[3]).append("/").append(n[2]).append(")").append("=24"); } //將運算表達式存入容器 set.add(sb.toString()); //將sb清空 sb = new StringBuilder(); }if(b==1) {//n0-n1 //由于這種代碼篇幅比較長,在這里省略了,思路和上面的一致 }
測試
import java.io.IOException; import java.util.Scanner; public class Test { public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); Game t = new Game(); System.out.println("----------"); System.out.println("1.隨機生成數判斷"); System.out.println("2.用戶輸入運算式"); System.out.println("請選擇"); char op = sc.next().charAt(0); switch (op) { case '1': t.getData(); for (String str : t.set) { System.out.println(str.replaceAll(".0", "")); } break; case '2': AutoGame a = new AutoGame(); a.start(); break; default: System.out.println("輸入錯誤"); } } }
運行結果
以下用戶輸入表達式的運行結果
測試過程中在該情況下的測試數據是由自己給出的為1 1 12 12這四個數字
分數存入文件
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。