利用Java編寫(xiě)24點(diǎn)小游戲的實(shí)例代碼
話不多說(shuō)直接給大家上代碼
package com.company; import java.util.*; /** * 24點(diǎn)小游戲 * 游戲規(guī)則:系統(tǒng)自動(dòng)生成4個(gè)1-10的隨機(jī)整數(shù),玩家通過(guò)加減乘除操作,得到結(jié)果為24,每個(gè)數(shù)字只能使用一次 */ public class Game24Player { final String[] patterns = {"nnonnoo", "nnonono", "nnnoono", "nnnonoo", "nnnnooo"}; final String ops = "+-*/^";//存儲(chǔ)運(yùn)算符 String solution;//解題答案 List<Integer> digits; public static void main(String[] args) { new Game24Player().play(); } void play() { digits = getSolvableDigits(); Scanner in = new Scanner(System.in); while (true) { System.out.println("24點(diǎn)小游戲:"); System.out.print("使用以下數(shù)字得出24點(diǎn): "); System.out.println(digits); System.out.println("tips:輸入q退出游戲,輸入s打印解法以及出下一道題"); System.out.print("> "); String line = in.nextLine();//獲取控制臺(tái)下一行輸入的內(nèi)容 if (line.equalsIgnoreCase("q")) { System.out.println("\nThanks for playing"); return; } if (line.equalsIgnoreCase("s")) { System.out.println(solution); digits = getSolvableDigits(); continue; } char[] entry = line.replaceAll("[^*+-/)(\\d]", "").toCharArray(); try { validate(entry); if (evaluate(infixToPostfix(entry))) { System.out.println("\n恭喜你,回答正確,請(qǐng)繼續(xù)下一輪 "); digits = getSolvableDigits(); } else { System.out.println("\n答題錯(cuò)誤,請(qǐng)重新答題"); } } catch (Exception e) { System.out.printf("%n%s 請(qǐng)重新輸入.%n", e.getMessage()); } } } //判斷玩家在控制臺(tái)輸入的內(nèi)容是否正確 void validate(char[] input) throws Exception { int total1 = 0, parens = 0, opsCount = 0; for (char c : input) { if (Character.isDigit(c)) total1 += 1 << (c - '0') * 4; else if (c == '(') parens++; else if (c == ')') parens--; else if (ops.indexOf(c) != -1) opsCount++; if (parens < 0) throw new Exception("括號(hào)不匹配."); } if (parens != 0) throw new Exception("括號(hào)不匹配."); if (opsCount != 3) throw new Exception("錯(cuò)誤輸入."); int total2 = 0; for (int d : digits) total2 += 1 << d * 4; if (total1 != total2) throw new Exception("輸入有誤."); } boolean evaluate(char[] line) throws Exception { Stack<Float> s = new Stack<>(); try { for (char c : line) { if ('0' <= c && c <= '9') s.push((float) c - '0'); else s.push(applyOperator(s.pop(), s.pop(), c)); } } catch (EmptyStackException e) { throw new Exception("輸入無(wú)效,請(qǐng)重新輸入."); } return (Math.abs(24 - s.peek()) < 0.001F); } float applyOperator(float a, float b, char c) { switch (c) { case '+': return a + b; case '-': return b - a; case '*': return a * b; case '/': return b / a; default: return Float.NaN; } } //獲取一組隨機(jī)數(shù) List<Integer> randomDigits() { Random r = new Random(); List<Integer> result = new ArrayList<>(4); for (int i = 0; i < 4; i++) result.add(r.nextInt(9) + 1);//添加4個(gè)1-10的隨機(jī)數(shù) return result; } List<Integer> getSolvableDigits() { List<Integer> result; do { result = randomDigits(); } while (!isSolvable(result)); return result; } boolean isSolvable(List<Integer> digits) { Set<List<Integer>> dPerms = new HashSet<>(4 * 3 * 2); permute(digits, dPerms, 0); int total = 4 * 4 * 4; List<List<Integer>> oPerms = new ArrayList<>(total); permuteOperators(oPerms, 4, total); StringBuilder sb = new StringBuilder(4 + 3); for (String pattern : patterns) { char[] patternChars = pattern.toCharArray(); for (List<Integer> dig : dPerms) { for (List<Integer> opr : oPerms) { int i = 0, j = 0; for (char c : patternChars) { if (c == 'n') sb.append(dig.get(i++)); else sb.append(ops.charAt(opr.get(j++))); } String candidate = sb.toString(); try { if (evaluate(candidate.toCharArray())) { solution = postfixToInfix(candidate); return true; } } catch (Exception ignored) { } sb.setLength(0); } } } return false; } String postfixToInfix(String postfix) { class Expression { String op, ex; int prec = 3; Expression(String e) { ex = e; } Expression(String e1, String e2, String o) { ex = String.format("%s %s %s", e1, o, e2); op = o; prec = ops.indexOf(o) / 2; } } Stack<Expression> expr = new Stack<>(); for (char c : postfix.toCharArray()) { int idx = ops.indexOf(c); if (idx != -1) { Expression r = expr.pop(); Expression l = expr.pop(); int opPrec = idx / 2; if (l.prec < opPrec) l.ex = '(' + l.ex + ')'; if (r.prec <= opPrec) r.ex = '(' + r.ex + ')'; expr.push(new Expression(l.ex, r.ex, "" + c)); } else { expr.push(new Expression("" + c)); } } return expr.peek().ex; } char[] infixToPostfix(char[] infix) throws Exception { StringBuilder sb = new StringBuilder(); Stack<Integer> s = new Stack<>(); try { for (char c : infix) { int idx = ops.indexOf(c); if (idx != -1) { if (s.isEmpty()) s.push(idx); else { while (!s.isEmpty()) { int prec2 = s.peek() / 2; int prec1 = idx / 2; if (prec2 >= prec1) sb.append(ops.charAt(s.pop())); else break; } s.push(idx); } } else if (c == '(') { s.push(-2); } else if (c == ')') { while (s.peek() != -2) sb.append(ops.charAt(s.pop())); s.pop(); } else { sb.append(c); } } while (!s.isEmpty()) sb.append(ops.charAt(s.pop())); } catch (EmptyStackException e) { throw new Exception("Invalid entry."); } return sb.toString().toCharArray(); } void permute(List<Integer> lst, Set<List<Integer>> res, int k) { for (int i = k; i < lst.size(); i++) { Collections.swap(lst, i, k); permute(lst, res, k + 1); Collections.swap(lst, k, i); } if (k == lst.size()) res.add(new ArrayList<>(lst)); } void permuteOperators(List<List<Integer>> res, int n, int total) { for (int i = 0, npow = n * n; i < total; i++) res.add(Arrays.asList((i / npow), (i % npow) / n, i % n)); } }
運(yùn)行結(jié)果截圖
游戲題目
在控制臺(tái)輸入答案
輸入s是查看結(jié)果并開(kāi)始下一次游戲。
輸入q是退出游戲。
總結(jié)
到此這篇關(guān)于利用Java編寫(xiě)24點(diǎn)小游戲的文章就介紹到這了,更多相關(guān)Java編寫(xiě)24點(diǎn)小游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java實(shí)現(xiàn)24點(diǎn)紙牌游戲
- java實(shí)現(xiàn)24點(diǎn)游戲
- Java實(shí)現(xiàn)24點(diǎn)小游戲
- Java編寫(xiě)的24點(diǎn)紙牌游戲
- Java Swing實(shí)現(xiàn)坦克大戰(zhàn)游戲
- Java實(shí)戰(zhàn)之飛翔的小鳥(niǎo)小游戲
- Java實(shí)現(xiàn)五子棋游戲
- Java實(shí)現(xiàn)的迷宮游戲
- Java實(shí)戰(zhàn)入門(mén)之雙色球彩票小游戲
- Java實(shí)戰(zhàn)之貪吃蛇小游戲(源碼+注釋?zhuān)?/a>
- 用Java實(shí)現(xiàn)24點(diǎn)游戲
相關(guān)文章
java后端如何調(diào)用第三方接口(往header和body中的參數(shù)傳參)
這篇文章主要介紹了java后端如何調(diào)用第三方接口(往header和body中的參數(shù)傳參),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12Java多線程Thread類(lèi)的使用及注意事項(xiàng)
這篇文章主要介紹了Java多線程Thread類(lèi)的使用及注意事項(xiàng),在java標(biāo)準(zhǔn)庫(kù)中提供了一個(gè)Thread類(lèi)來(lái)表示/操作線程,Thread類(lèi)也可以視為是java標(biāo)準(zhǔn)庫(kù)提供的API2022-06-06基于java中的null類(lèi)型---有關(guān)null的9件事
這篇文章主要介紹了java中的null類(lèi)型---有關(guān)null的9件事,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java中json使用方法_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式, json是個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu),在web開(kāi)發(fā)中應(yīng)用十分廣泛。下面通過(guò)本文給大家講解Java中json使用方法,感興趣的朋友一起看看吧2017-07-07Spring Boot集成Druid出現(xiàn)異常報(bào)錯(cuò)的原因及解決
Druid 可以很好的監(jiān)控 DB 池連接和 SQL 的執(zhí)行情況,天生就是針對(duì)監(jiān)控而生的 DB 連接池。本文講述了Spring Boot集成Druid項(xiàng)目中discard long time none received connection異常的解決方法,出現(xiàn)此問(wèn)題的同學(xué)可以參考下2021-05-05MyBatisPlus報(bào)錯(cuò):Failed to process,please exclud
這篇文章主要介紹了MyBatisPlus報(bào)錯(cuò):Failed to process,please exclude the tableName or statementId問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08一個(gè)簡(jiǎn)單的Python名片管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了一個(gè)簡(jiǎn)單的Python名片管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01詳解Spring Boot 使用Java代碼創(chuàng)建Bean并注冊(cè)到Spring中
本篇介紹了Spring Boot 使用Java代碼創(chuàng)建Bean并注冊(cè)到Spring中,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02