Monty Hall Paradox en Java -- java campo con random campo con simulation camp codereview Relacionados El problema

Monty Hall Paradox in Java


14
vote

problema

Español

Me preguntaba si este código se ve limpio, y si debería cambiar algo. Estaba planeando implementar marcos (o minus3 ) mañana en él. ¿Sería una buena idea usar las funciones?

  minus4  
Original en ingles

I was wondering if this code looks neat, and if I should change anything. I was planning to implement Frames (or JFrame) tomorrow on it. Would it be a good idea to use functions?

import java.lang.Math.*; import java.util.Random; import java.util.Scanner;  public class Paradox { public static void main(String[] args){     System.out.println("\n\nYou have got three doors, there is a price inside each of them. Pick a door: A, B, or C.");     Door A = new Door();     Door B = new Door();     Door C = new Door();     A.open=0;     B.open=0;     C.open=0;      Random rand = new Random();     int i = rand.nextInt(3);     /*System.out.println(i);*/      if(i==0) {         A.goatorcar="Car";         B.goatorcar="Goat";         C.goatorcar="Goat";     }     else if (i==1){         A.goatorcar="Goat";         B.goatorcar="Car";         C.goatorcar="Goat";     }     else if (i==2) {         A.goatorcar="Goat";         B.goatorcar="Goat";         C.goatorcar="Car";     } else { System.out.println("Unexpected error"); }        int pickedA=0;     int pickedB=0;     int pickedC=0;      Scanner sc = new Scanner(System.in);     String pickedDoor = sc.nextLine();     System.out.println("\n");      if (pickedDoor.equals("A") || pickedDoor.equals("1") || pickedDoor.equals("a")){         pickedA = 1;     }     if (pickedDoor.equals("B") || pickedDoor.equals("2") || pickedDoor.equals("b")){         pickedB = 1;     }     if (pickedDoor.equals("C") || pickedDoor.equals("3") || pickedDoor.equals("c")){         pickedC = 1;     }      if(pickedA==1) {         if (A.goatorcar.equals("Car")){             i = rand.nextInt(2);             if (i==0){ System.out.println("The door B contains a Goat"); B.open=1; }             else if (i==1){ System.out.println("The door C contains a Goat"); C.open=1; }         }         else {         if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; }         else if (C.goatorcar=="Goat") { System.out.println("The door C contains a Goat"); C.open=1; }         }     }     else if (pickedB==1) {         if (B.goatorcar.equals("Car")){             i = rand.nextInt(2);             if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; }             else if (i==1){ System.out.println("The door C contains a Goat"); C.open=1; }         }         else {             if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; }             else if (C.goatorcar=="Goat") { System.out.println("The door C contains a Goat"); C.open=1; }         }     }     else if (pickedC==1) {         if (C.goatorcar.equals("Car")){             i = rand.nextInt(2);             if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; }             else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; }         }         else {             if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; }             else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; }         }     }     else { System.out.println("You haven't picked any door"); System.exit(0); }       System.out.println("\nKnowing where one of the Goats are, do you wish to stay on your current door, or do you want to change?");      String changeornot = sc.nextLine();     int change=2;     System.out.println();      if (changeornot.equals("change") || changeornot.equals("1") || changeornot.equals("yes")){         change=1;     }     else if (changeornot.equals("stay") || changeornot.equals("0") || changeornot.equals("no")){         change=0;     }       if(change==0){         System.out.print("Congratulations! You stayed, and won a ");         if(pickedA==1){             System.out.println(A.goatorcar);         }         if(pickedB==1){             System.out.println(B.goatorcar);         }         if (pickedC==1){             System.out.println(C.goatorcar);         }     }      else if (change==1){         System.out.print("Congratulations! You changed, and won a ");         if (pickedA==1 && B.open==1) {             System.out.println(C.goatorcar);         }         if (pickedA==1 && C.open==1) {             System.out.println(B.goatorcar);         }          if (pickedB==1 && A.open==1) {             System.out.println(C.goatorcar);         }         if (pickedB==1 && C.open==1) {             System.out.println(A.goatorcar);         }          if (pickedC==1 && A.open==1) {             System.out.println(B.goatorcar);         }         if (pickedC==1 && B.open==1) {             System.out.println(A.goatorcar);         }        }     else if (change==2){ System.out.println("Error at change"); }   /*System.out.println("Door A: " + A.goatorcar); System.out.println("Door B: " + B.goatorcar); System.out.println("Door C: " + C.goatorcar);*/  } } class Door { String goatorcar; int open; }  
        
     
     

Lista de respuestas

