我编写了几个函数,这些函数采用格式化的字符串,定义骰子的数量和骰子的大小,将它们抛出并添加它们的值。 例如: 3d8 意味着扔3个骰子,每个骰子8个边,并添加它们的值。值始终为正,因此每次我为 3d8 运行此功能时,我都可以得到3到24之间的值。
public int calcDice(String diceFormula){
String[] divided = diceFormula.split("d");
int cant = Integer.parseInt(divided[0]);
int dice = Integer.parseInt(divided[1]);
int result = 0;
for (int i = 0; i < cant; i++) {
result += throwDice(dice);
}
return result;
}
private int throwDice(int diceSize) {
diceSize = diceSize < 0 ? dice * -1 : diceSize;
Random r = new Random();
return r.nextInt((diceSize - 1) + 1) + 1;
}
我现在需要的是能够使用这些值制作数学函数,因此我可以输入将要计算的数学函数。我需要遵守解决顺序 例如。 (((3d8)+1)x(2d4)x 3
其中一个想法是获取字符串并首先处理值,然后替换javascript评估程序以找出结果,但是我不确定如何“选择”值。 (也许是正则表达式?)
答案 0 :(得分:0)
我要做的是实现一个ShuntingYard
函数,该函数能够解析数学表达式
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ShuttingYard {
private final Map<String, Integer> operators = new HashMap<>();
public ShuttingYard(){
operators.put("-", 0);
operators.put("+", 0);
operators.put("/", 1);
operators.put("*", 1);
operators.put("^", 2);
}
public double doTheShuntingYard(String expression)throws IllegalArgumentException, NumberFormatException, ArithmeticException{
if(expression == null || expression.trim().length() == 0)
throw new IllegalArgumentException("Empty expression or null");
expression = expression.replaceAll("\\s+","");
expression = expression.replace("(-", "(0-");
if (expression.startsWith("-")){
expression = "0" + expression;
}
Pattern pattern = Pattern.compile("((([0-9]*[.])?[0-9]+)|([\\+\\-\\*\\/\\(\\)\\^]))");
Matcher matcher = pattern.matcher(expression);
int counter = 0;
List<String> tokens = new ArrayList<>();
while(matcher.find()){
if(matcher.start() != counter){
throw new IllegalArgumentException("Invalid Expression:" + expression + ". Error between " + counter+ " end " + matcher.start());
}
tokens.add(matcher.group().trim());
counter += tokens.get(tokens.size() - 1 ).length();
}
if(counter != expression.length()){
throw new IllegalArgumentException("Invalid end of expression");
}
Stack<String> stack = new Stack<>();
List<String> output = new ArrayList<>();
for(String token : tokens){
if(operators.containsKey(token)){
while(!stack.empty() &&
operators.containsKey(stack.peek())&&
((operators.get(token) <= operators.get(stack.peek()) && !token.equals("^"))||
(operators.get(token) < operators.get(stack.peek()) && token.equals("^")))){
output.add(stack.pop());
}
stack.push(token);
}
else if(token.equals("(")){
stack.push(token);
}
else if(token.equals(")")){
while(!stack.empty()){
if(!stack.peek().equals("(")){
output.add(stack.pop());
}
else{
break;
}
}
if(!stack.empty()){
stack.pop();
}
}
else{
output.add(token);
}
}
while(!stack.empty()){
output.add(stack.pop());
}
Stack<Double> doubles = new Stack<>();
for(String token : output){
if(!operators.containsKey(token) && token.matches("([0-9]*[.])?[0-9]+")){
try{
doubles.push(Double.parseDouble(token));
}
catch(NumberFormatException n){
throw n;
}
}
else{
if(doubles.size() > 1){
double op1 = doubles.pop();
double op2 = doubles.pop();
switch (token) {
case "+":
doubles.push(op2 + op1);
break;
case "-":
doubles.push(op2 - op1);
break;
case "*":
doubles.push(op2 * op1);
break;
case "/":
if(op1 == 0){
throw new ArithmeticException("Division by 0");
}
doubles.push(Math.floor(op2 / op1));
break;
case "^":
doubles.push(Math.pow(op2, op1));
break;
default:
throw new IllegalArgumentException(token + " is not an operator or is not handled");
}
}
}
}
if(doubles.empty() || doubles.size() > 1){
throw new IllegalArgumentException("Invalid expression, could not find a result. An operator seems to be absent");
}
return doubles.peek();
}
}
然后,我将在解决throwDice
操作之后调用此函数
public class DiceThrower{
private ShuttingYard shuttingYard;
public DiceThrower(){
this.shuttingYard = new ShuttingYard();
}
public void throwDiceAction(View view){
TextView result = findViewById(R.id.diceResult);
try{
String original = ((EditText)findViewById(R.id.formula)).getText().toString();
Pattern pattern = Pattern.compile("([0-9]{1,999})d([0-9]{1,999})");
Matcher matcher = pattern.matcher(original);
while(matcher.find()){
original = matcher.replaceFirst(Integer.toString(calcDice(matcher.group(0))));
matcher = pattern.matcher(original);
}
result.setText(evaluateExpression(original).split("\\.")[0]);
}catch(ArithmeticException e){
result.setText("This doesn't seem to be a valid mathematical expression");
}
}
public String evaluateExpression(String expression){
expression = expression.replaceAll("\\)\\(", ")*(");
expression = expression.replaceAll("x", "*");
return Double.toString(this.shuttingYard.doTheShuntingYard(expression));
}
public int calcDice(String formula){
String[] divided = formula.split("d");
int cant = Integer.parseInt(divided[0]);
int dice = Integer.parseInt(divided[1]);
int result = 0;
for (int i = 0; i < cant; i++) {
result += throwDice(dice);
}
return result;
}
private int throwDice(int dice) {
dice = dice < 0 ? dice * -1 : dice;
Random r = new Random();
return r.nextInt((dice - 1) + 1) + 1;
}
}