java實現(xiàn)24點(diǎn)游戲

游戲規(guī)則

創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比慈利網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式慈利網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋慈利地區(qū)。費(fèi)用合理售后完善,10年實體公司更值得信賴。

從撲克中每次取出4張牌。使用加減乘除,第一個能得出24者為贏。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求編程解決24點(diǎn)游戲。

基本要求

  • 隨機(jī)生成4個代表撲克牌牌面的數(shù)字字母,程序自動列出所有可能算出24的表達(dá)式
  • 列出表達(dá)式無重復(fù)
  • 用戶初始生命值為一給定值(比如3),初始分?jǐn)?shù)為0。隨機(jī)生成4個代表撲克牌牌面的數(shù)字或字母,由用戶輸入包含這4個數(shù)字或字母的運(yùn)算表達(dá)式(可包含括號),如果表達(dá)式計算結(jié)果為24則代表用戶贏了此局。
  • 使用計時器要求用戶在規(guī)定時間內(nèi)輸入表達(dá)式,如果規(guī)定時間內(nèi)運(yùn)算正確則加分,超時或運(yùn)算錯誤則進(jìn)入下一題并減少生命值(不扣分)。
  • 所有成績均可記錄在TopList.txt文件中。

解表達(dá)式基本思路

采用窮舉法列舉每一種存在的可能,接著判斷是否值為24,如果等于24,則將表達(dá)式存入Set集合,最終遍歷Set集合即可得到所有表達(dá)式。具體思路如下:

1.采用隨機(jī)數(shù)生成4個符合要求的數(shù)據(jù),假設(shè)四個數(shù)據(jù)為n1,n2,n3,n4 。
2.把數(shù)據(jù)相互組合可以得到如下組合:n1和n2 ,n1和n3,n1和n4,n2和n3,n2和n4,n3和n4
3.將上面的組合進(jìn)行各種可能的運(yùn)算例如:n1+n2,n1-n2,n2-n1,n1*n2,n1/n2,n2/n1等等。
4.把上面組合計算出來的結(jié)果存入進(jìn)對應(yīng)的數(shù)組中例如:組合相加的結(jié)果存入add數(shù)組,相減的結(jié)果存入sub數(shù)組……最終將這些數(shù)組存入一個list集合中,目的是為了方便通過循環(huán)遍歷出每一種組合。
5.通過循環(huán)去遍歷每一種組合,把這些組合在一起進(jìn)行相加,相減等運(yùn)算,記錄結(jié)果為24的表達(dá)式。在這里需要注意的是,因為數(shù)組得值為兩個數(shù)字的運(yùn)算結(jié)果,所以需要根據(jù)當(dāng)前循環(huán)變量的值和list集合以及數(shù)組存入數(shù)據(jù)的順序去把表達(dá)式格式化成四個數(shù)字組成的表達(dá)式,否則表達(dá)式只有兩個數(shù)字。

  • 需要注意的是:在遍歷集合的過程中,由于集合中存入的數(shù)組的數(shù)據(jù)為兩個數(shù)據(jù)組合的形式,所以遍歷是只需要控制好下標(biāo),使的每一個表達(dá)式中只有n1,n2,n3,n4這四個數(shù)據(jù),而不會出現(xiàn)類似于n1,n2,n1,n3 這種組合的方式。
  • 具體的流程圖入下圖所示:

java實現(xiàn)24點(diǎn)游戲

玩家運(yùn)算基本思路

在java中使用Timer和Canender即可實現(xiàn)定時的功能,而判斷表達(dá)式是否正確,在java中使用Script引擎調(diào)用eval方法即可判斷表達(dá)式的值是否正確,具體思路如下:

1.初始化生命值,和分?jǐn)?shù)
2.由系統(tǒng)給出四個數(shù)字
3.玩家給出答案
4.判斷給出的答案中的數(shù)字和系統(tǒng)給出的數(shù)字是否吻合,如果吻合進(jìn)入5,否則,生命值減一。
5.借助Timer類的schedule()判斷是否超時,如果沒有超時,進(jìn)入6,否則,生命值減一。
6.借助script引擎的eval()方法可以判斷表達(dá)式是否正確,如果正確,分?jǐn)?shù)加一,否則,生命值減一。
當(dāng)生命值大于0時執(zhí)行2,3,4,5,6操做,否則將當(dāng)前分?jǐn)?shù)寫入文件。

流程圖如下圖所示

java實現(xiàn)24點(diǎn)游戲

編碼

Game類,主要實現(xiàn)由系統(tǒng)隨機(jī)生成數(shù)據(jù),并計算可能的表達(dá)式

