寻找导致24的算术运算

时间:2015-05-06 15:10:43

标签: java combinatorics playing-cards javafx

我正在编写一个程序来评估4张扑克牌的整数值(数字1-13),并显示一个等于24的解决方案。我有一个很大的if语句,我为此编写并且已经意识到有太多的解决方案可以添加它们。我正在寻找有关如何将其浓缩为更优化版本的建议。代码运行正常,没有错误,这是我的整个代码:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.scene.image.ImageView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicReference;
import java.util.*;

public class Main extends Application {

   private Card card1;
   private Card card2;
   private Card card3;
   private Card card4;

   private int a;
   private int b;
   private int c;
   private int d;
   private int e=0;
   private int f=0;
   boolean par=false;


   @Override
   public void start(Stage primaryStage) {

      ArrayList<Integer> deck;
      deck = new ArrayList<>();
      int i = 1;
      while(i < 52){
         deck.add(i);
         i++;
      }
      final AtomicReference<String> result = new AtomicReference<>("");

      Collections.shuffle(deck);

      BorderPane pane = new BorderPane();

      HBox top = new HBox(10);
      Label display = new Label(result.toString());
      Button btShuffle = new Button("Shuffle");
      Button fiSolution = new Button("Find Solution");
      TextField solfield = new TextField();
      VBox bottomBox = new VBox();

      top.getChildren().add(fiSolution);
      top.getChildren().add(solfield);
      top.getChildren().add(btShuffle);

      HBox center = new HBox(10);

      card1 = new Card(deck.get(0));
      center.getChildren().add(card1);

      card2 = new Card(deck.get(1));
      center.getChildren().add(card2);

      card3 = new Card(deck.get(3));
      center.getChildren().add(card3);

      card4 = new Card(deck.get(4));
      center.getChildren().add(card4);


      //String str1 = solfield.setText();

      fiSolution.setOnAction(
            (ActionEvent e) -> {

               a = card1.CardValue();
               b = card2.CardValue();
               c = card3.CardValue(); 
               d = card4.CardValue();



              if (a+b+c+d == 24)
                  solfield.setText(a+"+"+b+"+"+c+"+"+d);
               else if (a+b+c-d == 24)
                  solfield.setText(a+"+"+b+"+"+c+"-"+d);
               else if (a-b+c+d == 24)
                  solfield.setText(a+"+-"+b+"+"+c+"+"+d);   
               else if (a+b-c+d == 24)
                  solfield.setText(a+"+"+b+"-"+c+"+"+d);
               else if ((((a+b)-c)*d)==24)
                  solfield.setText(a+"+"+b+"-"+c+"*"+d);
               else if ((((a+b)-c)/d)==24)
                  solfield.setText(a+"+"+b+"-"+c+"/"+d);
               else if ((((a+b)/c)-d)==24)
                  solfield.setText(a+"+"+b+"/"+c+"-"+d);
               else if ((((a+b)/c)*d)==24)
                  solfield.setText(a+"+"+b+"/"+c+"*"+d);
               else if ((((a+b)*c)/d)==24)
                  solfield.setText(a+"+"+b+"*"+c+"/"+d);
               else if ((((a+b)*c)-d)==24)
                  solfield.setText(a+"+"+b+"*"+c+"-"+d);
               else if ((((a-b)+c)*d)==24)
                  solfield.setText(a+"-"+b+"+"+c+"*"+d);
               else if ((((a-b)+c)/d)==24)
                  solfield.setText(a+"-"+b+"+"+c+"/"+d);
               else if ((((a-b)/c)+d)==24)
                  solfield.setText(a+"-"+b+"/"+c+"+"+d);
               else if ((((a-b)/c)*d)==24)
                  solfield.setText(a+"-"+b+"/"+c+"*"+d);
               else if ((((a-b)*c)/d)==24)
                  solfield.setText(a+"-"+b+"*"+c+"/"+d);
               else if ((((a-b)*c)+d)==24)
                  solfield.setText(a+"-"+b+"*"+c+"+"+d);
               else if ((((a*b)+c)/d)==24)
                  solfield.setText(a+"*"+b+"+"+c+"/"+d);
               else if ((((a*b)+c)-d)==24)
                  solfield.setText(a+"*"+b+"+"+c+"-"+d);
               else if ((((a*b)-c)/d)==24)
                  solfield.setText(a+"*"+b+"-"+c+"/"+d);
               else if ((((a*b)-c)+d)==24)
                  solfield.setText(a+"*"+b+"-"+c+"+"+d);
               else if ((((a*b)/c)+d)==24)
                  solfield.setText(a+"*"+b+"/"+c+"+"+d);
               else if ((((a*b)/c)-d)==24)
                  solfield.setText(a+"*"+b+"/"+c+"-"+d);
               else if ((((a/b)+c)*d)==24)
                  solfield.setText(a+"/"+b+"+"+c+"*"+d);
               else if ((((a/b)+c)-d)==24)
                  solfield.setText(a+"/"+b+"+"+c+"-"+d);
               else if ((((a/b)-c)+d)==24)
                  solfield.setText(a+"/"+b+"-"+c+"+"+d);
               else if ((((a/b)-c)*d)==24)
                  solfield.setText(a+"/"+b+"-"+c+"*"+d);
               else if ((((a/b)*c)-d)==24)
                  solfield.setText(a+"/"+b+"*"+c+"-"+d);
               else if ((((a/b)*c)+d)==24)
                  solfield.setText(a+"/"+b+"*"+c+"+"+d);


               f=c+d;
               if (((a/b)*f)==24)
                  solfield.setText(a+"/"+b+"*("+c+"+"+d+")");
               else if (((a/b)-f)==24)
                  solfield.setText(a+"/"+b+"-("+c+"+"+d+")");
               else if (((a*b)-f)==24)
                  solfield.setText(a+"*"+b+"-("+c+"+"+d+")");
               else if (((a*b)/f)==24)
                  solfield.setText(a+"*"+b+"/("+c+"+"+d+")");
               else if (((a-b)*f)==24)
                  solfield.setText(a+"-"+b+"*("+c+"+"+d+")");
               else if (((a-b)/f)==24)
                  solfield.setText(a+"-"+b+"/("+c+"+"+d+")");

               f=c-d;
               if (((a/b)*f)==24)
                  solfield.setText(a+"/"+b+"*("+c+"-"+d+")");
               else if (((a/b)+f)==24)
                  solfield.setText(a+"/"+b+"+("+c+"-"+d+")");
               else if (((a*b)+f)==24)
                  solfield.setText(a+"*"+b+"+("+c+"-"+d+")");
               else if (((a*b)/f)==24)
                  solfield.setText(a+"*"+b+"/("+c+"-"+d+")");
               else if (((a+b)*f)==24)
                  solfield.setText(a+"+"+b+"*("+c+"-"+d+")");
               else if (((a+b)/f)==24)
                  solfield.setText(a+"+"+b+"/("+c+"-"+d+")");

               f=c*d;
               if (((a/b)-f)==24)
                  solfield.setText(a+"/"+b+"*("+c+"*"+d+")");
               else if (((a/b)+f)==24)
                  solfield.setText(a+"/"+b+"+("+c+"*"+d+")");
               else if (((a-b)+f)==24)
                  solfield.setText(a+"-"+b+"+("+c+"*"+d+")");
               else if (((a-b)/f)==24)
                  solfield.setText(a+"-"+b+"/("+c+"*"+d+")");
               else if (((a+b)-f)==24)
                  solfield.setText(a+"+"+b+"-("+c+"*"+d+")");
               else if (((a+b)/f)==24)
                  solfield.setText(a+"+"+b+"/("+c+"*"+d+")");

               f=c/d;
               if (((a-b)*f)==24)
                  solfield.setText(a+"-"+b+"*("+c+"/"+d+")");
               else if (((a-b)+f)==24)
                  solfield.setText(a+"-"+b+"+("+c+"/"+d+")");
               else if (((a*b)+f)==24)
                  solfield.setText(a+"*"+b+"+("+c+"/"+d+")");
               else if (((a*b)-f)==24)
                  solfield.setText(a+"*"+b+"-("+c+"/"+d+")");
               else if (((a+b)*f)==24)
                  solfield.setText(a+"+"+b+"*("+c+"/"+d+")");
               else if (((a+b)-f)==24)
                  solfield.setText(a+"+"+b+"-("+c+"/"+d+")");

               f=b*c;
               if (((a-f)/d)==24)
                  solfield.setText(a+"-("+b+"*"+c+")/"+d);
               else if (((a-f)+d)==24)
                  solfield.setText(a+"-("+b+"*"+c+")+"+d);
               else if (((a/f)+d)==24)
                  solfield.setText(a+"/("+b+"*"+c+")+"+d);
               else if (((a/f)-d)==24)
                  solfield.setText(a+"/("+b+"*"+c+")-"+d);
               else if (((a+f)/d)==24)
                  solfield.setText(a+"+("+b+"*"+c+")/"+d);
               else if (((a+f)-d)==24)
                  solfield.setText(a+"+("+b+"*"+c+")-"+d);

               f=b-c;
               if (((a*f)/d)==24)
                  solfield.setText(a+"*("+b+"-"+c+")/"+d);
               else if (((a*f)+d)==24)
                  solfield.setText(a+"*("+b+"-"+c+")+"+d);
               else if (((a/f)+d)==24)
                  solfield.setText(a+"/("+b+"-"+c+")+"+d);
               else if (((a/f)*d)==24)
                  solfield.setText(a+"/("+b+"-"+c+")*"+d);

               f=b/c;
               if (((a-f)*d)==24)
                  solfield.setText(a+"-("+b+"/"+c+")*"+d);
               else if (((a-f)+d)==24)
                  solfield.setText(a+"-("+b+"/"+c+")+"+d);
               else if (((a*f)+d)==24)
                  solfield.setText(a+"*("+b+"/"+c+")+"+d);
               else if (((a*f)-d)==24)
                  solfield.setText(a+"*("+b+"/"+c+")-"+d);
               else if (((a+f)*d)==24)
                  solfield.setText(a+"+("+b+"/"+c+")*"+d);
               else if (((a+f)-d)==24)
                  solfield.setText(a+"+("+b+"/"+c+")-"+d);

               f=b+c;
               if (((a*f)/d)==24)
                  solfield.setText(a+"*("+b+"+"+c+")/"+d);
               else if (((a*f)-d)==24)
                  solfield.setText(a+"*("+b+"+"+c+")-"+d);
               else if (((a/f)-d)==24)
                  solfield.setText(a+"/("+b+"+"+c+")-"+d);
               else if (((a/f)*d)==24)
                  solfield.setText(a+"/("+b+"+"+c+")*"+d);






            });

      btShuffle.setOnAction(
            e -> {
               center.getChildren().clear();  
               Collections.shuffle(deck);
               card1 = new Card(deck.get(0));
               card2 = new Card(deck.get(1));
               card3 = new Card(deck.get(2));
               card4 = new Card(deck.get(3));

               center.getChildren().add(card1);
               center.getChildren().add(card2);           
               center.getChildren().add(card3);
               center.getChildren().add(card4);

            });

      HBox bottom = new HBox(10);
      Label expression = new Label("Please Enter the expression: ");

      TextField tfExpress = new TextField();

      String str = tfExpress.getText();       

      Button btVerify = new Button("Verify");
      bottom.getChildren().add(expression);
      bottom.getChildren().add(tfExpress);
      bottom.getChildren().add(btVerify);

      bottomBox.getChildren().add(bottom);
      bottomBox.getChildren().add(display);

      btVerify.setOnAction(
            (ActionEvent e) -> 
            {               
               String regex = ("[^0-9]+");
               String[] inputIntegers = tfExpress.getText().split(regex);

              // expInput.removeIf(p-> p.equals(signs));
               ArrayList<Integer> temp = new ArrayList<>();
               temp.add(new Integer(card1.CardValue()));
               temp.add(new Integer(card2.CardValue()));                    
               temp.add(new Integer(card3.CardValue()));          
               temp.add(new Integer(card4.CardValue())); 

               if(inputIntegers.length != 0)
               {
                  if (inputIntegers.length != 0) {
                     for (String s : inputIntegers) {
                        if (!s.equals(""))
                           temp.remove(new Integer(Integer.valueOf(s)));
                     }
                  }        
               }

               if(temp.isEmpty())
               {
                  if(evaluateExpression(tfExpress.getText()) == 24){
                     display.setText("Correct");
                  }
                  else
                     display.setText("Incorrect");
               }
               else
                  display.setText("The numbers in the expression don't "
                     + "match the numbers in the set.");
            });

      pane.setTop(top);
      pane.setCenter(center);
      pane.setBottom(bottomBox);


      Scene scene = new Scene(pane);
      primaryStage.setTitle("24 card game");
      primaryStage.setScene(scene);
      primaryStage.show();
   }