10
 
vote

algunos pensamientos:

  • Algunas de tus líneas son muy largas. Si bien puede parecer conveniente que encajen en su pantalla, el código se vuelve más difícil de entender, ya que las líneas se vuelven más largas. Muchas personas tienen buenas razones para desear un ochenta vía límite de línea. Esta es mi preferencia personal; y muchas personas no estarán en desacuerdo; pero me parece

      System.out.println(INTRODUCTION);   

    más amable que

      System.out.println("  You have got three doors, there is a price inside each of them. Pick a door: A, B, or C.");   

    ... principalmente porque entonces no necesito dedicar gran parte de mis propiedades inmobiliarias a un solo archivo. Si estoy trabajando en varios archivos en múltiples ventanas a la vez, o si estoy usando un Linux TTY, las líneas largas se convierten en un dolor si necesito desplazarse en cuatro direcciones en lugar de dos. Según lo señalado por los lectores astutos, esta práctica es además arcaica. En estos días, puede escapar fácilmente con líneas de más de 80 caracteres.

  • La escritura de código modular es un paso esencial para garantizar que su código no sea un truco. Un truco es básicamente el código que no le da libremente a la modificación. Cuando el código se divide en métodos, se vuelve más fácil de entender, modificar y depurar. Por ejemplo, si tiene un método 99887766555544337755544337 99887776665544338 , simplemente puede llamar a ese método siempre que desee que el usuario escoja una puerta . El método puede hacer la tarea de

      if (pickedDoor.toLowerCase().equals("a") || pickedDoor.equals("1"))   

    en un solo lugar. También puede salirse con la alejamiento del resultado de ese método; De esa manera, puede referirse a los resultados por nombre: int sum = sum(input); 0 int sum = sum(input); 1 , et Cetera. Escribir código modular puede ser un poco desalentador; Pero las recompensas son bastante deseables. El código modular es el código que se divide en módulos; Cada módulo hace una tarea específica. Según Wikipedia,

    La programación modular es una técnica de diseño de software que enfatiza la separación de la funcionalidad de un programa en módulos independientes e intercambiables, de modo que cada uno contiene todo lo necesario para ejecutar solo un aspecto de la funcionalidad deseada.

  • Tiene muchas cadenas codificadas por duras. Según Google:

    [Codificación dura es para] Solucionar (datos o parámetros) en un programa de tal manera que no se pueden modificar sin modificar el programa.

    Probablemente puede salirse con los campos int sum = sum(input); 2 Algo como

      int sum = sum(input); 3  

    int sum = sum(input); 4 significa que la variable no se puede modificar después de la asignación.

  • Miraría para hacer que su código sea más mantenido antes de hacer una GUI. El proceso no debería estar demasiado involucrado. Por lo general, trato de mantener todos los métodos GUI en una clase separada.

 

A few thoughts:

  • Some of your lines are very long. While it may seem convenient that they fit on your screen, code gets more difficult to understand as lines become longer. Many people have good reasons to desire an eighty char line limit. This is my personal preference; and many people will disagree; but i find

    System.out.println(INTRODUCTION); 

    more amiable than

    System.out.println("\n\nYou have got three doors, there is a price inside each of them. Pick a door: A, B, or C."); 

    ... mainly because then I don't need to devote much of my screen real estate to a single file. If I am working on multiple files in multiple windows at once, or if I am using a Linux TTY, long lines become a pain if I need to scroll in four directions instead of two. As pointed out by astute readers, this practice is moreover archaic. These days, you can easily get away with lines longer than 80 characters.

  • Writing modular code is an essential step towards ensuring your code isn't a hack. A hack is basically code that doesn't give freely to modification. When code is split up into methods, it becomes easier to understand, modify, and debug. For example, if you have instead a doorOption method that determines what door was chosen based on a String, you can simply call that method whenever you want the user to pick a door. The method can do the task of

    if (pickedDoor.toLowerCase().equals("a") || pickedDoor.equals("1")) 

    in one place. You can also probably get away with enumerating the result of that method; that way you can refer to the results by name: DOOR_ONE DOOR_TWO, et cetera. Writing modular code can be a little daunting; but the rewards are quite desirable. Modular code is code that is divided into modules; each module does a specific task. According to Wikipedia,

    Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.

  • You have a lot of hard-coded strings. According to Google:

    [Hard coding is to] fix (data or parameters) in a program in such a way that they cannot be altered without modifying the program.

    You can probably get away with making those into static final fields. Something like

    static final String INTRODUCTION = "\n\nYou have got three doors, there is a price inside each of them. Pick a door: A, B, or C."; 

    final means the variable can not be modified after assignment.

  • I would look into making your code more maintainable before making a GUI. The process shouldn't be overly involved. I usually try to keep all the GUI methods in a separate class.

 
 
         
         
