24点游戏
一:题目分析
24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。
1.程序风格良好(使用自定义注释模板)
2.列出表达式无重复。
基本思路:方法:穷举。
对四个数的运算实则还是算两个,只是进行多步,因此要得到所有可能的组合做到不重不漏同时编程易于实现,我采用定运算顺序变数字顺序的做法,即把运算顺序定下来,前两个先算,将达到的结果与下一个数运算,重复操作即可,变得是运算的数字,这种做法还可以推广到n个数n点,因此对四个数全排列,依次对四个数的前两个数进行四则运算,使四个数变成3个,2个,1个, 结果为24点即满足要求。’
二.算法构造
首先定义数组调用随机数生成函数将4个数存入数组,再定义集合通过多重循环把4个数的排列组合存入集合,遍历集合元素,将取出的4个数依次进行四则运算,由于‘-‘’和‘/’数字交换结果不同所以共有六种情况,构建多重循环遍历各种组合结果等于24则输出表达式,这里的表达式自己构建形式。
三.代码实现
package Point_24;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
class Game{
//生成四个数的全排列存入集合
private static ArrayList<double[]> Permutation(double[] a) {
ArrayList<double[]> arrayList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (i == j)
continue;
for (int k = 0; k < 4; k++) {
if (j == k || k == i)
continue;
for (int m = 0; m < 4; m++) {
if (m == k || m == j || m == i)
continue;
double[] b = new double[] { a[i], a[j], a[k], a[m] };
arrayList.add(b);
}
}
}
}
return arrayList;
}
//对两个数进行四则运算返回结果
private static double getNum(double a, double b, int i) {
switch (i) {
case 0:
return a + b;
case 1:
return a - b;
case 2:
return b-a;
case 3:
return a * b;
case 4:
return a / b;
case 5:
return b / a;
}
return 0;
}
//得到算式的所有结果并输出
public static String getPoint24Answer(double[] num) {
char []t=new char[] {'+','-','-','*','/','/'};
ArrayList<double[]> intlist = Permutation(num);
for (int z = 0; z < intlist.size(); z++) {
double a[] = intlist.get(z);
for (int i = 0; i < 6; i++) {
double a12 = getNum(a[0],a[1], i);
for (int j = 0; j < 6; j++) {
double a123 = getNum(a12, a[2], j);
for (int k = 0; k < 6; k++) {
double a1234 = getNum(a123, a[3], k);
//由于-和/交换数得的是不同结果,对应程序里即i,j,k=2或者5时输出形式有变化,
//这里构建多重判断语句觉得结果输出形式
if(a1234==(double)24) {
if(i==2||i==5) {
if(j==2||j==5) {
if(k==2||k==5)
//ijk都为2或5
System.out.println(String.valueOf((int)a[3])+t[k]+"("+(int)a[2]+t[j]+
"("+(int)a[1]+t[i]+(int)a[0]+"))");
else
System.out.println("("+(int)a[2]+t[j]+"("+(int)a[1]+t[i]+
(int)a[0]+"))"+t[k]+(int)a[3]);//k0
}
else {
if(k==2||k==5)
System.out.println(String.valueOf((int)a[3])+t[k]+"(("+(int)a[1]+t[i]+
(int)a[0]+")"+t[j]+(int)a[2]+")");
else System.out.println("(("+(int)a[1]+t[i]+(int)a[0]+")"+
t[j]+(int)a[2]+")"+t[k]+(int)a[3]);
}
}
else {
if(j==2||j==5) {
if(k==2||k==5)
System.out.println(String.valueOf((int)a[3])+t[k]+"("+(int)a[2]+t[j]+
"("+(int)a[0]+t[i]+(int)a[1]+"))");//i0&&j1&&k1
else System.out.println("("+(int)a[2]+t[j]+"("+(int)a[0]+
t[i]+(int)a[1]+"))"+t[k]+(int)a[3]);//i0&j1&&k0
}
else {
if(k==2||k==5)
System.out.println(String.valueOf((int)a[3])+t[k]+"(("+(int)a[0]+t[i]+
(int)a[1]+")"+t[j]+(int)a[2]+")");//i0&&j0&&k1
else System.out.println("(("+(int)a[0]+t[i]+(int)a[1]+")"+
t[j]+(int)a[2]+")"+t[k]+(int)a[3]);//i0&&j0&&k0
}
}
}
}
}
}
}
return null;
}
static int[]arg=new int[4];//四个数字
//产生四个随机数并输出
public static int Random(int[]arg)
{
Random r=new Random();//定义随机变量
for(int i=0;i<arg.length;i++)
{
arg[i]=(int)(Math.abs(r.nextInt())%13+1);//返回数的绝对值
System.out.print(cards(arg[i])+" ");
}
System.out.print("\n");
return 0;
}
//输出卡牌形式数字或者字母
public static char cards(int p)
{
/*判断产生的随机数是否为1,如果为1,则返回字符*/
if(p==1)
return 'A';
else if(p<10)
//System.out.print(p);
return (char)(p+'0');
else if(p==10)
{
System.out.print(Integer.parseInt("10",10));
return 10;
}
else if(p==11)
return 'J';
else if(p==12)
return 'Q';
else if(p==13)
return 'K';
else
return 0;
}
public static void main(String[] args) {
int g;//选择标志
@SuppressWarnings("resource")
Scanner sc=new Scanner(System.in);
System.out.println("*****24点*****");
System.out.println("请输入1生成随机数4个,输入2退出程序");
g=sc.nextInt();//获取从键盘输入的数字
//选择0,则退出游戏
if(g==2)
{
System.exit(0);
}
else
{
//用do,while循环实现先执行一次,再循环执行的功能。
do
{
System.out.println("随机生成的四个数");
Random(arg);//调用随机数生成函数,将生成的数放入数组arg[]中
//Random()函数产生4个随机数并调用字母转换函数card()将数字转换为字母输出
System.out.println(getPoint24Answer(new double[]{(double) arg[0], (double)arg[1],(double)arg[2],(double)arg[3]}));
System.out.println("请选择继续生成还是退出。继续请选1,退出请选2");
g=sc.nextInt();//获取从键盘输入的数字
}while(g==1);
}
}
}
四.运行结果
五.总结
本次作业在算法上参考了很多网上的人的做法,基本都是穷举法。加上自己的理解完成了基本要求,了解了java中集合这种数据结构,了解了对集合的一些操作,总体感觉代码并不完善,有点复杂,后面可以改进。主要问题还是输出算式这部分有些复杂不直接明了,同时多重循环也不是最好的解决办法,逻辑思维能力,对问题的分析与抽象能力还有待提高。