為了避免除零異常采用了float類型的數(shù)組進(jìn)行存儲

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. 采用隨機(jī)數(shù)生成4個符合要求的數(shù)據(jù),假設(shè)四個數(shù)據(jù)為n1,n2,n3,n4 。
 * 2.把數(shù)據(jù)相互組合可以得到如下組合:n1和n2 ,n1和n3,n1和n4,n2和n3,n2和n4。
 * 3.將上面的組合進(jìn)行各種可能的運(yùn)算例如:n1+n2,n1-n2,n2-n1,n1*n2,n1/n2,n2/n1等等。 
 * 4.把上面組合計算出來的結(jié)果存入進(jìn)對應(yīng)的數(shù)組中例如:組合相加的結(jié)果存入add數(shù)組,相減的結(jié)果存入sub數(shù)組……最終將這些數(shù)組存入一個list集合中,目的是為了方便通過循環(huán)遍歷出每一種組合。
 * 5.通過循環(huán)去遍歷每一種組合,把這些組合在一起進(jìn)行相加,相減等運(yùn)算,記錄結(jié)果為24的表達(dá)式
 * @author jianglei
 */
public class Game {
 static Set<String> set = new HashSet<String>();// 使用Set存儲算式表達(dá)式可以避免有重復(fù)的結(jié)果
 float[] data = new float[4];// 存放數(shù)據(jù)的集合
 float[] add = new float[6];// 存放組合相加的結(jié)果的集合
 float[] sub1 = new float[6];// 存放相減的結(jié)果(兩個數(shù)相減的結(jié)果存在兩種可能)
 float[] sub2 = new float[6];// 存放相減的結(jié)果
 float[] mul = new float[6];// 存放相乘
 float[] div1 = new float[6];// 存放相除(兩個數(shù)相除的結(jié)果存在兩種可能)
 float[] div2 = new float[6];// 存放相除
 List<float[]> list = new ArrayList<float[]>();// 存放組合結(jié)果運(yùn)算的集合

 /**
 * 
 * Title: combine
 * </p>
 * Description: 該方法用來獲取每兩個數(shù)字的組合組合, 用1代表第一個數(shù)字,2代表第二個數(shù)字....共有六種組合方式,分別如下:
 * 1和2,1和3,1和 4,2和 3,2和 4,3和 4 在上面的組合中,每一種組合都對應(yīng)著 加減乘除 這四種運(yùn)算
 * 將上述的組合的每種計算結(jié)果存入上面聲明的集合
 */
 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集合中,方便通過循環(huán)來遍歷每一種組合方式
 list.add(sub1);
 list.add(sub2);
 list.add(mul);
 list.add(div1);
 list.add(div2);
 }

 public void getData() {
 Random r = new Random();
 // 獲取1——13的的數(shù)字的集合
 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("四個數(shù)字為:");
 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;// 通過該變量去判斷是否存在表達(dá)式
 conbine(data[0], data[1], data[2], data[3]);
 for (int a = 0; a < 3; a++) {// 有種組合方式,分別遍歷每一種組合方法
 for (int b = 0; b < 6; b++) {// 窮舉每一個組合和他們之間的運(yùn)算
 for (int c = 0; c < 6; c++) {// 判斷每一種組合的每一種運(yùn)算結(jié)果是否等于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("沒有表達(dá)式滿足條件");
 }

AutoGame類主要實現(xiàn)由系統(tǒng)給定數(shù)值,用戶輸入表達(dá)式來根據(jù)結(jié)過進(jìn)行計分,并將分?jǐn)?shù)寫入文件

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;//該變量標(biāo)識是否超時
 static int life = 3;//初始化生命值
 static int score=0;//初始化分?jǐn)?shù)

 /**
 *開始游戲的方法,該方法通過當(dāng)前生命值判斷是否結(jié)束 
 */
 public void start() throws IOException {
 Calendar date = Calendar.getInstance();//實例化Calendar對象
 while(life>0) {//當(dāng)生命值大于0才會進(jìn)行
 flag=true;//初始化分?jǐn)?shù)標(biāo)記
 date.setTime(new Date());
 date.add(Calendar.SECOND, 20);//設(shè)置限定時間
 Timer timer = new Timer();
 //當(dāng)達(dá)到限定時間將會執(zhí)行run()方法,即把全局變量flag變?yōu)閒alse
 timer.schedule(new RemindTask(), date.getTime());
 int answer = answer();
 switch(answer) {
 case -1:
 System.out.println("表達(dá)式錯誤!! 當(dāng)前生命值為"+life+" 分?jǐn)?shù)為:"+score);
 break;
 case -2:
 System.out.println("輸入超時?。?當(dāng)前生命值為"+life+" 分?jǐn)?shù)為:"+score);
 break;
 case -3:
 System.out.println("結(jié)果錯誤??! 當(dāng)前生命值為"+life+" 分?jǐn)?shù)為:"+score);
 break;
 case 1: 
 System.out.println("正確,得到1分獎勵!! 當(dāng)前生命值為"+life+" 分?jǐn)?shù)為:"+score);
 break;
 }
 System.out.println("----------");
 }
 System.out.println("游戲結(jié)束……分?jǐn)?shù)為: "+score);//循環(huán)結(jié)束也就是生命值為0,打印游戲結(jié)束
 saveScore(score);//將玩家當(dāng)前分?jǐn)?shù)存入文件
 return;
 }
/**
 * 
 * Title: getData</p> 
 * Description:給定任意的數(shù)據(jù) 
 * @return
 */
 private float[] getData() {
 float[] data = new float[4];
 Random r = new Random();//隨機(jī)生成四個數(shù)據(jù)存入數(shù)組中
 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("四個數(shù)字為:");
 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:根據(jù)用戶輸入返回false或true
 * 1.輸入不含給定值,返回FALSE
 * 2.輸入超時,返回false
 * 3.輸入表達(dá)式的值不為24,返回false
 * 否則,返回true 
 * @return -1代表輸入的表達(dá)式與系統(tǒng)給出的數(shù)字不吻合
 * @return -2代表用戶計算結(jié)果超時
 * @return -3代表結(jié)果錯誤
 * @return 1代表用戶計算正確
 */
 public int answer() {
 Scanner sc = new Scanner(System.in);
 float[] data = getData();//獲取給定的數(shù)據(jù)
 //獲取script引擎,調(diào)用eval()方法來判斷表達(dá)式是否正確
 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] + "")) {//輸入的表達(dá)式不含給定的值
 life--;
 return -1;
 }
 if(!flag) {//判斷超時
 life--;
 return -2;
 }
 if (res.equals("24")) {//回答正確并且沒有超時
 score++;//分?jǐn)?shù)加一
 return 1;
 }
 life--;
 } catch (ScriptException e) {
 System.out.println("表達(dá)式輸入不合法");
 }
 return -3;

 }
 /**
 * Title: saveScore</p> 
 * Description: 該方法表示將玩家當(dāng)前分?jǐn)?shù)存入TopList.txt文件
 * @param score 需要存入的分?jǐn)?shù)
 * @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());//把分?jǐn)?shù)寫入文件
 bos.close();
 
 }
 public static void main(String[] args) throws IOException {
 saveScore(1);
 }
}
/**
 * 
* Title: RemindTask
* Description:該TimerTask并且重寫run()可以實現(xiàn)在指定的定時時間執(zhí)行run方法的內(nèi)容
* @author jianglei 
 */
