1. 程式人生 > >java作業練習:24點

java作業練習:24點

作業題目: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