   public boolean Twentyfour(boolean par){
   //some people play the game with or without parentheses.
      this.par=par;

      return par;
   }

   /** Evaluate an expression */
   public static int evaluateExpression(String expression) {
    // Create operandStack to store operands
      Stack<Integer> operandStack = new Stack<Integer>();

    // Create operatorStack to store operators
      Stack<Character> operatorStack = new Stack<Character>();

    // Insert blanks around (, ), +, -, /, and *
      expression = insertBlanks(expression);

    // Extract operands and operators
      String[] tokens = expression.split(" ");

    // Phase 1: Scan tokens
      for (String token: tokens) {
         if (token.length() == 0) // Blank space
            continue; // Back to the while loop to extract the next token
         else if (token.charAt(0) == '+' || token.charAt(0) == '-') {
         // Process all +, -, *, / in the top of the operator stack 
            while (!operatorStack.isEmpty() &&
            (operatorStack.peek() == '+' || 
            operatorStack.peek() == '-' ||
            operatorStack.peek() == '*' ||
            operatorStack.peek() == '/')) {
               processAnOperator(operandStack, operatorStack);
            }

         // Push the + or - operator into the operator stack
            operatorStack.push(token.charAt(0));
         }
         else if (token.charAt(0) == '*' || token.charAt(0) == '/') {
         // Process all *, / in the top of the operator stack 
            while (!operatorStack.isEmpty() &&
            (operatorStack.peek() == '*' ||
            operatorStack.peek() == '/')) {
               processAnOperator(operandStack, operatorStack);
            }

         // Push the * or / operator into the operator stack
            operatorStack.push(token.charAt(0));
         }
         else if (token.trim().charAt(0) == '(') {
            operatorStack.push('('); // Push '(' to stack
         }
         else if (token.trim().charAt(0) == ')') {
         // Process all the operators in the stack until seeing '('
            while (operatorStack.peek() != '(') {
               processAnOperator(operandStack, operatorStack);
            }

            operatorStack.pop(); // Pop the '(' symbol from the stack
         }
         else { // An operand scanned
         // Push an operand to the stack
            operandStack.push(new Integer(token));
         }
      }

    // Phase 2: process all the remaining operators in the stack 
      while (!operatorStack.isEmpty()) {
         processAnOperator(operandStack, operatorStack);
      }

    // Return the result
      return operandStack.pop();
   }

