Avaliar código

4 respostas
programaçãojava
M

Eai galera, sou um iniciante em programação e gostaria de saber se o código que eu programei poderia ser refinado de alguma forma, tanto no código em si, como em organização dos métodos e etc. Gostaria de deixa-lo na forma mais prática possível

O exercício pedia para eu criar um código que dada a entrada de uma dificuldade (sendo 1 números de apenas 1 digito, 2 dois dígitos e assim por diante) e uma entrada de uma operação aritmética (+,-,*,/) o programa fazia 10 perguntas com as especificações escolhidas, caso a resposta estivesse certa ele randomizava uma resposta positiva, caso não randomizava uma resposta negativa. Basicamente é isso, obrigado desde já.

public class InstrAux {

private int contador = 0;

private int acerto = 0;

private int dificuldade;

private char temp;

private double correto;

private double resposta;

Scanner input = new Scanner(System.in);
Random r = new Random();

public void lerProblema() {

System.out.println(Digite o nível de dificuldade:);

dificuldade = input.nextInt();

System.out.println(Escolha sua operação [+ - * /] ou [=] para fazer uma equação:);

temp = input.next().charAt(0);

gerarNumeros();

}

public void gerarNumeros() {

if (contador == 10) {

avaliarNota();

}

int n1 = r.nextInt((int) Math.pow(10, dificuldade) - (int) Math.pow(10, dificuldade - 1) + 1)

+ (int) Math.pow(10, dificuldade - 1) - 1;

int n2 = r.nextInt((int) Math.pow(10, dificuldade) - (int) Math.pow(10, dificuldade - 1) + 1)

+ (int) Math.pow(10, dificuldade - 1) - 1;

lerNumeros(n1, n2);

}

public void lerNumeros(int n1, int n2) {

if (temp == '=') {
  	System.out.printf("Quanto é (2 * %d) + (3 - %d) * (%d * %d)\n", n1, n2, n1, n2);
  	resposta = input.nextInt();
  	compararNumeros(n1, n2, resposta);
  } else {
  	if (temp == '/' && n2 == 0) {
  		n2++;
  		System.out.println("Quanto é " + n1 + temp + n2 + " (Apenas use 2 casas decimais)");
  		resposta = input.nextDouble();
  		compararNumeros(n1, n2, resposta);
  	} else {
  		System.out.println("Quanto é " + n1 + temp + n2 + " (Apenas use 2 casas decimais)");
  		resposta = input.nextDouble();
  		compararNumeros(n1, n2, resposta);
  	}
  }

}

public void compararNumeros(int n1, int n2, double resposta) {

String[] answer = new String[8];
  answer[0] = "Very good!";
  answer[1] = "Excellent!";
  answer[2] = "Nice work!";
  answer[3] = "Keep up the good work!";
  answer[4] = "No. Please try again";
  answer[5] = "Wrong. Try once more";
  answer[6] = "Don't give up";
  answer[7] = "No. Keep trying";
  switch (temp) {
case '+':
  	correto = n1 + n2;
  	break;
  case '-':
  	correto = n1 - n2;
  	break;
  case '*':
  	correto = n1 * n2;
  	break;
  case '/':
  	BigDecimal big1 = new BigDecimal(n1);
  	BigDecimal big2 = new BigDecimal(n2);
  	BigDecimal oi = big1.divide(big2, 2, RoundingMode.HALF_UP);
  	String aha = oi.toString();
  	correto = Double.parseDouble(aha);
  	break;
  case '=':
  	correto = (int) (2 * n1) + (3 - n2) * (n1 * n2);
  	break;
}
  if (correto == resposta) {
  	System.out.println(answer[r.nextInt(4)]);
  	acerto++;
  	contador++;
  	gerarNumeros();
  } else {
  	contador++;
  	System.out.println(answer[r.nextInt(4) + 4]);
  	gerarNumeros();
  }

}

public void avaliarNota() {

if (acerto > 7) {
  	System.out.println("Parabéns você teve um aproveitamento de: " + (acerto * 10)
  			+ "% \nVocê está pronto para avançar para o próximo nível!");
} else {
  	System.out
  			.println("Você teve um aproveitamento de: " + (acerto * 10) + "%\nPeça ajuda para o seu professor");
}
  acerto = 0;
  contador = 0;
  lerProblema();

}

}

Exemplo de saída:

Digite o nível de dificuldade:
1
Escolha sua operação [+ - * /] ou [=] para fazer uma equação:
/
Quanto é 3/1 (Apenas use 2 casas decimais)
3
Very good!
Quanto é 2/6 (Apenas use 2 casas decimais)
0,33
Excellent!
Quanto é 7/8 (Apenas use 2 casas decimais)
0,88
Nice work!
Quanto é 8/7 (Apenas use 2 casas decimais)
1,14
Nice work!
Quanto é 5/7 (Apenas use 2 casas decimais)
0,71
Nice work!
Quanto é 6/3 (Apenas use 2 casas decimais)
2
Nice work!
Quanto é 0/1 (Apenas use 2 casas decimais)
0
Excellent!
Quanto é 5/1 (Apenas use 2 casas decimais)
5
Keep up the good work!
Quanto é 9/1 (Apenas use 2 casas decimais)
9
Excellent!
Quanto é 7/6 (Apenas use 2 casas decimais)
1,17
Keep up the good work!
Parabéns você teve um aproveitamento de: 100% 
Você está pronto para avançar para o próximo nível!
Digite o nível de dificuldade:

4 Respostas

A

Oi @Ms1403,

Para quem está iniciando, ficou bom o resultado final e legal você querer se aprimorar.

O primeiro aspecto que pode ser melhorado é o fluxo do programa.
Geralmente você quer ter uma idéia clara de onde as coisas começam e terminam, mas no seu código esse fluxo está misturado com as outras partes.
Mapeando a sequencia de chamadas do seu código:

lerProblemas -> gerarNumeros -> lerNumeros -> compararNumeros -> gerarNumeros
                             -> avaliarNota -> lerProblema

Para quem lê seu código fica dificil saber como as coisas acontecem.
Para esse tipo de programa, pode valer mais a pena ter uma funçao que define esse fluxo e vai chamando outras mais específicas para realizar cada tarefa.

Isso nos leva ao segundo ponto. É legal você ter criado funçoes, mas é melhor deixar elas mais específicas. Se você remover a chamada de uma para outra, por exemplo, já ficariam bem mais apropriadas.

Um terceiro ponto é evitar ter aquelas variaveis no topo da classe sendo usadas por diferentes funçoes. Uma maneira melhor de fazer isso é você retornar valores das suas funçoes (repare que todos seus métodos sao void) e passar valores como parâmetro, ao invés de usar da classe. Do jeito que está usando, suas variáveis tem os mesmos problemas de variáveis globais.

Por último, mas nao menos importante, é sempre tentar deixar o código simples de entender. E para isso, você tem que abrir mao de truques espertos.
Por exemplo: ao invés de ter um simples array para respostas corretas e erradas, e usar aquele +4 para selecionar as erradas, é mais simples e fácil de entender se você criar um array específico pra cada tipo de respostas.
Isso é um hábito que muitos programadores tem e mesmo pessoas experientes caem na armadilha de fazer um código esperto ao invés de um código legível.

Enfim, parabéns por ter feito o que fez e se precisar de ajuda para evoluir em algum dos comentários acima, é só avisar.

M

Muito obrigado pela resposta, fiquei surpreso até, não esperava uma resposta tão detalhada hahahaha. Muito obrigado mesmo pela ajuda, vou tentar refinar o código da maneira que você disse e qualquer coisa eu volto a postar aqui.

Obrigado pelo incentivo!

M

Eu dei uma refinada no código só n entendi muito bem como fazer essa parte aqui:

Se puder me ajudar mais um pouco ficarei muito agradecido.

Ps: Eu mudei o caractere usado para a opção de fazer uma equação, pois entendi errado o exercício, nessa opção o problema quer que as 10 perguntas matemática sejam randômicas, ou seja, pode vir qualquer operação para resolver.

O código está assim no momento:

package instrAux;

import java.math.BigDecimal;

import java.math.RoundingMode;

import java.util.Random;

import java.util.Scanner;

