Java 编写24点游戏

以前用Python写过24点:传送门 。现在重新参照以前的思路用Java来写,结果发现很多问题。这里重新说一下完整的思路:

24 点的计算式主要有两种情况:

前言:先遍历由4个数全排列而得到的(List<int[]> ,每一次得到由4个数组成的int[],对这4个数:

第一种情况:第一个数和第二个数运算,结果记为 S12 , S12 和第三个数运算,结果记为S123 ,最后 S123 和第四个数运算,得到最终的运算值。

注意点:S12 和第三个数的运算,要考虑它们的先后位置,比如25-1 和1-25是不同的。同理, S123 也一样。

第二种情况:第一个数和第二个数运算,结果记为 S12 ;然后第三个数和第四个数运算,结果记为 S34 ,最后S12和S34运算,即得到最终的运算值。

注意点:这里不用考虑两个数运算之间的先后顺序,因为这些数都是全排列得到的数,而不是 “新数”

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;

public class Main {
	public static void main(String[] args) {
		CalcOf24 game = new CalcOf24();
		int[] n = game.getFourNum();			// 通过键盘输入4个数
		List<int[]> L = game.permutations(n);	// 全排列
		if(!game.calcWayOne(L)) {				// 第一种情况
			if(!game.calcWayTwo(L)) {			// 第二种情况
				System.out.println("无解!");
			}
		}
	}
}

/**
 * 24点游戏设计类
 * @author pytn
 *
 */
class CalcOf24{
	/**
	 * 4个数的全排列函数,但没有去除重复的元素,即不管4个数中是否有相同值,列表长度总是 4*3*2*1 个。但这不影响计算出24点
	 * @param n
	 */
	public List<int[]> permutations(int[] n){		
		List<int[]> list = new ArrayList<>();
		
		for(int i=0; i<n.length; i++) {		
			for(int j=0;j<n.length; j++) {
				if(j != i) {
					for(int k=0; k<n.length; k++) {
						if(k != i && k != j) {
							for(int z=0; z<n.length; z++) {
								if(z != i && z != j && z != k) {
									int[] num = new int[4];
									num[0] = n[i];
									num[1] = n[j];
									num[2] = n[k];
									num[3] = n[z];
									list.add(num);
								}
							}
						}
					}
				}				
			}
		}
		return list;
	}
	
	// 通过键盘输入4个数
    public int[] getFourNum() {
		int[] num = new int[4];
		String pattern = "[1-9]+\\d*";		// 匹配任何大于零的整数
		while(true) {
			boolean flag = false;
			String result;
			String[] nums = {"a","b","c","d"};
			@SuppressWarnings("resource")
			Scanner scanner = new Scanner(System.in);
			
			for(int i=0; i<nums.length; i++) {
				System.out.printf("请输入%s:", nums[i]);
				result = scanner.nextLine();
				if(Pattern.matches(pattern, result)) {
					num[i] = Integer.parseInt(result);
				}else {
					System.out.println("输入有误,请正确输入大于零的整数");
					flag = true;
					break;
				}
			}
			if(flag) {
				continue;
			}else {
				break;
			}
		}
		return num;
	}
	
	/**
	 * 第一种情况
	 * 即实现 ((a⊕b)⊕c)⊕d、(c⊕(a⊕b))⊕d、d⊕((a⊕b)⊕c)、d⊕(c⊕(a⊕b))的形式
	 * @param L
	 */
	public boolean calcWayOne(List<int[]> L) {
		String[] symbols1= {"+", "-", "-", "*", "/", "/"};
		String[] symbols2= {"+", "-", "*", "/"};
		
		for(int[] num : L) {
			float a = num[0];
			float b = num[1];
			float c = num[2];
			float d = num[3];
			float[] list2 = {a+b, a-b, a*b, a/b};
			float[] list3;
			float[] list4;
			
			for(int i=0; i<list2.length; i++) {
				if(list2[i] == 0) {
					list3 = new float[] {list2[i]+c, list2[i]-c, c-list2[i], list2[i]*c, list2[i]/c};
				}else {
					list3 = new float[] {list2[i]+c, list2[i]-c, c-list2[i], list2[i]*c, list2[i]/c, c/list2[i]};
				}
				for(int j=0; j<list3.length; j++) {
					if(list3[j] == 0) {
						list4 = new float[] {list3[j]+d, list3[j]-d, d-list3[j], list3[j]*d, list3[j]/d};
					}else {
						list4 = new float[] {list3[j]+d, list3[j]-d, d-list3[j], list3[j]*d, list3[j]/d, d/list3[j]};
					}
					for(int k=0; k<list4.length; k++) {
						if(Math.abs(list4[k]-24) < 1e-5 && list4[i] > 0) {
							String equation3 = null;
							String equation4 = null;		
							String equation2 = "(" + (int)a + symbols2[i] + (int)b + ")";	
							if(j == 2 || j == 5) {
								equation3 = "(" + (int)c + symbols1[j] + equation2 + ")";						
							}else {
								equation3 = "(" + equation2 + symbols1[j] + (int)c + ")";
							}
							if(k == 2 || k == 5) {
								equation4 = (int)d + symbols1[k] + equation3;						
							}else {
								equation4 = equation3 + symbols1[k] + (int)d;
							}
							System.out.println(equation4);
							return true;							
					    }					
					}				
				}			
			}
		}
		return false;
	}
	
	/**
	 * 实现 (a⊕b)⊕(c⊕d) 的形式
	 * @param L
	 */
	public boolean calcWayTwo(List<int[]> L) {
		String[] symbols= {"+", "-", "*", "/"};
		
		for(int[] num : L) {
			float a = num[0];
			float b = num[1];
			float c = num[2];
			float d = num[3];
			float[] list2 = {a+b, a-b, a*b, a/b};
			float[] list3 = {c+d, c-d, c*d, c/d};
			float[] list4;		
			for(int i=0; i<list2.length; i++) {
				for(int j=0; j<list3.length; j++) {
					if(list3[j] == 0) {
						list4 = new float[] {list2[i]+list3[j], list2[i]-list3[j], list2[i]*list3[j]};
					}else {
						list4 = new float[] {list2[i]+list3[j], list2[i]-list3[j], list2[i]*list3[j], list2[i]/list3[j]};
					}
					for(int k=0; k<list4.length; k++) {
						if(Math.abs(list4[k]-24) < 1e-5 && list4[i] > 0) {
							String equation2 = "(" + (int)a + symbols[i] + (int)b + ")";
							String equation3 = "(" + (int)c + symbols[j] + (int)d + ")";						
							String equation4 = equation2 + symbols[k] + equation3;						
							System.out.println(equation4);
							return true;
						}
					}
				}		
			}
		}
		return false;
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值