8
 
vote

One-Liners

Este no es un punto enorme, pero noté que tienes varios solteros que tienen múltiples comandos en ellos. Aunque eso no es técnicamente "incorrecto" podría llevar a cierta confusión para la siguiente persona que puede tener que mantener su código.

Por ejemplo:

  else if (pickedC==1) {     if (C.goatorcar.equals("Car")){         i = rand.nextInt(2);         if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; }         else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; }     }     else {         if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; }         else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; }     } } else { System.out.println("You haven't picked any door"); System.exit(0); }   

Algo como este formato indicaría más fácilmente que está más sucediendo que la impresión a la consola.

  else if (pickedC==1) {     if (C.goatorcar.equals("Car")){         i = rand.nextInt(2);         if (i==0){ System.out.println("The door A contains a Goat");              A.open=1; }         else if (i==1){ System.out.println("The door B contains a Goat");              B.open=1; }     }     else {         if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat");              A.open=1; }         else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat");              B.open=1; }     } } else { System.out.println("You haven't picked any door");      System.exit(0); }   

Idealmente, muchos, muchos podrían decir que deberías seguir la sangría estándar de Java en todo caso, a pesar de que se necesita más espacio vertical, hace que las cosas sean perfectamente claras, como esta:

  else if (pickedC==1) {     if (C.goatorcar.equals("Car")) {         i = rand.nextInt(2);         if (i==0) {              System.out.println("The door A contains a Goat");              A.open=1;          }         else if (i==1) {              System.out.println("The door B contains a Goat");              B.open=1;          }     }     else {         if (A.goatorcar=="Goat") {              System.out.println("The door A contains a Goat");              A.open=1;          }         else if (B.goatorcar=="Goat") {              System.out.println("The door B contains a Goat");              B.open=1;          }     } } else {      System.out.println("You haven't picked any door");      System.exit(0);  }   

Nombramiento y espaciado

algo como esto:

  if(i==0) {     A.goatorcar="Car";     B.goatorcar="Goat";     C.goatorcar="Goat"; }   

Por uno, el nombramiento de variables como ese sería más fácil de seguir si usó camelcase, que es la convención para variables y métodos de varias palabras. Por lo que goatorcar se vuelve más fácil de leer, goatOrCar .

También un poco de sala de respiración entre los operadores se vería mejor. Me gusta esto:

  if(i == 0) {     A.goatOrCar = "Car";     B.goatOrCar = "Goat";     C.goatOrCar = "Goat"; }   
 

One-liners

This is not a huge point, but I noticed you have several one-liners which have multiple commands in them. Even though that's not technically "wrong" it could lead to some confusion for the next person who may have to maintain your code.

For example:

else if (pickedC==1) {     if (C.goatorcar.equals("Car")){         i = rand.nextInt(2);         if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; }         else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; }     }     else {         if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; }         else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; }     } } else { System.out.println("You haven't picked any door"); System.exit(0); } 

Something like this formatting would more easily indicate there's more going on than printing to console.

else if (pickedC==1) {     if (C.goatorcar.equals("Car")){         i = rand.nextInt(2);         if (i==0){ System.out.println("The door A contains a Goat");              A.open=1; }         else if (i==1){ System.out.println("The door B contains a Goat");              B.open=1; }     }     else {         if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat");              A.open=1; }         else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat");              B.open=1; }     } } else { System.out.println("You haven't picked any door");      System.exit(0); } 

Ideally though, many could say you should just follow the standard Java indentation throughout, even though it takes more vertical room it makes things perfectly clear, like this:

else if (pickedC==1) {     if (C.goatorcar.equals("Car")) {         i = rand.nextInt(2);         if (i==0) {              System.out.println("The door A contains a Goat");              A.open=1;          }         else if (i==1) {              System.out.println("The door B contains a Goat");              B.open=1;          }     }     else {         if (A.goatorcar=="Goat") {              System.out.println("The door A contains a Goat");              A.open=1;          }         else if (B.goatorcar=="Goat") {              System.out.println("The door B contains a Goat");              B.open=1;          }     } } else {      System.out.println("You haven't picked any door");      System.exit(0);  } 

Naming and spacing

Something like this:

if(i==0) {     A.goatorcar="Car";     B.goatorcar="Goat";     C.goatorcar="Goat"; } 