class RemindTask extends TimerTask {

 @Override
 public void run() {
 AutoGame.flag = false;//當(dāng)超時會把全局變量flag變?yōu)閒alse
 }

}

DataFormat類根據(jù)a b c是三個循環(huán)變量將兩個組合數(shù)字的運(yùn)算格式化成四個數(shù)字的表達(dá)式

由于代碼比較長,在這里只留一種情況的,其余的情況與它類似

import java.util.Set;
/**
 * 
* Title: GetFoamat
* Description: 該類通過在循環(huán)中的a b c的值判斷出當(dāng)前所參與運(yùn)算的值與參加運(yùn)算的符號,假設(shè)四個值為n0,n1,n2,n3
* 形參 a、b、c為循環(huán)變量,形參n數(shù)組為參與運(yùn)算的四個數(shù)字,形參op表示當(dāng)前進(jìn)行的運(yùn)算類型,形參set為存儲結(jié)果的容器

 */
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之間的運(yùn)算
 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");
 }
 //將運(yùn)算表達(dá)式存入容器
 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.隨機(jī)生成數(shù)判斷");
 System.out.println("2.用戶輸入運(yùn)算式");
 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("輸入錯誤");
 }
 }
}

運(yùn)行結(jié)果

java實現(xiàn)24點(diǎn)游戲

java實現(xiàn)24點(diǎn)游戲

java實現(xiàn)24點(diǎn)游戲

以下用戶輸入表達(dá)式的運(yùn)行結(jié)果

測試過程中在該情況下的測試數(shù)據(jù)是由自己給出的為1 1 12 12這四個數(shù)字

java實現(xiàn)24點(diǎn)游戲

分?jǐn)?shù)存入文件

java實現(xiàn)24點(diǎn)游戲

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

當(dāng)前名稱:java實現(xiàn)24點(diǎn)游戲
網(wǎng)站URL:http://www.muchs.cn/article46/iidghg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、定制開發(fā)、服務(wù)器托管、、標(biāo)簽優(yōu)化、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)