题目
24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。
1.程序风格良好(使用自定义注释模板)
2.列出表达式无重复。
提高要求:用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。
1. 程序风格良好(使用自定义注释模板)
2.使用计时器要求用户在规定时间内输入表达式,如果规定时间内运算正确则加分,超时或运算错误则进入下一题并减少生命值(不扣分)。
3.所有成绩均可记录在TopList.txt文件中。
本次作业完成了基本的要求以及提高要求的简化版,分为两个文件,其中基本要求为puke22.java,提高要求为pukepai.java。
算法设计
基本要求:
首先利用Java的随机生成函数生成四张不同的牌,为保证他们之间的各不相同,我们可以添加循环,代码如下:
while(k1==0)
{ k1=new
Random().nextInt(15);}
while(k2==0||k2==k1)
{k2=new
Random().nextInt(15);}
while(k3==0||k3==k1||k3==k2)
{k3=new
Random().nextInt(15);}
while(k4==0||k4==k1||k4==k2||k4==k3)
{ k4=new
Random().nextInt(15);}
System.out.println("您的牌为"+k1+" "+k2+" "+k3+" "+k4+" ");
接下来就是利用穷举法进行列举,首先要规划一下,我们不采用括号先运算的方式,而是采取前两个数先运算,然后再和下一个数运算,这样也产生了不同的问题,如果数的顺序是一定的,那就限制了一些可能性,于是我们利用排列组合的知识,四个数选两个排列得出24有12种可能,四个数选三个排列得出24有24种可能,四个数选四个排列得出24有24种可能,我们将其全部列出就好了
然后编写运算的穷举
这里只列出四选四的算法:
public static void er(float a,float b,float c,float d)
{
float e=0,e1=0,e2=0,e3=0,e4=0;
char o='0';
char p='0';
char l='0';
for(int i=0;i<4;i++)
{
switch(i)
{ case 0: e=a+b;break;
case 1: e=a-b;break;
case 2: e=a*b;break;
case 3: e=a/b;break;
}
e1=e;
for(int j=0;j<4;j++)
{
switch(j)
{ case 0: e2=e1+c;break;
case 1: e2=e1-c;break;
case 2: e2=e1*c;break;
case 3: e2=e1/c;break;
}
e3=e2;
for(int k=0;k<4;k++)
{
switch(k)
{ case 0: e4=e3+d;break;
case 1: e4=e3-d;break;
case 2: e4=e3*d;break;
case 3: e4=e3/d;break;
}
switch(i)
{ case 0: o=’+’;break;
case 1: o='-';break;
case 2:o='*';break;
case 3: o='/';break;
}
switch(j)
{ case 0: p=’+’;break;
case 1: p='-';break;
case 2:p='*';break;
case 3: p='/';break;
}
switch(k)
{ case 0: l=’+’;break;
case 1: l='-';break;
case 2:l='*';break;
case 3: l='/';break;
}
if(e4==24)
{
System.out.println((int)a+" “+o+(int)b+” “+p+(int)c+” “+l+(int)d+” “+”=24");
}
}
}
}
}
通过三次循环嵌套运算就能列出所有可能,并通过判断判断是否输出。但是这个算法还有个缺陷待解决,他会列出一些重复的例如212=24,122=24.还需要加以完善。
提高要求:
随机生成牌的代码是一样的,在这里新加了时间的判断:
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
System.out.println("耗时"+(endTime-startTime)/1000+"s");
然后通过判断时间差来决定是否超时。
设置用户类并配置属性:
public class People {
int blood=5;
int grade=0;
People(int b,int g)
{
blood=b;
grade=g;
}
}
采用编码制及数组输入的形式进行运算(符号位为1,2,3,4分别代表加减乘除)
public static int read(int a[])
{ int b=0;
switch(a[1])
{ case 1: b=a[0]+a[2];break;
case 2: b=a[0]-a[2];break;
case 3: b=a[0]*a[2];break;
case 4: b=a[0]/a[2];break;
}
if(a[3]==0)
{return b;}
switch(a[3])
{ case 1: b=b+a[4];break;
case 2: b=b-a[4];break;
case 3: b=b*a[4];break;
case 4: b=b/a[4];break;
}
if(a[5]==0)
{return b;}
switch(a[5])
{ case 1: b=b+a[6];break;
case 2: b=b-a[6];break;
case 3: b=b*a[6];break;
case 4: b=b/a[6];break;
}
return b;
}
依次运算返回b的值,然后检查是否为24,并对用户的属性进行相应操作
最后是输入检查函数:主要功能为检查输入牌与发牌是否一致
public static Boolean
check(int a[],int z1,int z2,int z3,int z4)
{
if(a[0]==z1||a[0]==z2||a[0]==z3||a[0]==z4)
{
if(a[2]==z1||a[2]==z2||a[2]==z3||a[2]==z4)
{
if(a[4]==z1||a[4]==z2||a[4]==z3||a[4]==z4||a[4]==0)
{
if(a[6]==z1||a[6]==z2||a[6]==z3||a[6]==z4||a[6]==0)
{
if(a[0]!=a[2]&&a[4]!=a[2]&&a[0]!=a[4]&&a[0]!=a[6]&&a[6]!=a[2])
{
if(a[4]==0||a[6]==0)
{return true;}
else
{
if(a[6]!=a[4])
{return true;}
else
{return false;}
}
}
else {return false;}
}else {
return false;
}
}else {
return false;
}
}else {
return false;
}
}else {
return false;
}
}
源代码
import java.util.Random;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class pukepai {
//1,2,3,4分别代表加减乘除//提前运算完下一个符号写0或不写
public static void main(String[] args) {
int t=1;
int k1;int z;int g;
int k2;int k3; int k4;
FileOutputStream fout = null;
try {
fout = new FileOutputStream("D:/test.txt");
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
PrintWriter pwr = new PrintWriter(fout);
while(t==1) {
int a[]=new int[7];
for(int i = 0;i < a.length;i++) {
a[i]=0;}
k1=0; z=0;
k2=0; k3=0; k4=0;
while(k1==0)
{ k1=new Random().nextInt(15);}
while(k2==0||k2==k1)
{k2=new Random().nextInt(15);}
while(k3==0||k3==k1||k3==k2)
{k3=new Random().nextInt(15);}
while(k4==0||k4==k1||k4==k2||k4==k3)
{ k4=new Random().nextInt(15);}
System.out.println("您的牌为"+k1+" "+k2+" "+k3+" "+k4+" ");
Scanner j = new Scanner(System.in);
Scanner s = new Scanner(System.in);
//java
People p1=new People(5,0);
long startTime = System.currentTimeMillis();
System.out.println("请输入(每一个数的输入以空格结尾(1,2,3,4分别代表加减乘除))");
String[] numbers = s.nextLine().split(" ");
for(int i = 0;i < numbers.length;i++) {
// 逐个取出再进行转换即可
a[i]=Integer.parseInt(numbers[i]);
}
long endTime = System.currentTimeMillis();
System.out.println("耗时"+(endTime-startTime)/1000+"s");
if((endTime-startTime)>20000)
{System.out.println("超时分数减一");
p1.grade-=1;
}else {
for(int i = 0;i < a.length;i++) {
System.out.print(a[i]+" ");}
System.out.println("");
if(check(a,k1,k2,k3,k4)) {
z= read(a);
if(z==24)
{ p1.grade+=1;
System.out.println("成功");
System.out.println("您的得分为"+p1.grade);
System.out.println("您的血量为"+p1.blood);
}else {
p1.blood-=1;
System.out.println("失败");
System.out.println("您的得分为"+p1.grade);
System.out.println("您的血量为"+p1.blood);
}
}else {
System.out.println("您所输入与手牌不一致");
}
}
System.out.println("是否继续下局(1继续其他数字结束)");
t=j.nextInt();
g=p1.grade;
pwr.print(g);
pwr.close();
System.out.println("成功存入");
}
}
public static int read(int a[])
{ int b=0;
switch(a[1])
{ case 1: b=a[0]+a[2];break;
case 2: b=a[0]-a[2];break;
case 3: b=a[0]*a[2];break;
case 4: b=a[0]/a[2];break;
}
if(a[3]==0)
{return b;}
switch(a[3])
{ case 1: b=b+a[4];break;
case 2: b=b-a[4];break;
case 3: b=b*a[4];break;
case 4: b=b/a[4];break;
}
if(a[5]==0)
{return b;}
switch(a[5])
{ case 1: b=b+a[6];break;
case 2: b=b-a[6];break;
case 3: b=b*a[6];break;
case 4: b=b/a[6];break;
}
return b;
}
public static Boolean check(int a[],int z1,int z2,int z3,int z4)
{
if(a[0]==z1||a[0]==z2||a[0]==z3||a[0]==z4)
{
if(a[2]==z1||a[2]==z2||a[2]==z3||a[2]==z4)
{
if(a[4]==z1||a[4]==z2||a[4]==z3||a[4]==z4||a[4]==0)
{
if(a[6]==z1||a[6]==z2||a[6]==z3||a[6]==z4||a[6]==0)
{
if(a[0]!=a[2]&&a[4]!=a[2]&&a[0]!=a[4]&&a[0]!=a[6]&&a[6]!=a[2])
{
if(a[4]==0||a[6]==0)
{return true;}
else
{
if(a[6]!=a[4])
{return true;}
else
{return false;}
}
}
else {return false;}
}else {
return false;
}
}else {
return false;
}
}else {
return false;
}
}else {
return false;
}
}
}