java作業練習:24點
阿新 • • 發佈:2018-12-12
作業題目:24點遊戲
所用語言:java
所用類:Main MainTest
其他檔案:null
程式流程:Main方法中開始執行程式,獲得一組範圍由1到13的(閉區間)4張牌組,通過窮舉法把四張牌兩兩運算(加減乘除)得出最後結果是24的卡組視為勝出。若沒有得出24的卡組視為失敗,隨即下一組繼續運算直到發現存在24的卡組,然後輸出不帶重複的得出24的數學表示式。
程式碼如下:
import java.util.ArrayList; import java.util.Random; public class Main { public static void main(String[] args) { boolean flag = true;//判斷第一個出現24點的人 System.out.println("all right,遊戲開始~!!"); while (flag) { System.out.println("發牌ing"); ArrayList<Integer> random = getCardNumber();//獲得4個範圍由1到13的隨機卡組 System.out.println("這組牌是"+random); flag = gameStart(random);//傳入引數正式開始運算 if (flag == true) { System.out.println("這組牌沒有24點,下一組"); } } } private static boolean gameStart(ArrayList<Integer> random) { ArrayList<String> allOpeations = new ArrayList<>();//用於儲存所有的運算式 boolean isExist = true;//給主函式返回計算結果,判斷是否存在運算可以算的24 int first = 0, second = 0, third = 0;//first第一輪運算的運算子,second第二輪運算的運算子,third第三輪運算的運算子 //窮舉法計算各種情況 for (first = 0; first < 4; first++) { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { if (i != j) { double result1 = CaculateResults((double) random.get(i), (double) random.get(j), first); String[] operators = new String[3]; operators[0] = getOperator(first); for (second = 0; second < 4; second++) { for (int k = 0; k < 4; k++) { if (k != i && k != j) { double result2 = CaculateResults(result1, (double) random.get(k), second); operators[1] = getOperator(second); for (third = 0; third < 4; third++) { for (int m = 0; m < 4; m++) { if (m != i && m != j && m != k) { double result3 = CaculateResults(result2, (double) random.get(m), third); operators[2] = getOperator(third); if (result3 == 24) { //最後的格式是兩兩運算的順序 allOpeations.add("[" + "(" + random.get(i) + operators[0] + random.get(j) + ")" + operators[1] + random.get(k) + "]" + operators[2] + random.get(m)); isExist = false; } } } } } } } } } } //把所有的公式傳參後去排除相同的公式 showResults(allOpeations); return isExist; } private static void showResults(ArrayList<String> allOpeations) { System.out.println("看來我們已經有了一個贏家!而且他的組合牌是!"); ArrayList<String> list1 = new ArrayList();//list1用來存放所有的()小括號裡的表示式,只要確保()小括號裡的表示式一至就能有效排除相同的公式 //分割表示式 for (int i = 0; i < allOpeations.size(); i++) { list1.add(splitString(allOpeations.get(i), "(", ")")); } //list2用來存放所有相同的方程式,有多少相同的就放多少,最後用於刪除 ArrayList<String> list2 = new ArrayList<>(); for (int i = 0; i < list1.size(); i++) { for (int index = 0; index < list1.get(i).length(); index++) { //遍歷表示式判斷運算子,因為+和*有特殊性 if (list1.get(i).charAt(index) == '+') { String[] temp = list1.get(i).split("[+]"); String chekStr = temp[1] + "+" + temp[0]; allOpeations.get(i).replaceAll(list1.get(i), chekStr); for (int j = i + 1; j < allOpeations.size(); j++) { if (allOpeations.get(i).equals(allOpeations.get(j))) { list2.add(allOpeations.get(i)); break; } } } else if (list1.get(i).charAt(index) == '*') { String[] temp = list1.get(i).split("[*]"); String chekStr = temp[1] + "*" + temp[0]; allOpeations.get(i).replaceAll(list1.get(i), chekStr); for (int j = i + 1; j < allOpeations.size(); j++) { if (allOpeations.get(i).equals(allOpeations.get(j))) { list2.add(allOpeations.get(i)); break; } } } else if (list1.get(i).charAt(index) == '-') { for (int a = i + 1; a < list1.size(); a++) { if (allOpeations.get(a).equals(allOpeations.get(i))) { list2.add(allOpeations.get(i)); break; } } } else if (list1.get(i).charAt(index) == '/') { for (int a = i + 1; a < list1.size(); a++) { if (allOpeations.get(a).equals(allOpeations.get(i))) { list2.add(allOpeations.get(i)); break; } } } } } //刪除所有表示式中存在於list2的表示式 for (int j = 0; j < list2.size(); j++) { String temp = list2.get(j); allOpeations.remove(temp); } //輸出不一樣的表示式 for (int length = 0; length < allOpeations.size(); length++) { System.out.println(allOpeations.get(length)); } } //用於分割表示式,有目標表達式,分割開始的字元(串),分割結束的字元(串) public static String splitString(String target, String begin, String end) { int left = target.indexOf(begin); int right = target.indexOf(end); String result = target.substring(left + 1, right); return result; } //根據運算的引數來判斷返回到公式裡的運算子 private static String getOperator(int first) { String str = null; if (first == 0) return str = "+"; if (first == 1) return str = "-"; if (first == 2) return str = "*"; if (first == 3) return str = "/"; return str; } //用引數判斷計算的型別 private static double CaculateResults(double x, double y, int operator) { double result = 0; if (operator == 0) { result = x + y; return result; } if (operator == 1) { result = x - y; return result; } if (operator == 2) { result = x * y; return result; } if (operator == 3) { if (y != 0) { result = x / y; return result; } } return result; } //獲得隨機牌組 public static ArrayList getCardNumber() { Random random = new Random(); ArrayList<Integer> randomNumber = new ArrayList(); while (randomNumber.size() != 4) { int i = random.nextInt(14); if (i > 0) { if (randomNumber.size() == 0) { randomNumber.add(i); } else { randomNumber.add(i); } } } return randomNumber; } }
不要急著關!不要慌!看我給你慢慢道來!!!
我的程式計算上可能比較繁瑣,但是比較好理解。
首先:
程式由Main開始
public static void main(String[] args) { boolean flag = true;//判斷第一個出現24點的人 System.out.println("all right,遊戲開始~!!"); while (flag) { System.out.println("發牌ing"); ArrayList<Integer> random = getCardNumber();//獲得4個範圍由1到13的隨機卡組 System.out.println("這組牌是"+random); flag = gameStart(random);//傳入引數正式開始運算 if (flag == true) { System.out.println("這組牌沒有24點,下一組"); } } }
random是獲得隨機數的牌組,怎麼獲得的呢??通過限制隨機數的範圍和隨機數的數量,拿到了就跟撲克牌一樣A(1),2,3,4,5,6,7,8,9,10,J(11),K(12),Q(13),沒有王。返回了一個存放整數的列表。
public static ArrayList getCardNumber() { Random random = new Random(); ArrayList<Integer> randomNumber = new ArrayList(); while (randomNumber.size() != 4) { int i = random.nextInt(14); if (i > 0) { if (randomNumber.size() == 0) { randomNumber.add(i); } else { randomNumber.add(i); } } } return randomNumber; }
拿到卡之後就髮卡?,flag用來標記能通過兩兩運算後得到的結果來判斷遊戲什麼時候結束。
boolean flag = true;//判斷第一個出現24點的人
System.out.println("all right,遊戲開始~!!");
while (flag) {
System.out.println("發牌ing");
ArrayList<Integer> random = getCardNumber();//獲得4個範圍由1到13的隨機卡組
System.out.println("這組牌是"+random);
flag = gameStart(random);//傳入引數正式開始運算
if (flag == true) {
System.out.println("這組牌沒有24點,下一組");
}
}
來!算!?程式碼裡註釋給的很清楚,從下面的for開始就是在選擇兩兩數字去計算,具體計算在CaculateResults裡計算,注意其中的first用來標註第一次運算的運算子。second 和 third的用法一樣。
private static boolean gameStart(ArrayList<Integer> random) {
ArrayList<String> allOpeations = new ArrayList<>();//用於儲存所有的運算式
boolean isExist = true;//給主函式返回計算結果,判斷是否存在運算可以算的24
int first = 0, second = 0, third = 0;//first第一輪運算的運算子,second第二輪運算的運算子,third第三輪運算的運算子
//窮舉法計算各種情況
for (first = 0; first < 4; first++) {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
if (i != j) {
double result1 = CaculateResults((double) random.get(i), (double) random.get(j), first);
String[] operators = new String[3];
operators[0] = getOperator(first);
for (second = 0; second < 4; second++) {
for (int k = 0; k < 4; k++) {
if (k != i && k != j) {
double result2 = CaculateResults(result1, (double) random.get(k), second);
operators[1] = getOperator(second);
for (third = 0; third < 4; third++) {
for (int m = 0; m < 4; m++) {
if (m != i && m != j && m != k) {
double result3 = CaculateResults(result2, (double) random.get(m), third);
operators[2] = getOperator(third);
if (result3 == 24) {
//最後的格式是兩兩運算的順序
allOpeations.add("[" + "(" + random.get(i) + operators[0] + random.get(j) + ")" + operators[1] + random.get(k) + "]" + operators[2] + random.get(m));
isExist = false;
}
}
}
}
}
}
}
}
}
}
//把所有的公式傳參後去排除相同的公式
showResults(allOpeations);
return isExist;
}
而CacluateResults是這樣實現的?,很簡單對吧。
private static double CaculateResults(double x, double y, int operator) {
double result = 0;
if (operator == 0) {
result = x + y;
return result;
}
if (operator == 1) {
result = x - y;
return result;
}
if (operator == 2) {
result = x * y;
return result;
}
if (operator == 3) {
if (y != 0) {
result = x / y;
return result;
}
}
return result;
}
那每次運算後要把包括運算子和數字存放到allOpeations中來存放所有的運算式,那肯定要確定存放某個運算式的時候考慮怎麼存放這個運算子,存放哪個運算子對吧,?這裡頭的first只是個引數,不要和上面的first混淆。
private static String getOperator(int first) {
String str = null;
if (first == 0)
return str = "+";
if (first == 1)
return str = "-";
if (first == 2)
return str = "*";
if (first == 3)
return str = "/";
return str;
}
算完了拿到結果了最後就是篩選結果。怎麼獲得不帶重複樣的表示式呢??
private static void showResults(ArrayList<String> allOpeations) {
System.out.println("看來我們已經有了一個贏家!而且他的組合牌是!");
ArrayList<String> list1 = new ArrayList();//list1用來存放所有的()小括號裡的表示式,只要確保()小括號裡的表示式一至就能有效排除相同的公式
//分割表示式
for (int i = 0; i < allOpeations.size(); i++) {
list1.add(splitString(allOpeations.get(i), "(", ")"));
}
//list2用來存放所有相同的方程式,有多少相同的就放多少,最後用於刪除
ArrayList<String> list2 = new ArrayList<>();
for (int i = 0; i < list1.size(); i++) {
for (int index = 0; index < list1.get(i).length(); index++) {
//遍歷表示式判斷運算子,因為+和*有特殊性
if (list1.get(i).charAt(index) == '+') {
String[] temp = list1.get(i).split("[+]");
String chekStr = temp[1] + "+" + temp[0];
allOpeations.get(i).replaceAll(list1.get(i), chekStr);
for (int j = i + 1; j < allOpeations.size(); j++) {
if (allOpeations.get(i).equals(allOpeations.get(j))) {
list2.add(allOpeations.get(i));
break;
}
}
} else if (list1.get(i).charAt(index) == '*') {
String[] temp = list1.get(i).split("[*]");
String chekStr = temp[1] + "*" + temp[0];
allOpeations.get(i).replaceAll(list1.get(i), chekStr);
for (int j = i + 1; j < allOpeations.size(); j++) {
if (allOpeations.get(i).equals(allOpeations.get(j))) {
list2.add(allOpeations.get(i));
break;
}
}
} else if (list1.get(i).charAt(index) == '-') {
for (int a = i + 1; a < list1.size(); a++) {
if (allOpeations.get(a).equals(allOpeations.get(i))) {
list2.add(allOpeations.get(i));
break;
}
}
} else if (list1.get(i).charAt(index) == '/') {
for (int a = i + 1; a < list1.size(); a++) {
if (allOpeations.get(a).equals(allOpeations.get(i))) {
list2.add(allOpeations.get(i));
break;
}
}
}
}
}
//刪除所有表示式中存在於list2的表示式
for (int j = 0; j < list2.size(); j++)
{
String temp = list2.get(j);
allOpeations.remove(temp);
}
//輸出不一樣的表示式
for (int length = 0; length < allOpeations.size(); length++)
{
System.out.println(allOpeations.get(length));
}
}
然後輸出就OK了呀?。
遊戲截圖:
Coder:Flyige