- 算法思路
把多元运算转化为两元运算,先从四个数中取出两个数进行运算,然后把运算结果和第三个数进行运算,再把结果与第四个数进行运算。
主要步骤:
- 将4个整数放入数组中。
- 数组中取前两个数进行运算,将运算结果存入数组,并按顺序存在数组中。
- 重复(2)
- 将最后两个数进行运算,结果存在数组中,并与24进行比较。
- (2)(3)(4)运算过程,主要靠栈来实现,当是+、- 时,可以在栈顶进行所有的操作,当是*、/时,只能进行乘除操作。
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;public class TwentyFourPoke_Game extends JFrame {
private JButton jbsolution = new JButton("提示");
private JButton jbrefresh = new JButton("刷新");
private JButton jbverify = new JButton("确认");private JLabel jlmessage = new JLabel("输入一个表达式:");
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 char[] sign = { '+', '-', '*', '/' };public TwentyFourPoke_Game() {
JPanel p1 = new JPanel(new GridLayout(1, 3));
p1.add(jbsolution);
p1.add(jtsolution);
p1.add(jbrefresh);
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);ImagePanel imagePanel = new ImagePanel();
}class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbsolution) {
for (int i = 0; i < 4; i++) {
bcard[i] = (double) card[i] % 13;
if (card[i] % 13 == 0)
bcard[i] = 13;
}
search();
} else if (e.getSource() == jbrefresh) {
pp.sshow();} else if (e.getSource() == jbverify) {
String expression = jtexpression.getText();
// evaluateExpression()计算多项式的值
int result = evaluateExpression(expression);
if (result == 24) {
JOptionPane.showMessageDialog(null, "恭喜你!你答对了!", "消息框", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, "抱歉!请再次尝试。", "消息框", JOptionPane.INFORMATION_MESSAGE);
}
}
}
}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() {
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数组中
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];// 三个数字选出先计算的两个相邻数字,两种情况,相当于第二个括号
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 == 2 && n == 0) {
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) {
// 创建操作数栈以存储操作数
java.util.Stack<Integer> operandStack = new java.util.Stack<Integer>();// 创建一个操作数栈去存储操作符
java.util.Stack<Character> operatorStack = new java.util.Stack<Character>();// 提取操作数和运算符
/*
* 这个构造函数构造一个字符串标记为指定的字符串。 第一个参数:需要操作的字符串 第二个参数:以什么为标准分割
* 第三个参数:要不要保存作为分割标准的元素,在分割后结果里仍然保存
*/
java.util.StringTokenizer tokens = new java.util.StringTokenizer(expression, "()+-/*", true);
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken().trim(); // .trim()方法是为了去除字符串前后的空格,因为不能以空格为分割标准然后保存空格
if (token.length() == 0) // 空格
continue; // 回到等待循环以提取下一个令牌
else if (token.charAt(0) == '+' || token.charAt(0) == '-') { // 是+或—(优先级要比*或/要低)
while (!operatorStack.isEmpty()
&& (operatorStack.peek().equals('+') || operatorStack.peek().equals('-')
|| operatorStack.peek().equals('*') || operatorStack.peek().equals('/'))) {
processAnOperator(operandStack, operatorStack);
}
// + -入栈
operatorStack.push(new Character(token.charAt(0)));
} else if (token.charAt(0) == '*' || token.charAt(0) == '/') {
// 在栈顶进行所有的*/运算
while (!operatorStack.isEmpty()
&& (operatorStack.peek().equals('*') || operatorStack.peek().equals('/'))) {
processAnOperator(operandStack, operatorStack);
}// */入栈
operatorStack.push(new Character(token.charAt(0)));
} else if (token.trim().charAt(0) == '(') {
operatorStack.push(new Character('(')); // (入栈
} else if (token.trim().charAt(0) == ')') {
// 在栈中进行所有是运算知道看到)
while (!operatorStack.peek().equals('(')) {
processAnOperator(operandStack, operatorStack);
}
operatorStack.pop(); // (出栈
} else {
// 操作数进栈
operandStack.push(new Integer(token));
}
}// 处理堆栈中所有剩余的运算符
while (!operatorStack.isEmpty()) {
processAnOperator(operandStack, operatorStack);
}// 返回结果
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 {
public void sshow() {
int i;
for (i = 0; i < 4; i++) {
card[i] = (int) (1 + Math.random() * 52);
}
repaint();
}public void paintComponent(Graphics g) {
/*
* 每次重绘(repaint())的时候,程序就会调用到自身的paintComponent()
* 方法在paintComponent方法中第一行就先调用了super.paintComponent进行界面重绘,
* 那么就由父类先进行界面重绘(查看JDK的源代码,你会发现,一般是恢复原状),父类重绘完之后, 界面就恢复到某个界面,
*/
super.paintComponent(g);
int i;
int w = getWidth() / 4;
int h = getHeight();
int x = 0;
int y = 0;
for (i = 0; i < 4; i++) {
ImageIcon imageIcon = new ImageIcon("src" + card[i] + ".jpg");
Image image = imageIcon.getImage();
if (image != null) {
g.drawImage(image, x, y, w, h, this);
}
x += w;
}
}
}public static void main(String[] args) {
TwentyFourPoke_Game frame = new TwentyFourPoke_Game();
frame.setTitle("24 Poke Game");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(368, 200);
frame.setVisible(true);
// void paintComponent(Graphics g);}
}