24点游戏

z24点纸牌游戏是从52张牌中挑选任意4张牌,如下图所示。 请注意,Jokers被排除在外。 每张卡代表一个号码。 Ace,King,Queen和Jack分别代表1,13,12和11。 您可以单击“刷新”按钮以获得四张新卡。

输入一个表达式,该表达式使用四张选定卡片中的四个数字。 每个号码必须使用一次且只能使用一次。 您可以在表达式中使用运算符(加法,减法,乘法和除法)和括号。 表达式必须求值为24.输入表达式后,单击“验证”按钮以检查表达式中的数字是否正确。 在消息窗口中显示验证(参见下图)。
假设图像以黑桃,红桃,方块和梅花的顺序存储在名为1.png,2.png,...,52.png的文件中。 因此,前13张图片适用于黑桃1,2,3 ... 13。
假设在第一个令牌之前,令牌之间和最后一个令牌之后没有输入空格。 假设只能输入数字作为操作数。

在src包下放一个image包,里面图片以黑桃♠️、红桃♥️、方块♦️、梅花♣️的顺序存储在名为1.png,2.png,...,52.png的文件中,在生成jar包时可以包含在内


Driver.java

package TwentyFourPoints;

/**
* Displays a 2-point game.
* @author Qi Wang
* @version 1.0
*/
public class Driver {

    /**
     * Displays a 2-point game.
     * @param args A reference to a string array
     */
    public static void main(String[] args) {
        new TwentyFourPointsFrame();
    }
}


Expression.java
 

package TwentyFourPoints;

import java.util.*;

/**
* filename: SyntaxErrorException.java
* package:project03.twentyfourpoints
* author:XuWanxiang
* date:2018
* description: this class show expression.
* @version 1.0
*/

public class Expression {

    /**
     * The content of this expression
     */

    private String infix;

    public Expression(){
        this.infix = null;
    }

    public Expression(String infix){
        this.infix = infix;

    }

    /**
     * description: convert a string from infix to postfix
     * @return - arrayListPostfix
     * @throws Exception
     */
    public ArrayList<String> infixToPostfix(){
        ArrayList<String> arrayListPostfix = new ArrayList<String>();
        String stringPostfix = null;

        InfixToPostfixConvertor ITPC = new InfixToPostfixConvertor();
        try  {
            stringPostfix = ITPC.convert(this.infix);
        }catch (Exception e) {
            e.printStackTrace();
        }

        StringTokenizer PostfixTokens = new StringTokenizer(stringPostfix);
        while (PostfixTokens.hasMoreTokens()) {
            arrayListPostfix.add(PostfixTokens.nextToken());
        }

        return arrayListPostfix;
    }

    /**
     * description: evaluate Postfix to find out the value of the input equation.
     * @return - the postfix string
     * @throws Exception
     */
    public int evaluatePostfix(){

        ArrayList<String> postfix = infixToPostfix();
        Stack<Double> s = new Stack<Double>();
        Double a, b, result=0.0;
        //a\b is Intermediate variables of the calculation process,result is variable that push in to the stack.
        boolean isNumber;

        for (int index = 0;index < postfix.size();index++){
            try
            {
                isNumber = true;
                result = Double.parseDouble(postfix.get(index));
                //if the element is not number ,set isNumber false.
            }
            catch (Exception e)
            {
                isNumber = false;
            }
            if (isNumber)
                //push the element in to the stack if the element is number.
                s.push(result);
            else
            {   //pop two number and do the calculus and push the result in to the stack.
                switch (postfix.get(index).charAt(0))
                {
                    case '+':
                        a = s.pop();
                        b = s.pop();
                        s.push(b+a);
                        break;
                    case '-':
                        a = s.pop();
                        b = s.pop();
                        s.push(b-a);
                        break;
                    case '*':
                        a = s.pop();
                        b = s.pop();
                        s.push(b*a);
                        break;
                    case '/':
                        a = s.pop();
                        b = s.pop();
                        s.push(b/a);
                        break;
                    case '^':
                        a = s.pop();
                        b = s.pop();
                        s.push(Math.exp(a*Math.log(b)));//it's equal to "b^a".
                        break;
                }
            }
        }

        //after the loop ,there are only one element left in the stack.
        double doubleRes = s.peek();

        //return the peek element,but not delete it.
        int integerRes = (int) doubleRes;
        return integerRes;

    }