For one, the naming for variables like that would be easier to follow if you used camelCase, which is the convention for multi-word variables and methods. So goatorcar becomes more easily readable, goatOrCar.

Also a little bit of breathing room between operators would look better. Like this:

if(i == 0) {     A.goatOrCar = "Car";     B.goatOrCar = "Goat";     C.goatOrCar = "Goat"; } 
 
 
   
   
6
 
vote

Si definitivamente ayudaría si tuviera una función para obtener la entrada de usuario: tendrías un mejor separación de preocupaciones , el comportamiento sería más fácil de cambiar y la interfaz de usuario sería ligeramente más intuitiva y fácil de usar.

Mi Java es un poco oxidado, pero algo así como (el siguiente código no es correcto, lo que importa es la idea más que el código en sí):

  public static boolean getBooleanFromUser(String prompt, String retry, List<String> yesOptions, List<String> noOptions) {     System.out.println(prompt);     while (true)     {         String userInput = sc.nextLine();         System.out.println();         if (yesOptions.contains(userInput))             return true;         if (noOptions.contains(userInput))             return false;         System.out.println(retry); }  public static boolean userStaysOrNot() {     return getBooleanFromUser(" Knowing where one of the Goats are, do you wish to stay on your current door, or do you want to change?", "Invalid input, please retry", ["change", "1", "yes"], ["stay", "0", "false"]); }   
 

If would definitly help if you had a function to get the user input : you'd have a better separation of concerns, behavior would be easier to change and the user interface would be slightly more intuitive and user-friendly.

My Java is a bit rusty but something like (following code is not correct, what matters is the idea more than the code itself):

public static boolean getBooleanFromUser(String prompt, String retry, List<String> yesOptions, List<String> noOptions) {     System.out.println(prompt);     while (true)     {         String userInput = sc.nextLine();         System.out.println();         if (yesOptions.contains(userInput))             return true;         if (noOptions.contains(userInput))             return false;         System.out.println(retry); }  public static boolean userStaysOrNot() {     return getBooleanFromUser("\nKnowing where one of the Goats are, do you wish to stay on your current door, or do you want to change?", "Invalid input, please retry", ["change", "1", "yes"], ["stay", "0", "false"]); } 
 
 
5
 
vote

Yo usaría un valor booleano para representar si la puerta tiene un automóvil detrás de él o no. Yo modificaría:

  class Door { String goatorcar; int open; }    

a

  class Door {     boolean hasCar;     int open; }    

entonces, puedes cambiar todo

  else if (pickedC==1) {     if (C.goatorcar.equals("Car")){         i = rand.nextInt(2);         if (i==0){ System.out.println("The door A contains a Goat");              A.open=1; }         else if (i==1){ System.out.println("The door B contains a Goat");              B.open=1; }     }     else {         if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat");              A.open=1; }         else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat");              B.open=1; }     } } else { System.out.println("You haven't picked any door");      System.exit(0); } 0  

a simplemente

  else if (pickedC==1) {     if (C.goatorcar.equals("Car")){         i = rand.nextInt(2);         if (i==0){ System.out.println("The door A contains a Goat");              A.open=1; }         else if (i==1){ System.out.println("The door B contains a Goat");              B.open=1; }     }     else {         if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat");              A.open=1; }         else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat");              B.open=1; }     } } else { System.out.println("You haven't picked any door");      System.exit(0); } 1  

mucho más simple!

Ahora, siempre que haga else if (pickedC==1) { if (C.goatorcar.equals("Car")){ i = rand.nextInt(2); if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; } else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; } } else { if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; } else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; } } } else { System.out.println("You haven't picked any door"); System.exit(0); } 2 , puede cambiar eso a else if (pickedC==1) { if (C.goatorcar.equals("Car")){ i = rand.nextInt(2); if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; } else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; } } else { if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; } else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; } } } else { System.out.println("You haven't picked any door"); System.exit(0); } 3 . De manera similar, else if (pickedC==1) { if (C.goatorcar.equals("Car")){ i = rand.nextInt(2); if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; } else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; } } else { if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; } else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; } } } else { System.out.println("You haven't picked any door"); System.exit(0); } 4 puede convertirse en else if (pickedC==1) { if (C.goatorcar.equals("Car")){ i = rand.nextInt(2); if (i==0){ System.out.println("The door A contains a Goat"); A.open=1; } else if (i==1){ System.out.println("The door B contains a Goat"); B.open=1; } } else { if (A.goatorcar=="Goat") { System.out.println("The door A contains a Goat"); A.open=1; } else if (B.goatorcar=="Goat") { System.out.println("The door B contains a Goat"); B.open=1; } } } else { System.out.println("You haven't picked any door"); System.exit(0); } 5 . Hay muchos más cambios que podría hacer, pero esto es importante.

 

