一. 内容
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能
二. 步骤
1. 算法分析
随机产生四个数,通过数组限制其均为不同的随机数,将所有运算顺序情况排列出来,刚开始有4个数,拿出两个数进行第一次运算,运算后得出三个数,然后在这三个数中再拿出两个进行第二次运算,运算后就只有两个数了,第三次运算就是将这两个数进行计算,得出最后值,判断最后这个值是否为24,若为24,则输出表达式,若不是,则输出提示消息。然后在这4个数确定位置的情况下,再来改变操作符,即每次2个数进行运算的时候,有4种情况。在下一次计算的时候同样有4种情况,最后一次计算(第3次)同理。这样就找到了所有解的情况。
2. 概要设计
3. 测试
实现结果:
4. 调试
5. 代码实现
package Game;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class Compute {
//定义随机产生的四个数
static int[] poker = new int[4];
//转换后的num1,num2,num3,num4
static int m[]=new int [4];
static String n[] = new String[4];
//用来判断是否有解
static boolean flag = false;
//存放操作符
static char[] operator = { '+', '-', '*', '/' };
public static void main(String[] args){
Random rand = new Random();
System.out.println("随机产生四个数字,使用+,-,*,/进行计算,使最后计算结果为24");
for(int i=0;i<4;i++){
//随机生成四个不同的int型数
while(true){
int number = rand.nextInt(13)+1;
if(!contains(poker,number)){
poker[i] = number;
break;
}
}
if(poker[i]==1){
System.out.println("A");//如果随机生成的数为1,则显示为扑克牌牌面中的A
}
else if(poker[i]==11){
System.out.println("J");//如果随机生成的数为11,则显示为扑克牌牌面中的J
}
else if(poker[i]==12){
System.out.println("Q");//如果随机生成的数为12,则显示为扑克牌牌面中的Q
}
else if(poker[i]==13){
System.out.println("K");//如果随机生成的数为13,则显示为扑克牌牌面中的K
}
else
System.out.println(poker[i]);
}
System.out.println("可能的结果有:");
calculate();
}
public static boolean contains(int[] arr, int key) {
for (int i=0; i<arr.length; i++) {
//如果相等返回true
if (arr[i] == key){
return true;
}
}
return false;
}
//计算生成24的函数
public static void calculate(){
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
//存放数字,用来判断输入的4个数字中有几个重复的,和重复的情况
for (int i = 0; i < poker.length; i++) {
if(map.get(poker[i]) == null){
map.put(poker[i], 1);
}
else {
map.put(poker[i], map.get(poker[i]) + 1);
}
}
if(map.size() == 4){
//4个数都不同的情况
int i,j,k,l;
for (i=0; i<4; i++) //4的排列 4!=24,每种情况调用calculation
for (j=0; j<4; j++)
if (j!=i) //第2数和第1个数不能重复
for (k=0; k<4; k++)
if (k!=j && k!=i) //第3数和第1,2个数不能重复
for (l=0; l<4; l++)
if (l!=i && l!=j && l!=k) //第4数和第1,2,3个数不能重复
{
calculation(poker[i],poker[j],poker[k],poker[l]);//调用calculation函数,进行进行加、减、乘、除运算
}
}
if(flag==false)
System.out.println("这四张牌面数字无法经过运算得到24!");
}
public static void show(int[] m, int p){
if(m[p]==1){
n[p]="A";}
if(m[p]==2){
n[p]="2";}
if(m[p]==3){
n[p]="3";}
if(m[p]==4){
n[p]="4";}
if(m[p]==5){
n[p]="5";}
if(m[p]==6){
n[p]="6";}
if(m[p]==7){
n[p]="7";}
if(m[p]==8){
n[p]="8";}
if(m[p]==9){
n[p]="9";}
if(m[p]==10){
n[p]="10";}
if(m[p]==11){
n[p]="J";}
if(m[p]==12){
n[p]="Q";}
if(m[p]==13){
n[p]="k";}
}
public static void calculation(int num1, int num2, int num3, int num4){
for (int i = 0; i < 4; i++){
//第1次计算,先从四个数中任意选择两个进行计算
char operator1 = operator[i];
int firstResult = calcute(num1, num2, operator1);//先选第一,和第二个数进行计算
int midResult = calcute(num2, num3, operator1);//先选第二和第三两个数进行计算
int tailResult = calcute(num3,num4, operator1);//先选第三和第四俩个数进行计算
for (int j = 0; j < 4; j++){
//第2次计算,从上次计算的结果继续执行,这次从三个数中选择两个进行计算
char operator2 = operator[j];
int firstMidResult = calcute(firstResult, num3, operator2);
int firstTailResult = calcute(num3,num4,operator2);
int midFirstResult = calcute(num1, midResult, operator2);
int midTailResult= calcute(midResult,num4,operator2);
int tailMidResult = calcute(num2, tailResult, operator2);
for (int k = 0; k < 4; k++){
//第3次计算,也是最后1次计算,计算两个数的结果,如果是24则输出表达式
char operator3 = operator[k];
//在以上的计算中num1,num2,num3,num4都是整型数值,但若要输出为带有A,J,Q,K的表达式,则要将这四个数都变为String类型,下同
if(calcute(firstMidResult, num4, operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
System.out.println("((" + n[0] + operator1 + n[1] + ")" + operator2 + n[2] + ")" + operator3 + n[3]);
flag = true;//若有表达式输出,则将说明有解,下同
}
if(calcute(firstResult, firstTailResult, operator3) == 24){
System.out.println("(" + n[0] + operator1 + n[1] + ")" + operator3 + "(" + n[2] + operator2 + n[3] + ")");
flag = true;
}
if(calcute(midFirstResult, num4, operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
System.out.println("(" + n[0] + operator2 + "(" + n[1] + operator1 + n[2] + "))" + operator3 + n[3]);
flag = true;
}
if(calcute(num1,midTailResult, operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
System.out.println(" " + n[0] + operator3 + "((" + n[1] + operator1 + n[2] + ")" + operator2 + n[3] + ")");
flag = true;
}
if(calcute(num1,tailMidResult,operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
System.out.println(" " + n[0] + operator3 + "(" + n[1] + operator2 + "(" + n[2] + operator1 + n[3] + "))");
flag = true;
}
}
}
}
}
//给定2个数和指定操作符的计算
public static int calcute(int count1, int count2, char operator) {
if (operator == '+') {
return count1 + count2;
}
else if (operator == '-') {
return count1 - count2;
}
else if (operator == '*') {
return count1 * count2;
}
else if ((operator == '/' )&& (count2 != 0) && (count1%count2==0)) {
return count1 / count2;
}
else {
return -1;
}
}
}
三. 心得体会
通过查看别人的思想,学习到了24点游戏系统计算的思路,计算的重点就是理解四个数先计算两个数得出一个数,再在剩下的三个数中进行第二次计算,依次知道计算完成;除此之外,还知道了如何生成不同随机数。总之,收获很大,我会继续努力的。