Java解决24点游戏

题目

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;
 }
}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值