Usuario:ManuelRomero/estados
De WikiEducator
EstadoCalculadora
- Es la clase que implementa la máquina de estados
- Lleva un atributo que representa el estado acutal de la calculadora
- Su método principal es el cambiaEstado con el que se comunica con la clase VentanaCalculadora
Código fuente
package calculadora; public class EstadoCalculadora { //Definir una constante para cada estado final int INICIAL =11; final int OP1 = 12; final int ESPERANDO_OP2=2; final int ESPERANDO_DEN_OP1 =7; final int DEN_OP1=9; final int DEN_OP2=10; final int ESPERANDO_DEN_OP2=8; final int OP1_DECIMAL=3; final int OP2_DECIMAL = 4; final int OP2 =5; final int RESULTADO =6; //Definimos las entradas con constantes final int NUMERO =100; final int OPERADOR_RACIONAL =101; final int OPERADOR_REAL =102; final int SEPARADOR_PUNTO =103; final int SEPARADOR_RACIONAL =104; final int IGUAL =105; final int MAS_MENOS =106; final int RETROCESO =107; final int CLEAR =108; //ConstanttipoCalculadoraes para evaluar modo de calculadora final int REAL = 0; final int RACIONAL = 1; //atributo estrelpr private int estado; private int tipo; //Para saber como interpretar las entradas //constructor EstadoCalculadora(){ estado=INICIAL; } public void setTipo(int tipo){ if (tipo == 0) this.tipo=REAL; else this.tipo = RACIONAL; } /** * doy un tipo de entrada (ver constantes predefinidas) * en función de caracter que representa el botón que el usuario a presionadp * @param c es el caracter que el usuario ha presionado de la calculadora * @return un entero en forma que constante que representa la entrada */ private int tipoEntrada(char c){ //Por defecto el valor de retorno doy clear por su hay una invocación errónea a la función //que sea clear lo que se devuelva int valor=CLEAR; if ((c >='0')&& (c<='9')) valor= NUMERO; if ((c=='/')&&(tipo==RACIONAL)) valor = SEPARADOR_RACIONAL; if (c=='.') valor = SEPARADOR_PUNTO; if (tipo==REAL){ switch (c){ case '+': case '-': case '*': case '/': case '%': valor = OPERADOR_REAL; } } if (tipo==RACIONAL){ switch (c){ case '+': case '-': case '*': case ':': valor = OPERADOR_RACIONAL; } } if (c=='=') valor = IGUAL; if (c=='C') valor = CLEAR; if (c==(char)8592) valor = RETROCESO; if (c==(char)177) valor = MAS_MENOS; return valor; } /* * La e es la entrada de la calculadora * el método cambia de estado */ private void inicializarEstado(AccionCalculadora accion){ estado=INICIAL; //accion.actualiza("0"); } public void actualizaEstado(Character entrada, String valorActual, AccionCalculadora accion, int tipo){ setTipo(tipo); System.out.println("accion estado actual: "+getEstado(estado) + " entrada "+entrada); if (tipoEntrada(entrada)==CLEAR){ estado=INICIAL; accion.limpiaPantalla();//inicializarEstado(accion); } else switch (estado){ case INICIAL: estado=inicial(entrada,valorActual,accion); break; case OP1 : estado = op1(entrada,valorActual,accion); break; case OP1_DECIMAL: estado =op1Decimal(entrada, valorActual,accion); break; case ESPERANDO_OP2: estado = esperandoOp2(entrada,valorActual,accion); break; case OP2: estado = op2(entrada,valorActual,accion); break; case OP2_DECIMAL: estado = op2Decimal(entrada,valorActual,accion); break; case RESULTADO: estado = resultado(entrada,valorActual,accion); break; case ESPERANDO_DEN_OP2: estado = esperandoDenOp2(entrada,valorActual,accion); break; case ESPERANDO_DEN_OP1: estado = esperandoDenOp1(entrada,valorActual,accion); break; case DEN_OP1: estado = denOp1(entrada,valorActual,accion); break; case DEN_OP2: estado = denOp2(entrada,valorActual,accion); break; }//End switch System.out.println("Estado siguiente "+ getEstado(estado)); System.out.println("==================================="); } private int inicial(Character entrada,String valorActual,AccionCalculadora accion){ int estado=this.estado; switch (tipoEntrada(entrada)){ case NUMERO : estado=OP1; accion.actualiza(valorActual+entrada); break; case SEPARADOR_PUNTO : estado=OP1_DECIMAL; accion.actualiza(valorActual+"0"+entrada); break; case SEPARADOR_RACIONAL : estado=ESPERANDO_DEN_OP1; accion.actualiza(valorActual+"0"+entrada); break; case MAS_MENOS : if (valorActual.indexOf('-')==-1) accion.actualiza("-"); else accion.limpiaPantalla(); break; case RETROCESO: accion.actualiza(""); } return estado; } private int op1(Character entrada ,String valorActual,AccionCalculadora accion){ int estado=this.estado; switch (tipoEntrada(entrada)){ case NUMERO : int num = Integer.parseInt(valorActual+entrada);//Para quitar posibles ceros a la izquierda accion.actualiza(""+num); break; case MAS_MENOS : accion.cambioSignoOp1(valorActual); break; case OPERADOR_RACIONAL : if (tipo==RACIONAL){ System.out.println("---"); estado=ESPERANDO_OP2; accion.actualiza(valorActual+"/1"+entrada); } break; case OPERADOR_REAL : if (tipo==REAL){ estado=ESPERANDO_OP2; accion.actualiza(valorActual+entrada); } break; case SEPARADOR_PUNTO : estado = OP1_DECIMAL; accion.actualiza(valorActual+entrada); break; case SEPARADOR_RACIONAL : estado = ESPERANDO_DEN_OP1; accion.actualiza(valorActual+entrada); break; case RETROCESO : int n= Integer.parseInt(valorActual); if ((n<-9) ||(n>9)) estado=OP1; else estado =INICIAL; accion.quitarCaracterOp1(valorActual); break; } return estado; } private int esperandoDenOp1(Character entrada, String valorActual, AccionCalculadora accion){ int estado = this.estado; switch (tipoEntrada(entrada)){ case NUMERO : accion.actualiza(valorActual+entrada); estado=DEN_OP1; break; case MAS_MENOS : accion.cambioSignoOp1(valorActual); break; case RETROCESO ://PLEASE SIMPLIFICA ESTO MRM int pos = valorActual.length(); if (valorActual.charAt(0)=='-'){ if (valorActual.charAt(pos-2)=='0'&pos==3){ //caso "-0/" ==> "-" estado = INICIAL; accion.actualiza("-"); } else{ estado = OP1; accion.quitarCaracterOp1(valorActual); } } else{ if (valorActual.charAt(pos-2)=='0'&pos==2){ //caso "0/" ==> "" estado = INICIAL; accion.actualiza(""); } else{ estado = OP1; accion.quitarCaracterOp1(valorActual); } } } return estado; } private int op1Decimal (Character entrada, String valorActual,AccionCalculadora accion){ int estado=this.estado; switch (tipoEntrada(entrada)){ case NUMERO : accion.actualiza(valorActual+entrada); break; case OPERADOR_REAL : estado = ESPERANDO_OP2; if (valorActual.charAt(valorActual.length()-1)=='.') accion.actualiza(valorActual+"0"+entrada); else{ float num = Float.parseFloat(valorActual);//Para evitar el caso 9.000000000000000+... accion.actualiza(""+num+entrada); } break; case MAS_MENOS : double n= Double.parseDouble(valorActual); accion.actualiza(Double.toString(-n)); break; case RETROCESO : int pos = valorActual.length(); if (valorActual.charAt(pos-1)=='.'){ if( Integer.parseInt(valorActual.substring(0,pos-1))==0) estado = INICIAL; else estado = OP1; } else estado = OP1_DECIMAL; accion.quitarCaracterOp1(valorActual); break; } return estado; } private int denOp1(Character entrada, String valorActual, AccionCalculadora accion){ int estado = this.estado; switch (tipoEntrada(entrada)){ case NUMERO : accion.actualiza(valorActual+entrada); break; case OPERADOR_RACIONAL : estado = ESPERANDO_OP2; accion.actualiza(valorActual+entrada); break; case MAS_MENOS : accion.cambioSignoOp1(valorActual); break; case RETROCESO : int pos = valorActual.length(); if (valorActual.charAt(pos-2)=='/') estado = ESPERANDO_DEN_OP1; accion.actualiza(valorActual.substring(0,pos-1)); break; } return estado; } private int esperandoOp2(Character entrada, String valorActual,AccionCalculadora accion){ int estado=this.estado; switch (tipoEntrada(entrada)){ case NUMERO : estado = OP2; accion.actualizarConPosibleParentesis(valorActual,Character.toString(entrada)); break; //Ante la entrada punto o / no he de ver si estoy en tipo REAL o RACIONAL ya que sólo existe //la entrada punto en tipo REAL :) case SEPARADOR_PUNTO : estado=OP2_DECIMAL; accion.actualizarConPosibleParentesis(valorActual,"0"+entrada); break; case SEPARADOR_RACIONAL : estado=ESPERANDO_DEN_OP2; accion.actualizarConPosibleParentesis(valorActual,"0"+entrada); break; case MAS_MENOS : if (valorActual.contains("(")) accion.actualiza(valorActual.substring(0,valorActual.indexOf('('))); else accion.actualiza(valorActual+"(-)"); break; case RETROCESO : int pos = valorActual.length(); String op1; if (valorActual.charAt(pos-1)==')'){ accion.quitarSignoOp2(valorActual); System.out.println("Esperando Op2 retroceso "+valorActual); } else{ op1=valorActual.substring(0,pos-1); accion.quitarCaracterOp1(valorActual); if (op1.indexOf('.')!=-1) estado = OP1_DECIMAL; else if (op1.indexOf('/')!=-1) estado = DEN_OP1; else estado =OP1; } break; } return estado; } private int op2(Character entrada, String valorActual,AccionCalculadora accion){ int estado=this.estado; switch (tipoEntrada(entrada)){ case NUMERO : accion.actualizarConPosibleParentesis(valorActual,""+entrada); break; case OPERADOR_RACIONAL : accion.calcula(valorActual,tipo); accion.addResultado(entrada); estado=ESPERANDO_OP2; break; case OPERADOR_REAL : accion.calcula(valorActual,tipo); accion.addResultado(entrada); estado=ESPERANDO_OP2; break; case SEPARADOR_PUNTO : accion.actualizarConPosibleParentesis(valorActual,""+entrada); estado=OP2_DECIMAL; break; case SEPARADOR_RACIONAL : accion.actualizarConPosibleParentesis(valorActual,""+entrada); estado=ESPERANDO_DEN_OP2; break; case IGUAL : estado= RESULTADO; accion.calcula(valorActual,tipo); break; case MAS_MENOS : accion.cambiarSignoOp2(valorActual,tipo); break; case RETROCESO : // 1 x/y op z ==> x/y op ESPERANDO_OP2 // 2 x/y op zv ==> x/y op z OP2 // 3 x/y op -(z) ==> x/y op -() ESPERANDO_OP2 // 4 x/y op -(zv) ==> x/y op -(z) OP2 // 5 x op y ==> x op ESPERANDO_OP2 // 6 x op yz ==> x op y OP2 // 7 x op -(y) ==> x op -() ESPERANDO_OP2 // 8 x op -(yz) ==> x op -(y) OP2 int c = accion.caracteresOp2(valorActual,tipo); if (c==0) estado = ESPERANDO_OP2; else estado = OP2; accion.quitarCaracterOp2(valorActual); } return estado; } private int op2Decimal(Character entrada, String valorActual,AccionCalculadora accion){ int estado = this.estado; switch (tipoEntrada(entrada)){ case NUMERO : accion.actualizaNumOp2Decimal(valorActual,entrada); break; case OPERADOR_REAL : estado=ESPERANDO_OP2; accion.calcula(valorActual,tipo); accion.actualiza(""+entrada); break; case IGUAL: estado = RESULTADO; accion.calcula(valorActual,tipo); accion.actualiza(""+entrada); case MAS_MENOS : accion.actualizaCambioSigno(valorActual); break; case RETROCESO : int pos = valorActual.length(); accion.actualiza(valorActual.substring(0,pos-1)); if (valorActual.charAt(pos-1)=='.') if (valorActual.charAt(pos-2)=='0'){ estado=ESPERANDO_OP2; accion.actualiza(valorActual.substring(0,pos-2)); } else estado = OP2; break; } return estado; } private int esperandoDenOp2(Character entrada, String valorActual, AccionCalculadora accion){ int estado = this.estado; switch (tipoEntrada(entrada)){ case NUMERO : estado = DEN_OP2; accion.actualiza(valorActual+entrada); break; case MAS_MENOS : accion.cambiarSignoOp2(valorActual,tipo); break; case IGUAL: if (valorActual.contains("(")) valorActual=valorActual.substring(0,valorActual.length()-2)+"1)"; else valorActual=valorActual+"1"; accion.calcula(valorActual, tipo); estado = RESULTADO; break; case OPERADOR_RACIONAL: if (valorActual.contains("(")) valorActual=valorActual.substring(0,valorActual.length()-2)+"1)"; else valorActual=valorActual+"1"; accion.calcula(valorActual, tipo); accion.addResultado(entrada); estado=ESPERANDO_OP2; break; case RETROCESO ://MRM Me quede aquà // 1 a/b op c/ ==> a/b op c OP2 // 2 a/b op 0/ ==> a/b op ESPERANDO_OP2 // 3 a/b op (-c/) ==> a/b op (-c) OP2 // 4 a/b op (-0/) ==> a/b op ESPERANDO_OP2 int c = accion.caracteresOp2(valorActual,tipo); if (c==1) estado = ESPERANDO_OP2; else estado = OP2; accion.quitarCaracterOp2(valorActual); break; }//End case return estado; } private int denOp2(Character entrada, String valorActual, AccionCalculadora accion){ int estado = this.estado; switch (tipoEntrada(entrada)){ case NUMERO : accion.actualizarConPosibleParentesis(valorActual,""+entrada); break; case OPERADOR_RACIONAL : estado=ESPERANDO_OP2; accion.calcula(valorActual,tipo); accion.actualiza(""+entrada); break; case IGUAL: estado=RESULTADO; accion.calcula(valorActual,tipo); break; case MAS_MENOS : accion.actualizaCambioSigno(valorActual); break; case RETROCESO : // 1 a/b op c/d ==> a/b op c/ ESPERANDO_DEN_OP2 // 2 a/b op c/de ==> a/b op c/d DEN OP2 // 3 a/b op -(c/d) ==> a/b op -(c/) ESPERANDO_DEN_OP2 // 4 a/b op -(c/de) ==> a/b op -(c/d) DEN_OP2 int c = accion.caracteresOp2(valorActual,tipo); if (c==0) estado = ESPERANDO_OP2; else estado = OP2; accion.actulizaRetrocesoConPosibleParentesis(valorActual); } return estado; } private int resultado(Character entrada, String valorActual, AccionCalculadora accion){ int estado = this.estado; switch (tipoEntrada(entrada)){ case NUMERO : estado=OP1; accion.actualiza(""+entrada); break; case OPERADOR_RACIONAL : case OPERADOR_REAL : estado=ESPERANDO_OP2; accion.addResultado(entrada); break; case MAS_MENOS : estado = OP1; accion.cambiaSignoResultado(); break; case CLEAR : } return estado; } public void inicializa(AccionCalculadora accion){ estado=INICIAL; accion.actualiza(""); } public int getEstado(){ return estado; } private String getEstado(int estado){ switch (estado){ case INICIAL: return "INICIAL"; case OP1 : return "OPERANDO 1"; case OP1_DECIMAL: return "OP1_DECIMAL"; case ESPERANDO_OP2 : return "ESPERANDO_OP2"; case OP2 : return "OP2"; case OP2_DECIMAL : return "OP2_DECIMAL"; case RESULTADO : return "RSULTADO"; case ESPERANDO_DEN_OP1: return "ESPERANDO_DEN_OP1"; case ESPERANDO_DEN_OP2: return "ESPERANDO_DEN_OP2"; case DEN_OP1: return "DEN_OP1"; case DEN_OP2: return "DEN_OP2"; default: return("SIN ESTADO!!!!"); } } /** * Me verifica si un número es negativo * Paso solamente el número a verificar como un string * @return true si el número es negativo falso en otro caso */ }//eND CLASE