    //Other methods

    /**
     * description: get the value of the infix.
     * @return - infix
     */
    public String getInfix(){
        return infix;
    }

    /**
     * description: set the value of the infix.
     * @param str
     */
    public void setInfix(String str){
        this.infix = str;
    }
    //Helper methods
}

 

InfixToPostfixConvertor


package TwentyFourPoints;

import java.util.*;

/**
 * filename: InfixtoPostfixConvertor.java
 * @package:InfixtoPostfixConvertor
 * @author:XuWanxiang
 * date:2018/11/7
 * @description: this class crate a convertor that turn infix to postfix.
 * @version 1.0
 */
public class InfixToPostfixConvertor {
    /**
     * The list of objects of this stack
     */

    // the operator stack
    private Stack<Character> operatorStack;

    // the operators
    private   static   final  String OPERATORS =  "+-*/()" ;

    // the precedence of the operators
    private   static   final   int [] PRECEDENCE = { 1 ,  1 ,  2 ,  2 , - 1 , - 1 };

    // the postfix string
    private  StringBuilder postfix;

    /**
     * description: the default constructor
     */
    public InfixToPostfixConvertor() {
        // TODO Auto-generated constructor stub*/
        postfix =  new  StringBuilder();
    }

    /**
     * description: convert a string from infix to postfix
     * @param infix - the infix string to input
     * @return - the postfix string
     * @throws Exception
     */
    public String convert(String infix) throws Exception{
        operatorStack = new Stack<Character>();
        StringTokenizer infixTokens = new StringTokenizer(addSpace(infix));
        try {
            // process each token in the infix string
            while (infixTokens.hasMoreTokens()){
                String nextToken = infixTokens.nextToken();
                char firstChar = nextToken.charAt(0);
                // determine if it is an operator
                if (Character.isJavaIdentifierStart(firstChar) || Character.isDigit(firstChar)) {
                    postfix.append(nextToken);
                    postfix.append(' ');
                } else if (isOperator(firstChar)){
                    processOperator(firstChar);
                } else {
                    throw new SyntaxErrorException("syntax error!");
                }
            }
            // pop any remaining operators and append them to postfix
            while (!operatorStack.isEmpty()){
                Character op = operatorStack.pop();
                // any '(' on the stack is not matched
                if (op.charValue() == '('){
                    throw new SyntaxErrorException("syntax error!");
                }
                postfix.append(op);
                postfix.append(' ');
            }
            return postfix.toString();
        } catch (EmptyStackException e){
            throw new SyntaxErrorException("the stack is empty!");
        }
    }

    /**
     * description: process operators
     * @param op - the operator
     */
    private   void  processOperator(char op){
        if (operatorStack.isEmpty() || op == '(' ){
            operatorStack.push(op);
        }  else  {
            // peek the operator stack
            char  topOp = operatorStack.peek().charValue();
            if (precedence(op) > precedence(topOp)){
                operatorStack.push(op);
            }  else  {
                // pop all stacked operators with equal or higher precedence than op
                while (!operatorStack.isEmpty() && precedence(op) <= precedence(topOp)) {
                    operatorStack.pop();
                    if (topOp ==  '(' ){
                        break ;
                    }
                    postfix.append(topOp);
                    postfix.append( ' ' );
                    if (!operatorStack.isEmpty()){
                        // reset topOp
                        topOp = operatorStack.peek().charValue();
                    }
                }
                if (op !=  ')' ) {
                    operatorStack.push(op);
                }
            }
        }
    }

    /**
     * description: determine the precedence of an operator
     * @param op - the operator
     * @return - the precedence
     */
    private int precedence(char op){
        return PRECEDENCE[OPERATORS.indexOf(op)];
    }

    /**
     * description: determine whether a char is an operator
     * @param op - the given char
     * @return - true if the char is an operator
     */
    private boolean isOperator(char op){
        return OPERATORS.indexOf(op) != -1;
    }