I would use a boolean value to represent if the door has a car behind it or not. I would modify:

class Door { String goatorcar; int open; }  

to

class Door {     boolean hasCar;     int open; }  

Then, you can change all of

if(i==0) {     A.goatorcar="Car";     B.goatorcar="Goat";     C.goatorcar="Goat"; } else if (i==1){     A.goatorcar="Goat";     B.goatorcar="Car";     C.goatorcar="Goat"; } else if (i==2) {     A.goatorcar="Goat";     B.goatorcar="Goat";     C.goatorcar="Car"; } else { System.out.println("Unexpected error"); } 

to simply

A.hasCar = i == 0; B.hasCar = i == 1; C.hasCar = i == 2; 

Much simpler!

Now, whenever you do A.goatcar.equals("Car"), you can change that to A.hasCar. Similarly, A.goatcar.equals("Goat") can become !A.hasCar. There are many more changes you could maker but this is an important one.

 
 
         
         
3
 
vote

Hay muchas buenas sugerencias en las otras respuestas para Mejora del estilo de codificación de este programa. Si el objetivo es simular el conjunto de un programa de juego con un uno a uno. Correspondencia entre objetos en el conjunto y objetos en su código fuente, Debe seguir ese consejo, así como usted.

Si el objetivo es simplemente simular los eventos que ocurren mientras juegan el juego, Sin embargo (que parece ser el objetivo, ya que esas son las únicas cosas que son emitidos por el programa), Luego hay un modelo mucho más simple del juego que también funcionará. Este modelo se construye alrededor de dos variables que describen el conjunto del programa de juegos:

  • doorWithCar Esta variable tiene valor 1, 2 o 3, lo que indica si el automóvil está detrás de la primera, segunda o tercera puerta.
  • doorOpened Esta variable inicialmente tiene valor 0, cuando todas las puertas están cerradas; Cuando Monty abre una puerta, esta variable se le asigna el número de la puerta Monty Abre.

Además, puede usar dos variables para representar las decisiones del jugador:

  • initialChoiceDoor El número de la puerta primero elegido por el jugador.
  • finalChoiceDoor3 El número de la puerta elegida por el jugador después de Monty ha abierto una de las otras puertas.

Todo lo que necesita saber sobre el estado de las cosas en cada etapa de la juego (hasta el momento en que Monty revela lo que el jugador ha ganado) Puede ser representado por estas cuatro variables.

Aún necesitará un código para manejar la entrada y la salida, por ejemplo, un mapeo de los valores de las cuatro variables anteriores a los nombres de las puertas (si desea imprimir nombres diferentes de los valores utilizados para el estado interno de el programa), y una función de entrada que toma una respuesta del usuario y determina lo que significa (puerta 1, 2, o 3; interruptores o estadías). También puede querer funciones para cosas como las que se abre la puerta Monty. (La entrada de esta función sería doorWithCar y initialChoiceDoor ) o qué puerta el jugador finalmente elige (La entrada de esta función podría ser initialChoiceDoor , doorOpened , y un booleano Valor que indica si el jugador optó por "cambiar").

Podría terminar con el código donde la clase principal se vea algo así:

  public class Paradox {     public static void main(String[] args) {         playGame();     }      void playGame() {         Random randomVar   = new Random();         int    doorWithCar = randomVar.nextInt(3);          System.out.println("  Pick a door: A, B, or C.");         Scanner sc = new Scanner(System.in);         int initialChoiceDoor = doorSelectedByString(sc.nextLine());          int doorOpened = chooseDoorToOpen(initialChoiceDoor, doorWithCar);          System.out.println("The door " + nameOfDoor(doorOpened) + " contains a Goat");         System.out.println(" Do you want to change?");          bool isChange = isChangeString(sc.nextLine());         int  finalChoiceDoor = isChange ? neitherOfTheseDoors(initialChoiceDoor, doorOpened) :                                           initialChoiceDoor ;          String tactic = isChange ? "changed" : "stayed":         String prize  = (finalChoiceDoor == doorWithCar) ? "Car" : "Goat";         System.out.print("Congratulations! You " + tactic + ", and won a " + prize);     }      /* other functions here ... */ }   

Para manejar la mala entrada, podría tener las funciones doorSelectedByString y doorOpened0 Imprima un mensaje de error y salga si la entrada no realiza una opción válida; Si desea poder reutilizar esta clase en un programa más grande, podría tener estas funciones que lanzan excepciones en lugar de salir, y manejar las excepciones en la función principal ().