public class InstrAux {

private int acerto = 0;

private int dificuldade;

private char temp;

private double correto;

private double resposta;

private String[] answerPositive = new String[4];

private String[] answerNegative = new String[4];

private boolean x;
public InstrAux(String[] answerPositive, String[] answerNegative) {

super();

this.answerPositive = answerPositive;

this.answerNegative = answerNegative;

}

Scanner input = new Scanner(System.in);
Random r = new Random();

public void lerInput() {

System.out.println(Digite o nível de dificuldade:);

dificuldade = input.nextInt();

System.out.println(Escolha sua operação [+ - * /] ou [~] para fazer uma equação:);

temp = input.next().charAt(0);

if (temp == ~) {

x = true;
}

}

public void gerarNumeros() {

int n1 = r.nextInt((int) Math.pow(10, dificuldade) - (int) Math.pow(10, dificuldade - 1) + 1)
  		+ (int) Math.pow(10, dificuldade - 1) - 1;
  int n2 = r.nextInt((int) Math.pow(10, dificuldade) - (int) Math.pow(10, dificuldade - 1) + 1)
  		+ (int) Math.pow(10, dificuldade - 1) - 1;
  compararNumeros(n1, n2);

}

public void compararNumeros(int n1, int n2) {

if (x) {
  	String oi = "+-*/";
  	temp = oi.charAt(r.nextInt(oi.length()));
  }
  switch (temp) {
case '+':
  	System.out.println("Quanto é " + n1 + temp + n2);
  	resposta = input.nextInt();
  	correto = n1 + n2;
  	break;
  case '-':
  	System.out.println("Quanto é " + n1 + temp + n2);
  	resposta = input.nextInt();
  	correto = n1 - n2;
  	break;
  case '*':
  	System.out.println("Quanto é " + n1 + temp + n2);
  	resposta = input.nextInt();
  	correto = n1 * n2;
  	break;
  case '/':
  	if (n2 == 0) {
  		n2++;
  	}
  	System.out.println("Quanto é " + n1 + temp + n2);
  	resposta = input.nextDouble();
  	BigDecimal number1 = new BigDecimal(n1);
  	BigDecimal number2 = new BigDecimal(n2);
  	BigDecimal result = number1.divide(number2, 2, RoundingMode.HALF_UP);
  	String resultTransform = result.toString();
  	correto = Double.parseDouble(resultTransform);
  	break;
  }
if (correto == resposta) {
  	System.out.println(answerPositive[r.nextInt(4)]);
  	acerto++;
} else {
  	System.out.println(answerNegative[r.nextInt(4)]);
  	
  }

}

public void avaliarNota() {

if (acerto > 7) {
  	System.out.println("\nParabéns você teve um aproveitamento de: " + (acerto * 10)
  			+ "% \nVocê está pronto para avançar para o próximo nível!\n");
} else {
  	System.out
  			.println("\nVocê teve um aproveitamento de: " + (acerto * 10) + "%\nPeça ajuda para o seu professor\n");
}
  acerto = 0;

}
}

Classe Main:

package instrAux;

public class Main {

public static void main(String[] args) {

String[] answerPositive = new String[4];
  answerPositive[0] = "Very good!";
  answerPositive[1] = "Excellent!";
  answerPositive[2] = "Nice work!";
  answerPositive[3] = "Keep up the good work!";
  
  String[] answerNegative = new String[4];
  answerNegative[0] = "No. Please try again";
  answerNegative[1] = "Wrong. Try once more";
  answerNegative[2] = "Don't give up";
  answerNegative[3] = "No. Keep trying";
  
  InstrAux ia = new InstrAux(answerPositive,answerNegative);
  while (true) {
ia.lerInput();
  	for (int i = 0; i < 10; i++) {
  		ia.gerarNumeros();
  	}
  	ia.avaliarNota();
  }

}
}

A

Desculpe a demora para responder.

Eu estava sugerindo algo no estilo:

InstrAux ia = new InstrAux(answerPositive,answerNegative);
	while (true) {

        Parametros parametros = ia.lerInput();
        int acertos = 0;
		for (int i = 0; i &lt; 10; i++) {
		  if (ia.gerarNumeros(parametros)) {
                acertos += 1;
		  };
		}
		ia.avaliarNota(acertos);
	}

Repare que, ao invés de lerInput mudar os atributos dificuldade e operacao na classe InstrAux, a funçao agora retorna quais sao os parametros escolhidos.
O método gerarNumeros recebe esses parâmetros e retorna se o usuário acertou a pergunta a partir daquilo.
Com isso você pode remover da classe InstrAux os atributos contador, acerto e dificuldade.
Em geral, quanto menos atributos você tem numa classe, mais fácil é entender o que ela faz.

Uma última dica, já que você nao modifica o valor das respostas, você nao precisa passar no construtor de InstrAux. Poderia definir esses valores dentro da classe assim:

private String[] answerPositive = {"Very good!", "Excellent!", "Nice work!", "Keep up the good work!"};
private String[] answerNegative = {"No. Please try again", "Wrong. Try once more", "Don't give up", "No. Keep trying"};
Criado 6 de abril de 2017
Ultima resposta 11 de abr. de 2017
Respostas 4
Participantes 2