  /** Process one operator: Take an operator from operatorStack and
   *  apply it on the operands in the operandStack */
   public static void processAnOperator(
      Stack<Integer> operandStack, Stack<Character> operatorStack) {
      char op = operatorStack.pop();
      int op1 = operandStack.pop();
      int op2 = operandStack.pop();
      if (op == '+') 
         operandStack.push(op2 + op1);
      else if (op == '-') 
         operandStack.push(op2 - op1);
      else if (op == '*') 
         operandStack.push(op2 * op1);
      else if (op == '/') 
         operandStack.push(op2 / op1);
   }

   public static String insertBlanks(String s) {
      String result = "";

      for (int i = 0; i < s.length(); i++) 
      {
         if (s.charAt(i) == '(' || s.charAt(i) == ')' || 
          s.charAt(i) == '+' || s.charAt(i) == '-' ||
          s.charAt(i) == '*' || s.charAt(i) == '/')
            result += " " + s.charAt(i) + " ";
         else
            result += s.charAt(i);
      }

      return result;
   }

   public class Card extends Pane {
      public int cardVal;
      Card(int card){
         Image cardImage;
         cardImage = new Image("card/"+ card +".png");
         getChildren().add(new ImageView(cardImage));
         cardVal = card;
      }

      public int CardValue(){
         int card = 0;

         if(cardVal <= 13){
            card = cardVal;
         }
         else if(cardVal > 13 && cardVal <= 26){
            card = cardVal - 13;
         }
         else if(cardVal > 26 && cardVal <= 39){
            card = cardVal - 26;
         }
         else if(cardVal > 39 && cardVal <= 52){
            card = cardVal - 39;
         }

         return card;
      }
   }