Es cierto que, hay un poco precioso en el camino de la programación orientada a objetos en este ejemplo. Pero el punto es que este es un ejercicio tan simple, no se necesita muchos objetos. Si debe crear un montón de objetos solo para manejar un problema tan simple, ¿Qué haces cuando tienes que resolver un problema que es fundamentalmente mucho más? ¿Complicado? Mantener las cosas lo más simples posible significa el código para grandes, complicadas. Los problemas son más fáciles de entender.

 

There are a lot of good suggestions in the other answers for improving the coding style of this program. If the goal is to simulate the set of a game show with a one-to-one correspondence between objects on the set and Objects in your source code, you should follow that advice as well as you can.

If the goal is simply to simulate the events that occur while playing the game, however (which appears to be the goal, since those are the only things that are output by the program), then there is a much simpler model of the game that will work just as well. This model is built around two variables describing the set of the game show:

  • doorWithCar This variable has value 1, 2, or 3, indicating whether the car is behind the first, second, or third door.
  • doorOpened This variable initially has value 0, when all the doors are closed; when Monty opens a door, this variable is assigned the number of the door Monty opened.

In addition, you can use two variables to represent the player's decisions:

  • initialChoiceDoor The number of the door first chosen by the player.
  • finalChoiceDoor The number of the door chosen by the player after Monty has opened one of the other doors.

Everything you need to know about the state of things at each stage of the game (up to the moment when Monty reveals what the player has won) can be represented by these four variables.

