内容
24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式,用擅长的语言(C/C++/Java或其他均可)实现程序解决问题。
1.程序风格良好(使用自定义注释模板)
2.列出表达式无重复。
提高要求:用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。
1. 程序风格良好(使用自定义注释模板)
2.使用计时器要求用户在规定时间内输入表达式,如果规定时间内运算正确则加分,超时或运算错误则进入下一题并减少生命值(不扣分)。
3.所有成绩均可记录在TopList.txt文件中。
算法分析
创建一个person类存放玩家的分数和生命值;创建一个洗牌类Makepuker实现洗牌和发牌,用Hashmap储存扑克,调用Collctions的suffer方法实现习洗牌;类player实现游戏的运行,其中calculate函数中实现中缀表达式计算,play函数用于中调用Makerpuker中的makerpuker函数洗牌,然后用户根据puker输入表达式,计时器判断是否超时,如果超时则不用比价结果直接进入下一行,否则比较;play类中的make函数对makerpuker函数中的返回值进行判断,并向用户响应相应的结果,main函数调用make函数,并将结果写入文件。
概要设计
代码
package game;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class Makepuker {
public String[] makepuker() {
List<String> color = List.of("♥", "♠", "♣", "♦");
List<String> number = List.of("A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "k");
//存放扑克
HashMap<Integer, String> pai = new HashMap<>();
//存放扑克的所引
ArrayList<Integer> index = new ArrayList<>();
int i = 0;
//循环嵌套存放扑克和索引
for (String c : color) {
for (String n : number) {
pai.put(i, n + c);
index.add(i);
i++;
}
}
//洗牌
Collections.shuffle(index);
// System.out.println(index);
//System.out.println(pai);
//取出前4张牌
String puker[] = new String[4];
for (int j = 0; j <= 3; j++) {
puker[j] = pai.get(index.get(j));
System.out.println(puker[j]);
}
return puker;
}
}
package game;
public class person {
private int life;
private int score ;
public person(int life, int score) {
this.life = life;
this.score = score;
}
public person() {
}
public int getLife() {
return life;
}
public void setLife(int life) {
this.life = life;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
package game;
import game.thread.threadpool;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class player {
public int play(){
//获取开始游戏时系统时间
long star = System.currentTimeMillis();
//洗牌
Makepuker makepuker=new Makepuker();
makepuker.makepuker();
System.out.println("根据扑克输入表达式");
Scanner scanner=new Scanner(System.in);
String s=scanner.next();
BigDecimal a= new BigDecimal(24);
person p=new person();
//获取系统时间
long end = System.currentTimeMillis();
if(end-star<20000) {//如果时间小于10秒则进行比较
if (calculate(s).equals(a)) {//输入的表达式等于24
return 1;
} else {//输入的表达式不等于24
return 2;
}
}else {//时间到了
return 3;
}
}
//计算加减乘除四则运算
public BigDecimal calculate(String str){
// 对表达式进行预处理,并简单验证是否是正确的表达式
// 存放处理后的表达式
List<String> list = new ArrayList<>();
char[] arr = str.toCharArray();
// 存放数字临时变量
StringBuffer tmpStr = new StringBuffer();
for (char c : arr) {
// 如果是数字或小数点,添加到临时变量中
if (c >= '0' && c <= '9') {
tmpStr.append(c);
} else if (c == '.') {
if (tmpStr.indexOf(".") > 0) {
throw new RuntimeException("非法字符");
}
tmpStr.append(c);
}
// 如果是加减乘除或者括号,将数字临时变量和运算符依次放入list中
else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') {
if (tmpStr.length() > 0) {
list.add(tmpStr.toString());
tmpStr.setLength(0);
}
list.add(c + "");
}
// 如果是空格,跳过
else if (c == ' ') {
continue;
} else {
throw new RuntimeException("非法字符");
}
}
if (tmpStr.length() > 0) {
list.add(tmpStr.toString());
}
// 初始化后缀表达式
List<String> strList = new ArrayList<>();
// 运算过程中,使用了两次栈结构,第一次是将中缀表达式转换为后缀表达式,第二次是计算后缀表达式的值
Stack<String> stack = new Stack<>();
// 声明临时变量,存放出栈元素
String tmp;
// 1. 将中缀表达式转换为后缀表达式
for (String s : list) {
// 如果是左括号直接入栈
if (s.equals("(")) {
stack.push(s);
}
// 如果是右括号,执行出栈操作,依次添加到后缀表达式中,直到出栈元素为左括号,左括号和右括号都不添加到后缀表达式中
else if (s.equals(")")) {
while (!(tmp = stack.pop()).equals("(")) {
strList.add(tmp);
}
}
// 如果是加减乘除,弹出所有优先级大于或者等于该运算符的栈顶元素(栈中肯定没有右括号,认为左括号的优先级最低),然后将该运算符入栈
else if (s.equals("*") || s.equals("/")) {
while (!stack.isEmpty()) {
// 取出栈顶元素
tmp = stack.peek();
if (tmp.equals("*") || tmp.equals("/")) {
stack.pop();
strList.add(tmp);
} else {
break;
}
}
stack.push(s);
} else if (s.equals("+") || s.equals("-")) {
while (!stack.isEmpty()) {
// 取出栈顶元素
tmp = stack.peek();
if (!tmp.equals("(")) {
stack.pop();
strList.add(tmp);
} else {
break;
}
}
stack.push(s);
}
// 如果是数字,直接添加到后缀表达式中
else {
strList.add(s);
}
}
// 最后依次出栈,放入后缀表达式中
while (!stack.isEmpty()) {
strList.add(stack.pop());
}
// 2.计算后缀表达式的值
Stack<BigDecimal> newStack = new Stack<>();
for (String s : strList) {
// 若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,
// 运算后的结果再进栈,直到后缀表达式遍历完毕
if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {
BigDecimal b1 = newStack.pop();
BigDecimal b2 = newStack.pop();
switch (s) {
case "+":
newStack.push(b2.add(b1));
break;
case "-":
newStack.push(b2.subtract(b1));
break;
case "*":
newStack.push(b2.multiply(b1));
break;
case "/":
newStack.push(b2.divide(b1, 9, BigDecimal.ROUND_HALF_UP));
break;
}
}
// 如果是数字,入栈
else {
newStack.push(new BigDecimal(s));
}
}
// 最后,栈中仅有一个元素,就是计算结果
return newStack.peek();
}
}
package game;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class play {
public static void main(String[] args) throws IOException {
//创建玩家p
person p=new person(3,2);
System.out.println("你的生命值: "+p.getLife()+"你的分数为: "+p.getScore());
//player player1=new player();
play.mmake(p);
FileWriter fileWriter = new FileWriter("wrrite,txt");
String life=p.getLife()+"";
String score=p.getScore()+"";
String str="生命值:"+life+"分数为:"+score;
fileWriter.write(str);
fileWriter.close();
System.out.println("1游戏结束!");
}
//进行游戏
public static void mmake(person p) {
player player1=new player();
int resust=player1.play();
if(resust==1){
int score=p.getScore()+1;
p.setScore(score);
System.out.println("回答正确,您的分数为"+score);
return;
}
if(resust==2){
int life=p.getLife();
life--;
p.setLife(life);
if(life>0){
System.out.println("回答错误!你的生命值为"+life);
mmake(p);
}else{
return;
}
}
if(resust==3){
int life=p.getLife();
life--;
p.setLife(life);
if(life>0){
System.out.println("时间到了,开始下一轮,你的生命值:"+life);
mmake(p);
}else{
return;
}
}
}
测试
心得体会
刚才开始使用定时器来记时,但无法在主线程中找到定时器提供的信息,最后使用System.currenttimemillist( )函数解决了问题。## 标题