    /**
     * description: add space between every element of a string
     * @param str - the infix string to add Space
     * @return - sb.toString()
     * @throws Exception
     */
    public String addSpace(String str){
        StringTokenizer infixTokens = new StringTokenizer(str,OPERATORS,true);
        StringBuilder sb = new StringBuilder();
        while (infixTokens.hasMoreTokens()){
            String nextToken = infixTokens.nextToken();
            sb.append(nextToken);
            if (infixTokens.hasMoreTokens()){
                sb.append(" ");
            }
        }
        return sb.toString();
    }
}

SyntaxErrorException


package TwentyFourPoints;

/**
 * filename: SyntaxErrorException.java
 * package:project03.twentyfourpoints
 * author:Xu Wanxiang
 * date:2018/11/7
 * description: this exception shows a syntax error.
 */
public class SyntaxErrorException extends  Exception {
    private   static   final   long  serialVersionUID = 1L;
    public  SyntaxErrorException( final  String message) {
        super(message);
    }
}

TwentyFourPointsActionListener


package TwentyFourPoints;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JOptionPane;

/**
 * Process actions event triggered by a button
 * @author Qi Wang
 * @version 1.0
 */
public class TwentyFourPointsActionListener implements ActionListener{
    /**
     * A reference to a panel
     */
    private JPanel panel;

    /**
     * Constructs an action listener with a panel.
     * @param panel A reference to a panel
     */
    public TwentyFourPointsActionListener(JPanel panel){
        this.panel = panel;
    }

    /**
     * Invoked when an action occurs.
     * @param e A reference to an action event object
     */
    public void actionPerformed(ActionEvent e) {
        if(this.panel instanceof TwentyFourPointsPanel){
            TwentyFourPointsPanel temp = (TwentyFourPointsPanel)this.panel;
            if(e.getSource() == temp.getVerify()){
                // Check whether all numbers in the expression are currently selected
                if (!temp.correctNumbers()) {
                    JOptionPane.showMessageDialog(null, "The numbers in the expression don't \nmatch the numbers in the set ");
                }else{
                    // Check whether the expression evaluates to 24.
                    if (temp.evaluate()) {
                        JOptionPane.showMessageDialog(null, "Correct");
                    } else {
                        JOptionPane.showMessageDialog(null, "Incorrect result");
                    }
                }
            }
            if(e.getSource() == temp.getRefresh()){
                temp.refresh();
            }
        }
    }
}

TwentyFourPointsFrame


package TwentyFourPoints;

import javax.swing.JFrame;

/**
 * Displays 24-point game.
 * @author Qi Wang
 * @version 1.0
 */
public class TwentyFourPointsFrame extends JFrame{
    /**
     * Constructs an interface of 24-point game.
     */
    public TwentyFourPointsFrame(){
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("24-Point Card Game");

        TwentyFourPointsPanel panel = new TwentyFourPointsPanel();
        this.getContentPane().add(panel);

        this.pack();
        this.setVisible(true);
    }
}

TwentyFourPointsPanel


package TwentyFourPoints;

import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.ImageIcon;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Dimension;

/**
 * Display all components of 24-point game. The components are a refresh button, a panel with four labels with card
 * image icons, a text field for an expression, and a verify button.
 * @author Qi Wang
 * @version 1.0
 */
public class TwentyFourPointsPanel extends JPanel{
    /**
     * The refresh button
     */
    private JButton refresh;
    /**
     * The verify button
     */
    private JButton verify;
    /**
     * The cards panel
     */
    private JPanel cards;
    /**
     * The expression text field
     */
    private JTextField expression;
    /**
     * The first card label
     */
    private JLabel card1;
    /**
     * The second card label
     */
    private JLabel card2;
    /**
     * The third card label
     */
    private JLabel card3;
    /**
     * The fourth card label
     */
    private JLabel card4;
    /**
     * The 52 image icons
     */
    private ImageIcon[] cardIcons = new ImageIcon[52];
    /**
     * THe 52 integers from 1 to 52
     */
    private ArrayList<Integer>  list= new ArrayList<Integer>();

    /**
     * Current card values
     */
    private ArrayList<Integer> currentCardValues = new ArrayList<Integer>();

