java实现24点经典游戏

1.游戏简介

从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1).用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。

2.主要算法

利用栈来计算表达式的值,在与24进行比较.

2.1数据结构

LinkedList 相当于一个栈,其pop(),push()函数,就是弹栈,入栈的功能.

 //用于记录操作符
    private static LinkedList<String> operators = new LinkedList<>();
    //用于展示后缀表达式
    private static StringBuilder sb = new StringBuilder();

2.2 中缀表达式转后缀表达式

2.2.1规则

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

2.2.2 代码实现

 //中缀表达式转为后缀表达式
    private static int transferToPostfix(LinkedList<String> list) {
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if (isOperator(s)) {
                //1.操作符的栈为空直接入栈
                if (operators.isEmpty()) {
                    operators.push(s);
                } else {
                    //A1:如果读入的操作符为非")"且优先级比栈顶元素的优先级高或一样,则将操作符压入栈
                    if (priority(operators.peek()) <= priority(s) && !s.equals(")")){//peek():检索但不删除此列表的头(第一个元素)。
                        operators.push(s);
                    }//A2:如果读入的操作符为非")"且优先级比栈顶元素的优先级低,则弹出栈顶运算符
                    else if (!s.equals(")")  && priority(operators.peek()) > priority(s)) {
                            while (operators.size() != 0 && priority(operators.peek()) >= priority(s)
                                && !operators.peek().equals("(")) {
                            if (!operators.peek().equals("(")) {
                                String operator = operators.pop();
                                sb.append(operator).append(" ");
                            }
                        }
                        operators.push(s);
                    }
                    //如果读入的操作符是")",则弹出从栈顶开始第一个"("及其之前的所有操作符
                    else if (s.equals(")")) {
                        while (!operators.peek().equals("(")) {
                            String operator = operators.pop();
                            sb.append(operator).append(" ");

                        }
                        //弹出"("
                        operators.pop();
                    }
                }
            }
            //读入的为非操作符
            else {
                sb.append(s).append(" ");
            }
        }
        if (!operators.isEmpty()) {
            Iterator<String> iterator = operators.iterator();
            while (iterator.hasNext()) {
                String operator = iterator.next();
                sb.append(operator).append(" ");
                iterator.remove();
            }
        }
//        System.out.println("后缀: " + sb);
        int flag=calculate();
        return flag;
    }

2.3 计算后缀表达式的值

简单来讲,后缀表达式的计算就是从左到右扫描表达式,遇到数字就将其压入栈,遇到操作符表示可以计算,这时取出栈顶的两个元素进行操作,然后再次将结果压入栈,最后栈里会留下一个元素,该元素就是运行结果.

 //根据后缀表达式计算结果
    private static int calculate() {
        int flag=0;
        LinkedList<String> mList = new LinkedList<>();
        String[] postStr = sb.toString().split(" ");
        for (String s : postStr) {
            //字符则进行相应计算
            if (isOperator(s)) {
                if (!mList.isEmpty()) {
                    int num1 = Integer.valueOf(mList.pop());
                    int num2 = Integer.valueOf(mList.pop());
                    if (s.equals("/") && num1 == 0) {
                        System.out.println("除数不能为0");
                        return 0;
                    }
                    int newNum = cal(num2, num1, s);//计算出弹出来的两个数的结果
                    mList.push(String.valueOf(newNum));
                }
            } else {
                //数字则压入栈中
                mList.push(s);
            }
        }//
        if (!mList.isEmpty()) {
            if(Integer.parseInt(mList.pop())==24){
                ++score;
                flag=2;
                System.out.println("真棒! 加一分");

            }else{
                flag=1;
                System.out.println("可惜!");
            }
            //System.out.println("result: " + mList.pop());
            //int result= Integer.parseInt(mList.pop());
        }
        return flag;
    }

2.4 通过线程控制输入的时间

 private void  show() {
        int a = 0;
        System.out.println("请在输60秒内输入表达式(每个字符之间空一格):");
        new Thread() {
            public void run() {
                 flag=stack.m();
                if(Stack.live<1){
                    System.exit(0);
                }
            }
        }.start();
        new Thread() {
            public void run() {
                for (int i = 0; i < 10; ) {
                    try {
                        Thread.sleep(1000);
                        i++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                 if(flag==2){
                    Stack.live++;
                    flag=1;
                 }
                Stack.live--;
                System.out.println("时间到!,进入下一题(当前生命值:"+Stack.live+"    分数:"+Stack.score+")");
                show();
                if(Stack.live<1){
                    fileOut= new File("D://TopList.txt");
                    try {
                        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                        bufferedWriter=new BufferedWriter(new FileWriter(fileOut,true));
                        bufferedWriter.write(String.valueOf(df.format(new Date())+"-score:"+Stack.score+"\n"));
                        bufferedWriter.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    System.out.println("您当前生命值已用完,拜拜啦您嘞!!");
                    System.exit(0);
                }

            }
        }.start();
    }

3.运行结果

在这里插入图片描述

谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值