暑期数据结构——24点游戏
24点游戏设计
24点游戏是一种使用扑克牌来进行的益智类游戏。24点游戏内容是:从一副扑克牌中抽去大小王剩下52张,任意抽取4张牌,把牌面上的数(A代表1)运用加(+)、减(-)、乘(×)、除(÷)和括号进行运算得出24。每张牌都必须使用一次,但不能重复使用。
设计要求:
(1) 可考虑推广到n张牌(n>4)的情形;
(3) 如没有解答方案请输出“无解”的提示;
(2) 提供图形化游戏界面;
代码
package excise; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.*; import javax.swing.JOptionPane; public class Point extends JFrame { private JButton jbsolution = new JButton("生成解决方法"); private JButton jbrefresh = new JButton("开始"); private JButton jbverify = new JButton("提交"); private JLabel jlmessage = new JLabel("请输入表达式:"); private JButton jbmore = new JButton("推广到n张牌"); private JTextField jtsolution = new JTextField(); private JTextField jtexpression = new JTextField(); private ImagePanel pp = new ImagePanel(); private int[] card = new int[4]; private double[] bcard = new double[4]; private double sum; private double[] temp1 = new double[3]; private double[] temp2 = new double[2]; private int[] card2 = new int[5]; private double[] bcard2 = new double[5]; private double[] temp11 = new double[4]; private double[] temp22 = new double[3]; private double[] temp33 = new double[2]; private char[] sign = {'+','-','*','/'}; private int flag=0; public Point() { JPanel p1 = new JPanel(new GridLayout(1,3)); p1.add(jbsolution); p1.add(jtsolution); p1.add(jbrefresh); p1.add(jbmore); JPanel p3 = new JPanel(new GridLayout(1,3)); p3.add(jlmessage); p3.add(jtexpression); p3.add(jbverify); add(p1,BorderLayout.NORTH); add(pp,BorderLayout.CENTER); add(p3,BorderLayout.SOUTH); ButtonListener listener = new ButtonListener(); jbsolution.addActionListener(listener); jbrefresh.addActionListener(listener); jbverify.addActionListener(listener); jbmore.addActionListener(listener); } class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(e.getSource() ==jbmore) { flag=1; pp.sshow(); jtsolution.setText(null); } else if(e.getSource() == jbrefresh) { flag=0; pp.sshow(); jbrefresh.setText("再来一次"); jtsolution.setText(null); } else if(e.getSource() == jbverify) { String expression = jtexpression.getText(); int result = evaluateExpression(expression); if(result == 24) { JOptionPane.showMessageDialog(null,"恭喜你!你答对了!","消息框",JOptionPane.INFORMATION_MESSAGE); jtexpression.setText(null); } else { JOptionPane.showMessageDialog(null,"抱歉!请再次尝试。","消息框",JOptionPane.INFORMATION_MESSAGE); jtexpression.setText(null); } }else if(e.getSource() == jbsolution) { if(flag==0) { for(int i = 0;i < 4;i++) { bcard[i] = (double)card[i] % 13; if(bcard[i]>13) { bcard[i]=bcard[i]%13; } if(card[i] % 13 == 0) bcard[i] = 13; } search(); } if(flag==1) { for(int i = 0;i < 5;i++) { bcard2[i] = (double)card2[i] % 13; if(bcard2[i]>13) { bcard2[i]=bcard[i]%13; } if(card2[i] % 13 == 0) bcard2[i] = 13; } search_more(); } } } } public static double calcute(double a,double b,char c) { if(c == '+') return a+b; else if(c == '-') return a-b; else if(c == '*') return a*b; else if(c == '/' && b != 0) return a/b; else return -1; } public void search_more() { boolean judge = false; for(int i=0;i<4;i++) //第一次放置的符号 { for(int j=0;j<4;j++) //第二次放置的符号 { for(int k=0;k<4;k++) //第三次放置的符号 { for(int p=0;p<4;p++) { for(int m=0;m<4;m++) //首先计算的两个相邻数字,共有4种情况,相当于括号的作用 { if(bcard2[m+1]==0 && sign[i]=='/') break; temp11[m]=calcute(bcard2[m],bcard2[m+1],sign[i]); temp11[(m+1)%4]=bcard2[(m+2)%5]; temp11[(m+2)%4]=bcard2[(m+3)%5]; temp11[(m+3)%4]=bcard2[(m+4)%5]; //先确定首先计算的两个数字,计算完成相当于剩下4个数,按顺序储存在temp数组中 for(int n=0;n<3;n++) //4个数字选出先计算的两个相邻数字,三种情况,相当于第二个括号 { if(temp11[n+1]==0 && sign[j]=='/') break; temp22[n]=calcute(temp11[n],temp11[n+1],sign[j]); temp22[(n+1)%3]=temp11[(n+2)%4]; temp22[(n+2)%3]=temp11[(n+3)%4]; for(int t=0;t<2;t++) { //先确定首先计算的两个数字,计算完成相当于剩下两个数,按顺序储存在temp数组中 if(temp22[t+1]==0 && sign[k]=='/') break; temp33[t]=calcute(temp22[t],temp22[t+1],sign[k]); temp33[(t+1)%2]=temp22[(t+2)%3]; if(temp33[1]==0 && sign[p]=='/') break; sum=calcute(temp33[0],temp33[1],sign[p]); //计算和 if(sum==24) //若和为24 { //jtexpression.setText(temp33[0]+" "+temp33[1]+" "+sign[p]+"m= "+m+" n="+n+" t="+t+" i="+sign[i]+" j="+sign[j]+" k="+sign[k] ); judge=true; //判断符为1,表示已求得解 if(m==0 && n==0) { if(t==0) { String sss ="((("+(int)bcard2[0]+sign[i]+(int)bcard2[1]+")"+sign[j]+(int)bcard2[2]+")"+sign[k]+(int)bcard2[3]+")"+sign[p]+(int)bcard2[4]+"="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss ="(("+(int)bcard2[0]+sign[i]+(int)bcard2[1]+")"+sign[j]+(int)bcard2[2]+")"+sign[p]+"("+(int)bcard2[3]+sign[k]+(int)bcard2[4]+")"+"="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==0 && n==1) { if(t==0) { String sss ="(("+(int)bcard2[0]+sign[i]+(int)bcard2[1]+")"+sign[k]+"("+(int)bcard2[2]+sign[j]+(int)bcard2[3]+")"+sign[p]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss ="("+(int)bcard2[0]+sign[i]+(int)bcard2[1]+")"+sign[p]+"(("+(int)bcard2[2]+sign[j]+(int)bcard2[3]+")"+sign[k]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==0 && n==2) { if(t==0) { String sss ="(("+(int)bcard2[0]+sign[i]+(int)bcard2[1]+")"+sign[k]+(int)bcard2[2]+")"+sign[p]+"("+(int)bcard2[3]+sign[j]+(int)bcard2[4]+")"+"="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss ="("+(int)bcard2[0]+sign[i]+(int)bcard2[1]+")"+sign[p]+"("+(int)bcard2[2]+sign[k]+"("+(int)bcard2[3]+sign[j]+(int)bcard2[4]+"))="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==1 && n==0) { if(t==0) { String sss ="(("+(int)bcard2[0]+sign[j]+"("+(int)bcard2[1]+sign[i]+(int)bcard2[2]+"))"+sign[k]+(int)bcard2[3]+")"+sign[p]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss ="("+(int)bcard2[0]+sign[j]+"("+(int)bcard2[1]+sign[i]+(int)bcard2[2]+"))"+sign[p]+"("+(int)bcard2[3]+sign[k]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==1 && n==1) { if(t==0) { String sss ="("+(int)bcard2[0]+sign[k]+"(("+(int)bcard2[1]+sign[i]+(int)bcard2[2]+")"+sign[j]+(int)bcard2[3]+"))"+sign[p]+(int)bcard2[4]+"="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss =(int)bcard2[0]+sign[p]+"((("+(int)bcard2[1]+sign[i]+(int)bcard2[2]+")"+sign[j]+(int)bcard2[3]+")"+sign[k]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==1 && n==2) { if(t==0) { String sss ="("+(int)bcard2[0]+sign[k]+"("+(int)bcard2[1]+sign[i]+(int)bcard2[2]+"))"+sign[p]+"("+(int)bcard2[3]+sign[j]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss =(int)bcard2[0]+sign[p]+"(("+(int)bcard2[1]+sign[i]+(int)bcard2[2]+")"+sign[k]+"("+(int)bcard2[3]+sign[j]+(int)bcard2[4]+"))="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==2 && n==0) { if(t==0) { String sss ="(("+(int)bcard2[0]+sign[j]+(int)bcard2[1]+")"+sign[k]+"("+(int)bcard2[2]+sign[i]+(int)bcard2[3]+")"+sign[p]+(int)bcard2[4]+"="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss ="("+(int)bcard2[0]+sign[j]+(int)bcard2[1]+")"+sign[p]+"(("+(int)bcard2[2]+sign[i]+(int)bcard2[3]+")"+sign[k]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==2 && n==1) { if(t==0) { String sss ="("+(int)bcard2[0]+sign[k]+"("+(int)bcard2[1]+sign[j]+"("+(int)bcard2[2]+sign[i]+(int)bcard2[3]+")))"+sign[p]+(int)bcard2[4]+"="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss =(int)bcard2[0]+sign[p]+"(("+(int)bcard2[1]+sign[j]+"("+(int)bcard2[2]+sign[i]+(int)bcard2[3]+"))"+sign[k]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==2 && n==2) { if(t==0) { String sss ="("+(int)bcard2[0]+sign[k]+(int)bcard2[1]+")"+sign[p]+"(("+(int)bcard2[2]+sign[i]+(int)bcard2[3]+")"+sign[j]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss =(int)bcard2[0]+sign[p]+"("+(int)bcard2[1]+sign[k]+"(("+(int)bcard2[2]+sign[i]+(int)bcard2[3]+")"+sign[j]+(int)bcard2[4]+"))="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==3 && n==0) { if(t==0) { String sss ="(("+(int)bcard2[0]+sign[j]+(int)bcard2[1]+")"+sign[k]+(int)bcard2[2]+")"+sign[p]+"("+(int)bcard2[3]+sign[i]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss ="("+(int)bcard2[0]+sign[j]+(int)bcard2[1]+")"+sign[p]+"("+(int)bcard2[2]+sign[k]+"("+(int)bcard2[3]+sign[i]+(int)bcard2[4]+"))="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==3 && n==1) { if(t==0) { String sss ="("+(int)bcard2[0]+sign[k]+"("+(int)bcard2[1]+sign[j]+(int)bcard2[2]+"))"+sign[p]+"("+(int)bcard2[3]+sign[i]+(int)bcard2[4]+")="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss =(int)bcard2[0]+sign[p]+"(("+(int)bcard2[1]+sign[j]+(int)bcard2[2]+")"+sign[k]+"("+(int)bcard2[3]+sign[i]+(int)bcard2[4]+"))="+(int)sum; jtsolution.setText(sss); } return ; } else if(m==3 && n==2) { if(t==0) { String sss ="("+(int)bcard2[0]+sign[k]+(int)bcard2[1]+")"+sign[p]+"("+(int)bcard2[2]+sign[j]+"("+(int)bcard2[3]+sign[i]+(int)bcard2[4]+"))="+(int)sum; jtsolution.setText(sss); }else if(t==1) { String sss =(int)bcard2[0]+sign[p]+"("+(int)bcard2[1]+sign[k]+"("+(int)bcard2[2]+sign[j]+"("+(int)bcard2[3]+sign[i]+(int)bcard2[4]+")))="+(int)sum; jtsolution.setText(sss); } return ; } //m=0,1,2,3 n=0,1,2 t=0,1表示24种括号放置可能,并按照这24种可能输出相应的格式的计算式 } } } } } } } } if(judge==false) jtsolution.setText("无解!"); //如果没有找到结果,符号位为0 } public void search() { boolean judge = false; for(int i=0;i<4;i++) //第一次放置的符号 { for(int j=0;j<4;j++) //第二次放置的符号 { for(int k=0;k<4;k++) //第三次放置的符号 { for(int m=0;m<3;m++) //首先计算的两个相邻数字,共有3种情况,相当于括号的作用 { if(bcard[m+1]==0 && sign[i]=='/') break; temp1[m]=calcute(bcard[m],bcard[m+1],sign[i]); temp1[(m+1)%3]=bcard[(m+2)%4]; temp1[(m+2)%3]=bcard[(m+3)%4]; //先确定首先计算的两个数字,计算完成相当于剩下三个数,按顺序储存在temp数组中 for(int n=0;n<2;n++) //三个数字选出先计算的两个相邻数字,两种情况,相当于第二个括号 { if(temp1[n+1]==0 && sign[j]=='/') break; temp2[n]=calcute(temp1[n],temp1[n+1],sign[j]); temp2[(n+1)%2]=temp1[(n+2)%3]; //先确定首先计算的两个数字,计算完成相当于剩下两个数,按顺序储存在temp数组中 if(temp2[1]==0 && sign[k]=='/') break; sum=calcute(temp2[0],temp2[1],sign[k]); //计算和 if(sum==24) //若和为24 { judge=true; //判断符为1,表示已求得解 if(m==0 && n==0) { String sss ="(("+(int)bcard[0]+sign[i]+(int)bcard[1]+")"+sign[j]+(int)bcard[2]+")"+sign[k]+(int)bcard[3]+"="+(int)sum; jtsolution.setText(sss); return ; } else if(m==0 && n==1) { String sss ="("+(int)bcard[0]+sign[i]+(int)bcard[1]+")"+sign[k]+"("+(int)bcard[2]+sign[j]+(int)bcard[3]+")="+(int)sum; jtsolution.setText(sss); return ; } else if(m==1 && n==0) { String sss ="("+(int)bcard[0]+sign[j]+"("+(int)bcard[1]+sign[i]+(int)bcard[2]+"))"+sign[k]+(int)bcard[3]+"="+(int)sum; jtsolution.setText(sss); return ; } else if(m==2 && n==0) { String sss ="("+(int)bcard[0]+sign[j]+(int)bcard[1]+")"+sign[k]+"("+(int)bcard[2]+sign[i]+(int)bcard[3]+")="+(int)sum; jtsolution.setText(sss); return ; }else if(m==1&&n==1) { String sss =(int)bcard[0]+sign[j]+"(("+(int)bcard[1]+sign[k]+(int)bcard[2]+")"+sign[i]+(int)bcard[3]+")="+(int)sum; jtsolution.setText(sss); } else if(m==2 && n==1) { String sss =(int)bcard[0]+sign[k]+"("+(int)bcard[1]+sign[j]+"("+(int)bcard[2]+sign[i]+(int)bcard[3]+"))="+(int)sum; jtsolution.setText(sss); return ; } //m=0,1,2 n=0,1表示六种括号放置可能,并按照这六种可能输出相应的格式的计算式 } } } } } } if(judge==false) jtsolution.setText("无解!"); //如果没有找到结果,符号位为0 } public static int evaluateExpression(String expression) { // Create operandStack to store operands java.util.Stack<Integer> operandStack = new java.util.Stack<Integer>(); // Create operatorStack to store operators java.util.Stack<Character> operatorStack = new java.util.Stack<Character>(); // Extract operands and operators java.util.StringTokenizer tokens = new java.util.StringTokenizer(expression, "()+-/*", true); // Phase 1: Scan tokens while (tokens.hasMoreTokens()) { String token = tokens.nextToken().trim(); // Extract a token 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().equals('+') ||operatorStack.peek().equals('-') || operatorStack.peek().equals('*') || operatorStack.peek().equals('/'))) { processAnOperator(operandStack, operatorStack); } // Push the + or - operator into the operator stack operatorStack.push(new Character(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().equals('*') || operatorStack.peek().equals('/'))) { processAnOperator(operandStack, operatorStack); } // Push the * or / operator into the operator stack operatorStack.push(new Character(token.charAt(0))); } else if (token.trim().charAt(0) == '(') { operatorStack.push(new Character('(')); // Push '(' to stack } else if (token.trim().charAt(0) == ')') { // Process all the operators in the stack until seeing '(' while (!operatorStack.peek().equals('(')) { 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 ((Integer)(operandStack.pop())).intValue(); } public static void processAnOperator(java.util.Stack<Integer> operandStack,java.util.Stack<Character> operatorStack) { if (operatorStack.peek().equals('+')) { operatorStack.pop(); int op1 = ((Integer)(operandStack.pop())).intValue(); int op2 = ((Integer)(operandStack.pop())).intValue(); operandStack.push(new Integer(op2 + op1)); } else if (operatorStack.peek().equals('-')) { operatorStack.pop(); int op1 = ((Integer)(operandStack.pop())).intValue(); int op2 = ((Integer)(operandStack.pop())).intValue(); operandStack.push(new Integer(op2 - op1)); } else if (operatorStack.peek().equals('*')) { operatorStack.pop(); int op1 = ((Integer)(operandStack.pop())).intValue(); int op2 = ((Integer)(operandStack.pop())).intValue(); operandStack.push(new Integer(op2 * op1)); } else if (operatorStack.peek().equals('/')) { operatorStack.pop(); int op1 = ((Integer)(operandStack.pop())).intValue(); int op2 = ((Integer)(operandStack.pop())).intValue(); operandStack.push(new Integer(op2 / op1)); } } class ImagePanel extends JPanel { private int num=0; public void sshow() { int i; for(i = 0;i < 4;i++) { card[i] = (int)Math.floor(1 + Math.random() * 52); } while(compare(card)) { card[num] = (int)Math.floor(1 + Math.random() * 52); } for(i=0;i<5;i++) { card2[i]= (int)Math.floor(1 + Math.random() * 52); } while(compare(card2)) { card2[num] = (int)Math.floor(1 + Math.random() * 52); } repaint(); } public boolean compare(int a[]) { boolean flag=false; for(int i=0;i<a.length-1;i++) { for(int j=i+1;j<a.length;j++) { if(a[i]==a[j]) { flag=true; num=i; } } } return flag; } protected void paintComponent(Graphics g) { super.paintComponent(g); int i; if(flag==1) { int w = getWidth() / 5; int h = getHeight(); int x = 0; int y = 0; for(i = 0;i < 5;i++) { ImageIcon imageIcon = new ImageIcon("image/" + card2[i] + ".png"); Image image = imageIcon.getImage(); if(image != null) { g.drawImage(image,x,y,w,h,this); } x += w; } }else { int w = getWidth() / 4; int h = getHeight(); int x = 0; int y = 0; for(i = 0;i < 4;i++) { ImageIcon imageIcon = new ImageIcon("image/" + card[i] + ".png"); Image image = imageIcon.getImage(); if(image != null) { g.drawImage(image,x,y,w,h,this); } x += w; } } } } public static void main(String[] args) { Point frame = new Point(); frame.setTitle("24点游戏"); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(450,330); frame.setVisible(true); } }