    /**
     * Constructs a 24-point game panel.
     */
    public TwentyFourPointsPanel() {
        this.setPreferredSize(new Dimension(350,180));
        this.setLayout(new BorderLayout());

        //Load all 52 numbers that will be shuffled.
        for (int i = 0; i < 52; i++){
            this.list.add(i);
        }
        // Load the image icons
        for (int i = 0; i < 52; i++){
            this.cardIcons[i] = new ImageIcon(TwentyFourPointsPanel.class.getResource("/image/" + (i + 1) + ".png"));
        }

        // refresh panel
        JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        this.refresh = new JButton("Refresh");
        panel1.add(this.refresh);

        // card panel
        this.card1 = new JLabel();
        this.card2 = new JLabel();
        this.card3 = new JLabel();
        this.card4 = new JLabel();
        this.cards = new JPanel();
        this.cards.add(this.card1);
        this.cards.add(this.card2);
        this.cards.add(this.card3);
        this.cards.add(this.card4);

        //expression panel
        this.verify = new JButton("Verify");
        this.expression = new JTextField(8);
        JPanel panel3 = new JPanel(new BorderLayout());
        panel3.add(new JLabel("Enter an expression: "), BorderLayout.WEST);
        panel3.add(this.expression, BorderLayout.CENTER);
        panel3.add(this.verify, BorderLayout.EAST);

        this.add(panel1, BorderLayout.NORTH);
        this.add(this.cards, BorderLayout.CENTER);
        this.add(panel3, BorderLayout.SOUTH);

        //Chooses the first four cards after they are shuffled. Changes card image icons accordingly.
        this.refresh();

        TwentyFourPointsActionListener listener = new TwentyFourPointsActionListener(this);
        this.refresh.addActionListener(listener);
        this.verify.addActionListener(listener);
    }

    /**
     * Verifies if numbers of the expression matches the numbers of the cards.
     * @return A boolean value specifying if numbers of the expression matches the numbers of the cards
     */
    public boolean correctNumbers() {
        // Constructs a string tokenizer for the specified expression.
        // The delimiters are ()+-/* that are not returned as tokens.
        // Only operands in the expression are returned as tokens.
        StringTokenizer tokens = new StringTokenizer(this.expression.getText().trim(), "()+-/*", false);

        // The array list of operands of this expression
        ArrayList<Integer> valueList = new ArrayList<Integer>();

        // Each token is returned as a string that can be used to make an Integer object.
        while(tokens.hasMoreTokens()){
            //valueList.add(Integer.parseInt(tokens.nextToken()));
            valueList.add(new Integer(tokens.nextToken()));
        }

        Collections.sort(valueList);
        Collections.sort(this.currentCardValues);

        return valueList.equals(this.currentCardValues);
    }

    /**
     * Evaluates current expression, and return a value to indicate if the result is equal to 24.
     * Converts this infix expression into a postfix form, and evaluates the postfix form.
     * @return A boolean value specifying if the result is equal to 24
     * */
    public boolean evaluate() {
        //Create an expression with the user-entered expression.
        Expression exp = new Expression(expression.getText().trim());
        //Evaluate the expression, and check if the result is 24.
        return exp.evaluatePostfix() == 24;
    }


    /**
     * Chooses the first four cards after they are shuffled. Changes card image icons accordingly.
     */
    public void refresh() {
        //Clear the expression
        this.expression.setText(null);

        //Shuffle the list of cards(integers)
        Collections.shuffle(this.list);

        //Pick the first four as the fours cards
        int index1 = this.list.get(0);
        int index2 = this.list.get(1);
        int index3 = this.list.get(2);
        int index4 = this.list.get(3);

        //Change card image icons accordingly
        this.card1.setIcon(this.cardIcons[index1]);
        this.card2.setIcon(this.cardIcons[index2]);
        this.card3.setIcon(this.cardIcons[index3]);
        this.card4.setIcon(this.cardIcons[index4]);

        //Clear the previous card values, and add new card values
        //Card values 1 to 13 repeat
        this.currentCardValues.clear();
        this.currentCardValues.add(index1 % 13 + 1);
        this.currentCardValues.add(index2 % 13 + 1);
        this.currentCardValues.add(index3 % 13 + 1);
        this.currentCardValues.add(index4 % 13 + 1);
    }

    /**
     * Returns a reference to this refresh button.
     * @return A reference to a button
     */
    public JButton getRefresh(){
        return this.refresh;
    }

    /**
     * Returns a reference to this verify button.
     * @return A reference to a button
     */
    public JButton getVerify(){
        return this.verify;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值