You'll still need code to handle input and output, for example a mapping from the values of the four variables above to the names of the doors (if you want to print names different from the values used for the internal state of the program), and an input function that takes a response from the user and determines what it means (door 1, 2, or 3; switch or stay). You might also want functions for things such as which door Monty opens (this function's input would be doorWithCar and initialChoiceDoor) or which door the player finally chooses (this function's input could be initialChoiceDoor, doorOpened, and a boolean value indicating whether the player chose to "switch").

You might end up with code where the main class looks something like this:

public class Paradox {     public static void main(String[] args) {         playGame();     }      void playGame() {         Random randomVar   = new Random();         int    doorWithCar = randomVar.nextInt(3);          System.out.println("\n\nPick a door: A, B, or C.");         Scanner sc = new Scanner(System.in);         int initialChoiceDoor = doorSelectedByString(sc.nextLine());          int doorOpened = chooseDoorToOpen(initialChoiceDoor, doorWithCar);          System.out.println("The door " + nameOfDoor(doorOpened) + " contains a Goat");         System.out.println("\nDo you want to change?");          bool isChange = isChangeString(sc.nextLine());         int  finalChoiceDoor = isChange ? neitherOfTheseDoors(initialChoiceDoor, doorOpened) :                                           initialChoiceDoor ;          String tactic = isChange ? "changed" : "stayed":         String prize  = (finalChoiceDoor == doorWithCar) ? "Car" : "Goat";         System.out.print("Congratulations! You " + tactic + ", and won a " + prize);     }      /* other functions here ... */ } 

To handle bad input, you could have the functions doorSelectedByString and isChangeString print an error message and exit if the input does not make a valid choice; if you want to be able to re-use this class in a larger program, you could have these functions throw exceptions instead of exiting,and handle the exceptions in the main() function.

Admittedly, there is precious little in the way of object-oriented programming in this example. But the point is that this is such a simple exercise, it does not need a lot of objects. If you must create a bunch of objects just to handle such a simple problem, what do you do when you have to solve a problem that is fundamentally much more complicated? Keeping things as simple as possible means the code for large, complicated problems is easier to understand.

 
 
3
 
vote

Aquí hay una versión alternativa (parcial).

  1. En lugar de un Door clase, se usa una puerta enum . Sería trivial usar el tipo int2 , tal vez ahorre un poco de memoria. Pero, es conveniente tener todos los valores de puerta legales enumerados. El estado se almacena directamente en el objeto del juego, que es conveniente (y funciona) porque el juego es tan simple.
  2. Implementaciones Especifique cómo ocurre la entrada, por ejemplo, InteractiveGame3 , 9988776655544334 , AlwaysSwitchGame5 , etc.
  3. Ahora puede probar la lógica del juego sin simular la entrada estándar.
  4. El algoritmo del juego está encapsulado en un método corto y fácil de leer.
  5. Implementaciones especifican la fuente aleatoria.
  6. Juegos consecutivos (ya sea real o prueba) puede reutilizar un objeto Random65544336 en lugar de reencender cada juego.
  7. Las pruebas
  8. pueden hacer un accesorio de semillas aleatorias. Ahora las pruebas son deterministas.
  9. Cada juego tiene su propio estado. Su método main puede ejecutar algunos juegos, luego mostrar las estadísticas. Puede tener un método separado que realice un 9988776655544338 y muestra el resultado, por ejemplo,

    La puerta A tiene el coche. Usted recogió la puerta B. La puerta C fue abierta. ¡Te atrapaste con tu selección y perdiste!

  10. Cada objeto es inmutable de "código> Game. El juego se ejecuta en la construcción. Te deja con el resultado. Puede procesar juegos de forma segura en un entorno multi-roscado.

.

  enum0  
 

Here's a (partial) alternate version.

  1. Instead of a Door class, a Door enum is used. It'd be trivial to use the int type instead, maybe save a little memory. But, it's convenient to have all the legal door values enumerated. State is stored directly in the game object, which is convenient (and works) because the game is so simple.
  2. Implementations specify how the input happens, eg InteractiveGame, RandomGame, AlwaysSwitchGame, etc
  3. Now you can test the game logic without simulating standard input.
  4. The game algorithm is encapsulated in a short easy to read method.
  5. Implementations specify the random source.
  6. Consecutive games (whether real or test) can re-use a Random object instead of re-seeding every game.
  7. Tests can make the random seed a fixture. Now tests are deterministic.
  8. Each game has its own state. Your main method might run a few games, then display statistics. You can have a separate method that takes a Game and displays the result, eg

    Door A has the car. You picked door B. Door C was opened. You stuck with your pick and lost!

  9. Each Game object is immutable. The game is run on construction. It leaves you with the outcome. You can safely process games in a multi-threaded environment.

.

public enum Door {     A, B, C; }  public abstract class Game {      protected final Random rnd;     public final Door hasCar;     public final Door choice1;     public final Door opened;     public final Door choice2;      protected abstract Door userPicks();     protected abstract boolean userSwitches();      public Game(Random rnd) {         this.rnd = rnd;         hasCar = Door.values()[rnd.nextInt(Door.values().length)];         choice1 = userPicks();         opened = hostOpens();         choice2 = userSwitches() ? userPicks() : choice1;     }      private Door hostOpens() {         List<Door> could = new ArrayList<>();         for (Door d : Door.values()) {             if (d != hasCar && d != choice1) {                 could.add(d);             }         }         return could.get(rnd.nextInt(could.size()));     } } 
 
 
2
 
vote

Use algún tipo de contenedor de datos como una matriz o un conjunto para colocar las puertas. Y sí, algunos métodos también pueden ayudar.

Mira esta versión

  enum1  

Editar: Había mucha repetición en tu código. Que se puede fijar utilizando variables para que pueda escribir por ejemplo. enum2 En lugar de tener varias declaraciones de impresión que hacen el mismo trabajo. El uso de clases de recopilación, como set o lista, puede simplificar las cosas porque puede usar una variable para indicar qué elemento en esa recopilación desea acceder en lugar de tener que decidir que cuando escriba el código y también puede agregar o eliminar fácilmente los artículos de una colección que le permite administrar cantidades arbitrarias de datos.

 

Use some kind of data container like an array or a set to put the doors in. And yes, some methods might help as well.

Look at this version

import java.lang.Math.*; import java.util.Arrays; import java.util.HashSet; import java.util.Random; import java.util.Set; import java.util.Scanner;  public class Paradox {   private static Random rand = new Random();   private static int cars = 0;    private static String pickRandom(Set<String> set) {     return (String)set.toArray()[rand.nextInt(set.size())];   }    public static void run(boolean automatic, String changeornot) {     Set<String> closedDoors = new HashSet<>(Arrays.asList("A", "B", "C"));     String doorWithCar = pickRandom(closedDoors);     Set<String> doorsWithGoat = new HashSet<>(closedDoors);     doorsWithGoat.remove(doorWithCar);      Scanner sc = new Scanner(System.in);      System.out.println("\n\nYou have got three doors, there is a price inside each of them. Pick a door: A, B, or C.");     String pickedDoor = "";     if(automatic) {       pickedDoor = pickRandom(closedDoors);     } else {       while(true) {         pickedDoor = sc.nextLine().toUpperCase();         System.out.println("\n");         try {           pickedDoor = "" + (char)(Integer.parseInt(pickedDoor) - 1 + 'A');         } catch(NumberFormatException e) {         }         if(closedDoors.contains(pickedDoor)) break;         System.out.println("The door you chose is not available. Try again.");       }     }     System.out.println("you picked door " + pickedDoor);     Set<String> possibleChoices = new HashSet<>(doorsWithGoat);     possibleChoices.remove(pickedDoor);      String openDoor = pickRandom(possibleChoices);     closedDoors.remove(openDoor);      System.out.println("The door " + openDoor + " contains a Goat");      System.out.println("\nKnowing where one of the Goats are, do you wish to stay on your current door, or do you want to change?");     if(!automatic) {       while(true) {         changeornot = sc.nextLine().toLowerCase();         System.out.println();          if (changeornot.equals("1") || changeornot.equals("yes")) {             changeornot = "change";         }         else if (changeornot.equals("0") || changeornot.equals("no")) {             changeornot = "stay";         }         if(changeornot.equals("change") || changeornot.equals("stay")) break;         System.out.println("choose either change or stay");       }     }     if(changeornot.equals("change")) {       closedDoors.remove(pickedDoor);       pickedDoor = (String)closedDoors.toArray()[0];     }     String price = "goat";     if(pickedDoor.equals(doorWithCar)) price = "car";     System.out.print("Congratulations! You chose to " + changeornot + ", and won a " + price + ".");     System.out.println();     if(price.equals("car")) cars++;      System.out.println("---------------------------------------");   }    public static void main(String[] args) {     String choice = "stay";     for(int i = 0; i < 1000; i++) run(true, choice);     System.out.println("You chose to " + choice + " and won a total of " + cars + " cars.");   } } 

edit: There was a lot of repetition in your code. That can be fixed by using variables so you can write e.g. System.out.println("The door " + openDoor + " contains a Goat"); instead of having several println statements that do the same job. Also using collection classes like Set or List can simplify things because you can then again use a variable to state which element in that collection you want to access instead of having to decide that when you write the code and you can also easily add or remove items from a collection allowing you to manage arbitrary amounts of data.

 
 
         
         

Relacionados problema

1  Cuenta las precipitaciones acumuladas en una cadena de montaña 2D  ( Count the accumulated rainfall in a 2d mountain range ) 
desafío: cuenta cuánta lluvia se recogerá en los valles entre los picos de una cordillera en un mundo 2D. La gama de montaña se define por una única ...

0  Consigue los lados del vecino de un cubo de rúbidos  ( Get neighbour sides of a rubics cube ) 
Estoy escribiendo 2x2x2 Rubics Cube Simulator. En mi código, tengo un concepto de cara, que es un lado individual del cubo, y el estado, que es agregado de lo...

5  Vectorización para simulación de temperatura  ( Vectorization for temperature simulation ) 
Soy nuevo en Matlab y me gustaría saber consejos para reducir el tiempo de procesamiento de dicho programa. El esquema del código real es muy similar al códig...

4  Tarea de lotería virtual  ( Virtual lotto task ) 
Tuve la tarea de escribir un simulador de lotería. Mi programa funciona de la siguiente manera: Para comenzar, el usuario puede escribir en 6 números. Lu...

1  Medidas repetidas de optimización simuladora  ( Repeated measures simulator optimisation ) 
Estoy aprendiendo a programar en R y para hacer eso y crear algo útil en el proceso, he decidido reescribir este applet Java para la simulación de medidas r...

8  UEFA Champions League Draw Simulator  ( Uefa champions league draw simulator ) 
Soy nuevo en Python y he escrito un simulador de sorteo de la UEFA Champions League. Recibe aportes para 32 equipos de 14 países, y luego los distribuye al az...

2  Simulación física de agregados limitados por difusión  ( Physical simulation of diffusion limited aggregates ) 
El siguiente código genera agregados limitados de difusión en un Lattice cuadrado bidimensional. Algunos del Código se han omitido (por ejemplo, Soporte par...

1  Simulación de la placa de galton  ( Galton board simulation ) 
Este programa está escrito para Windows 7 en MINGW utilizando GCC. Estoy buscando recomendaciones para mejorar la portabilidad del programa. /* galtonboa...

5  Monte Carlo Moneda Simulación Flip  ( Monte carlo coin flip simulation ) 
He estado aprendiendo sobre las simulaciones de Monte Carlo en la introducción de MIT a la clase de programación, y estoy tratando de implementar una que calc...

8  Los individuos reproducen y mutan  ( Individuals reproduce and mutate ) 
¿Cómo puedo mejorar el rendimiento (en términos de tiempo de cómputo) de este código? # Settings const nbloci = 100 # length of the genome const ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos