24点游戏

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

 
  

public class TwentyFourPoint {  
    public static void main(String[] args)  {  
    	
    	System.out.println("请输入4个0~13的整数:");
    	int b1=new Scanner(System.in).nextInt();
    	int b2=new Scanner(System.in).nextInt();
    	Scanner a3=new Scanner(System.in);
    	int b3=a3.nextInt();
    	Scanner a4=new Scanner(System.in);
    	int b4=a4.nextInt();
    	
    		
    	if((0<=b1&&b1<=13)&&(0<b2&&b2<=13)&&(0<b2&&b2<=13)&&(0<b2&&b2<=13)) {
    			
    		}
    		else {
				System.out.println("数值输入错误,请重新输入");
				TwentyFourPoint.main(args);
				
			}
    
        try {  
            Set<String> set = caculate(new int[] { b1, b2, b3, b4 }, 24);  
            printlnResultSet(set);  
        } catch (Exception e) {  
            // e.printStackTrace();开发期间方便查找错误,测试通过后就无需打印错误信息了  
            System.err.println(e.getMessage());  
        }  
    }  
  

    private static void printlnResultSet(Collection<String> resultSet) {  
        for (String str : resultSet) {  
            System.out.println(str);  
        }  
    }  
  
 
    private static int[][] arrangeAllNumbers(int[] numbers) {  
        List<int[]> list = new ArrayList<int[]>();  
        allSort(numbers, 0, numbers.length - 1, list);  
        int[][] resultSet = new int[list.size()][list.get(0).length];  
        resultSet = list.toArray(resultSet);  
        return resultSet;  
    }  
  
    /** 
     * 得到给定的操作中出现的所有操作符排列情况 
     *  
     * @param operators 
     *            出现的操作符数组 
     * @param number 
     *            每组操作符的数量 
     * @return 所有操作符排列数组 
     */  
    private static char[][] arrangeAllOperators(char[] operators, int number) {  
        int setSize = (int) Math.pow(operators.length, number);  
        int index = 0;  
        char[][] resultSet = new char[setSize][number];  
        for (int i = 0; i < operators.length; i++) {  
            for (int j = 0; j < operators.length; j++) {  
                for (int k = 0; k < operators.length; k++) {  
                    resultSet[index][0] = operators[i];  
                    resultSet[index][1] = operators[j];  
                    resultSet[index][2] = operators[k];  
                    index++;  
                }  
            }  
        }  
        return resultSet;  
    }  
  

    public static Set<String> caculate(int[] numbers, int targetNumber)  
            throws Exception {  
        Set<String> resultSet = new HashSet<String>();// 这里用Set而不是用List,主要是因为当给定的一组数字中如果有重复数字的话,同一结果会被出现多次,如果用List存放的话,会将重复的结果都存放起来,而Set会自动消除重复值  
        char[][] operatorsArrangement = arrangeAllOperators(new char[] { '+',  
                '-', '*', '/' }, 3);  
        int[][] numbersArrangement = arrangeAllNumbers(numbers);  
        for (int[] nums : numbersArrangement)  
            for (char[] operators : operatorsArrangement) {  
                int result = 0;  
                try {  
                    result = caculate(nums, operators);  
                } catch (Exception e) {// 出现非精确计算  
                    continue;  
                }  
                if (result == targetNumber)  
                    resultSet.add(buildString(nums, operators, targetNumber));// 如果计算后的结果等于想要的结果,就存放到集合中  
            }  
        if (resultSet.isEmpty())  
            throw new Exception("给定的数字:" + Arrays.toString(numbers)  
                    + "不能通过加减乘除运算得到结果:" + targetNumber);  
        return resultSet;  
    }  
  
   
    private static String buildString(int[] nums, char[] operators, int target) {  
        String str = String.valueOf(nums[0]);  
        for (int i = 0; i < operators.length; i++) {  
            str = '('+str +' '+ operators[i] +' '+ nums[i + 1]+')';  
        }  
        str = str + " = " + target;  
        return str;  
    }  
  
  
    private static int caculate(int[] nums, char[] operators) throws Exception {  
        int result = 0;  
        for (int i = 0; i < operators.length; i++) {  
            if (i == 0) {  
                result = caculate(nums[i], nums[i + 1], operators[i]);  
            } else {  
                result = caculate(result, nums[i + 1], operators[i]);  
            }  
        }  
        return result;  
    }  
  
   
    private static int caculate(int num1, int num2, char operator)  
            throws Exception {  
        double result = 0;  
        switch (operator) {// 根据操作符做相应的计算操作  
        case '+':  
            result = num1 + num2;  
            break;  
        case '-':  
            result = num1 - num2;  
            break;  
        case '*':  
            result = num1 * num2;  
            break;  
        case '/':  
            result = (double) num1 / (double) num2;  
            break;  
        }  
        if (!check(result))  
            throw new Exception("不精确的计算数字");  
        return (int) result;  
    }  
  
  
    private static boolean check(double result) {  
        String str = String.valueOf(result);  
        int pointIndex = str.indexOf(".");// 小数点的下标值  
        String fraction = str.substring(pointIndex + 1);  
        return fraction.equals("0") ? true : false;// 通过判断小数点后是否只有一个0来确定是否可以无损转换为整型数值  
    }  
  
 
    private static void allSort(int[] buf, int start, int end, List<int[]> list) {  
        if (start == end) {// 当只要求对数组中一个字母进行全排列时,只要就按该数组输出即可  
            int[] a = new int[buf.length];  
            System.arraycopy(buf, 0, a, 0, a.length);  
            list.add(a);  
        } else {// 多个字母全排列  
            for (int i = start; i <= end; i++) {  
                int temp = buf[start];// 交换数组第一个元素与后续的元素  
                buf[start] = buf[i];  
                buf[i] = temp;  
                allSort(buf, start + 1, end, list);// 后续元素递归全排列  
                temp = buf[start];// 将交换后的数组还原  
                buf[start] = buf[i];  
                buf[i] = temp;  
            }  
        }  
    }  
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值