   public static void main(String[] args) {
      launch(args);
   }
}

3 个答案:

答案 0 :(得分:4)

enum可以提供帮助。

我不确定我是否完整,因为我不确定我是否实施了所有可能的包围但现在它看起来很完整。

enum Op {

    Add("+") {

                @Override
                int op(int a, int b) {
                    return a + b;
                }

            },
    Sub("-") {

                @Override
                int op(int a, int b) {
                    return a - b;
                }

            },
    Mul("*") {

                @Override
                int op(int a, int b) {
                    return a * b;
                }

            },
    Div("/") {

                @Override
                int op(int a, int b) {
                    // Insane value for / 0 to ensure unlikely to match.
                    return b != 0 ? a / b : Integer.MAX_VALUE;
                }

            };
    final String asString;

    Op(String asString) {
        this.asString = asString;
    }

    public String toString() {
        return asString;
    }

    abstract int op(int a, int b);
}

private void tryAllOrders(int a, int b, int c, int d, Op op1, Op op2, Op op3, int target) {
    if (op3.op(op2.op(op1.op(a, b), c), d) == target) {
        System.out.println("    ((" + a + op1 + b + ")" + op2 + c + ")" + op3 + d + "=" + target);
    }
    if (op3.op(op1.op(a, op2.op(b, c)), d) == target) {
        System.out.println("    (" + a + op1 + "(" + b + op2 + c + "))" + op3 + d + "=" + target);
    }
    if (op2.op(op1.op(a, b), op3.op(c, d)) == target) {
        System.out.println("    (" + a + op1 + b + ")" + op2 + "(" + c + op3 + d + ")=" + target);
    }
    if (op1.op(a, op3.op(op2.op(b, c), d)) == target) {
        System.out.println("    " + a + op1 + "((" + b + op2 + c + ")" + op3 + d + ")=" + target);
    }
    if (op1.op(a, op2.op(b, op3.op(c, d))) == target) {
        System.out.println("    " + a + op1 + "(" + b + op2 + "(" + c + op3 + d + "))=" + target);
    }
}

private void tryAllOps(int a, int b, int c, int d, int target) {
    for (Op op1 : Op.values()) {
        for (Op op2 : Op.values()) {
            for (Op op3 : Op.values()) {
                tryAllOrders(a, b, c, d, op1, op2, op3, target);
            }
        }
    }
}

public void test() {
    int target = 24;
    for (int a = 1; a <= 13; a++) {
        for (int b = 1; b <= 13; b++) {
            for (int c = 1; c <= 13; c++) {
                for (int d = 1; d <= 13; d++) {
                    tryAllOps(a, b, c, d, target);
                }

            }

        }
    }
}

打印:

((1+1)+1)*8=24
(1+(1+1))*8=24
(1+1)*(1+11)=24
((1+1)*1)*12=24
(1+(1*1))*12=24
(1+1)*(1*12)=24
...
7+((11*8)/5)=24
((7+11)*8)/6=24
((7-11)+8)*6=24
(7-(11-8))*6=24
((7+11)/8)*12=24
(7/(11-8))*12=24
...
((13/13)*13)+11=24
(13/13)*(13+11)=24
(13/(13/13))+11=24
((13+13)/13)*12=24
(13-(13/13))+12=24
13-((13/13)-12)=24

总共有67,752个结果。

答案 1 :(得分:2)

啊,组合学!

首先,手动进行一次计算:有多少种组合?

  • 每个变量只能使用一次。
  • 变量的顺序很重要(这可以看作是括号)
  • 每个变量之间是一个数学运算,+ - * /之一,每个运算可以多次使用。

四个变量,有序,创造\ $ 4! = 4 * 3 * 2 * 1 = 24 \ $组合。

不同的数学运算会产生\ $ 4 ^ 3 = 64 \ $组合。

总计\ $ 64 * 24 = 1536 \ $组合。这不是太多,所以粗暴强迫是可以接受的。

一种方法:

这是一种选择变量和运算符的递归方式,并将其添加到结果中。

请注意,这只是一个示例方法,并且尚未经过测试,您需要进行一些调整才能使其正常工作。

void result(List<Variable> remaining, List<Variable> used, List<Operator> operatorsUsed, int current) {
    for (Variable variable : remaining) {
        for (Operator operation : operators) {
            int newValue = operation.perform(current, variable.getValue());
            List<Variable> copy = new ArrayList<>(variables);
            copy.remove(variable);
            List<Operator> usedOps = new ArrayList<>(operatorsUsed);
            usedOps.add(operation);
            int result = result(copy, newValue);
            if (result == 24) {
                 solfield.setText(createString(used, operatorsUsed));
            }
        }
    }
}

答案 2 :(得分:0)

9216个不同的方程 - 括号中的6个点(给定1 b 2 c 3 d,操作以6个不同的顺序发生),64(4x4x4)个不同的操作符和24个不同的数字顺序。

显然你不能手写这些。

然而,你可以做的是手动定义这些类中的每一个,并有三个for循环,每个循环遍历它们的操作列表。

对于实际实施,我认为策略模式最好,因为它允许您将问题分成小块。

......这是一个蛮力的解决方案,但我认为必须有更好的东西......

相关问题