การจำลองการโยนลูกเต๋าใน Java

Oct 30 2020

สำหรับหนึ่งในห้องทดลองของฉันฉันต้องเขียนโปรแกรม java ที่สมบูรณ์ซึ่งจะจำลองเกมเดิมพันลูกเต๋าที่ "ง่ายมาก" ข้อกำหนดมีดังนี้: จำลองการโยนลูกเต๋า 3 ลูก ถ้าคุณโยนสามหกคุณจะชนะ$20; if you throw three of any other value then you win $10; หากคุณทอยลูกเต๋าสองลูกซึ่งมีค่าเท่ากันคุณจะชนะ$5. If none of the conditions above are met, then you would lose $1.

ตัวอย่างการวิ่ง: ลูกเต๋าโยน

Dice 1 : 2     Dice 2 : 1    Dice 3 : 2
Congratulations : You threw TWO - 2s
You win $5 Dice 1 : 2 Dice 2 : 2 Dice 3 : 2 Congratulations : You threw THREE - 2s You win $10

Dice 1 : 4    Dice 2 : 6    Dice 3 : 3
Unfortunately : You did not throw anything of value
You lose $1

รหัสผลลัพธ์ที่ฉันเขียนเพื่อแก้ปัญหานี้มีดังนี้:

/**
 * SRN: 507-147-9
 */
public class Lab6_part3 {

    public static void main(String[] args) {

        // define vars
        int round = 1;
        int dice1, dice2, dice3;

        while (round <= 3) {

            dice1 = 1 + (int)(Math.random() * 6);
            dice2 = 1 + (int)(Math.random() * 6);
            dice3 = 1 + (int)(Math.random() * 6);

            System.out.println();
            System.out.println("Dice 1 : " + dice1 + "    Dice 2 : " + dice2 + "    Dice 3 : " + dice3);

            // Three of a kind
            if ((dice1 == dice2) && (dice1 == dice3)) { // 3-of-a-kind (D1)                              

                // Rolls three sixes
                if (dice1 == 6) {
                    System.out.println("Congratulations : You threw THREE - 6s");
                    System.out.println("You win $20");
                } else {
                    // Rolls three of anything else
                    System.out.println("Congratulations : You threw THREE - " + dice1 + "s");
                    System.out.println("You win $10"); } } // Two of a kind (PRINT "dice1") else if (dice1 == dice2 || dice1 == dice3) { System.out.println("Congratulations : You threw TWO - " + dice1 + "s"); System.out.println("You win $5");
            } 
            
            // Two of a kind (PRINT "dice2")
            else if (dice2 == dice1 || dice2 == dice3) {                              
                System.out.println("Congratulations : You threw TWO - " + dice2 + "s");
                System.out.println("You win $5"); } // Two of a kind (PRINT "dice3") else if (dice3 == dice1 || dice3 == dice2) { System.out.println("Congratulations : You threw TWO - " + dice3 + "s"); System.out.println("You win $5");
            } 
            // Did not throw anything of value
            else {
                System.out.println("Unfortunately : You did not throw anything of value");
                System.out.println("You lose $1");
            }
            round++;
        }
    }
}

ปัญหาที่ฉันพบกับแนวทางนี้คือแม้ว่าโค้ดจะทำงานตามที่ควรจะเป็น แต่ฉันก็อยากมีวิธีที่ง่ายกว่าในการเขียน two-of-a-kind แทนที่จะมีคำสั่ง "if" สามคำ เป้าหมายของฉันคือการสร้างคำสั่ง "หรือ" สามทางแทนที่จะเปรียบเทียบ dice1 กับลูกเต๋า 2 และ 3 และลูกเต๋า 2 กับลูกเต๋า 1 และ 3 ฯลฯ ...

else if (dice1 == dice2 || dice1 == dice3 || dice2 == dice3) {                              
    System.out.println("Congratulations : You threw TWO - " + somethings?? + "s");
    System.out.println("You win $5"); 

ถ้าฉันจะทำเช่นนั้นฉันจะพิมพ์ค่าของคู่ที่ฉันระบุได้อย่างไร?

คำตอบ

7 Marc Oct 30 2020 at 14:37

ยินดีต้อนรับสู่ CodeReview สำหรับปัญหาของคุณวิธีแก้ไขอย่างรวดเร็วคือ:

else if (dice1 == dice2 || dice1 == dice3 || dice2 == dice3) {       
    int doubleNum = dice1 == dice2 ? dice1 : dice1 == dice3 ? dice1 : dice3;
    System.out.println("Congratulations : You threw TWO - " + doubleNum + "s");
    System.out.println("You win $5"); 
}

ตัวดำเนินการ ternary ทำให้โค้ดมีขนาดกะทัดรัดขึ้น แต่ในกรณีนี้ฉันคิดว่ามันอ่านได้น้อยกว่า chain ของif-else.

คำแนะนำอื่น ๆ :

  • while-loop สามารถแทนที่ได้ด้วย for-loop ที่สะดวกกว่า จาก:
    int round = 1;
    while(round<=3){
        //...
        round++;
    }
    
    ถึง:
    for(int round = 1; round <= 3; round++) {
        //...
    }
    
  • การประกาศตัวแปรหลายตัวในบรรทัดเดียวint dice1, dice2, dice3;ไม่ถือเป็นแนวทางปฏิบัติที่ดีใน Java
  • แทนที่จะสร้างแบบสุ่มfloatแล้วส่งไปยังintสร้างโดยตรงintด้วยThreadLocalRandom.current().nextInt(6). เอกสาร
  • คุณสามารถพิมพ์บรรทัดแรกด้วยSystem.out.formatไฟล์. จาก:
    System.out.println();
    System.out.println("Dice 1 : " + dice1 + "    Dice 2 : " + dice2 + "    Dice 3 : " + dice3);
    
    ถึง:
    System.out.format("%nDice 1 :  %d    Dice 2 : %d    Dice 3 : %n", dice1, dice2, dice3)
    
  • ชื่อชั้นควรจะ PascalCase แทนที่จะคุณสามารถตั้งชื่อมันLab6_part3Lab6Part3
  • ประกาศค่าคงที่สำหรับจำนวนรอบเพื่อให้ง่ายต่อการเปลี่ยนแปลง ตัวอย่างเช่น:
    public class Lab6Part3 {
    
        private static final int ROUNDS = 3;
    
        public static void main(String[] args) {
            for(int round = 1; round <= ROUNDS; round++) {
                //...
            }
    }
    

อีกวิธีหนึ่งคือการสร้างตัวเลขสามตัวRandom#intsและคำนวณความถี่:

Random r = new Random();
// Generate three random numbers from 1 to 6
IntStream diceRolls = r.ints(3, 1, 7);

// Generate map of frequencies
Map<Integer, Long> freq = diceRolls.boxed()
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

boolean winner = false;
for (Entry<Integer, Long> entry : freq.entrySet()) {
    int number = entry.getKey();
    long times = entry.getValue();
    if (times == 3) {
        // Three of a kind ...
        winner = true;
    } else if (times == 2) {
        // Two of a kind...
        System.out.println("Congratulations : You threw TWO - " + number + "s");
        System.out.println("You win $5");
        winner = true;
    }
}
if(!winner) {
    // Did not throw anything of value
}
2 SavvasParastatidis Oct 30 2020 at 21:40

คุณไม่จำเป็นต้องมี 3 else_if งบ มี 3 สถานการณ์ที่คุณอยู่ในกรณี "two-fo-a-kind" dice1 == dice2, dice1 == dice3, dice2 == dice3 บล็อกแรกของคุณจับ 2 สถานการณ์เหล่านี้ได้ ทางเลือกเดียวคือถ้า dice2 == dice3

หากคุณคิดเช่นนั้นบล็อก else_If ที่สามของคุณจะสร้างการประเมินที่แท้จริงในหนึ่งในสองบล็อกแรกเสมอดังนั้นโค้ดของคุณจะไม่มีวันไปถึง

// Two of a kind (PRINT "dice1")
else if (dice1 == dice2 || dice1 == dice3) {
    System.out.println("Congratulations : You threw TWO - " + dice1 + "s");
    System.out.println("You win $5"); } // Two of a kind (PRINT "dice2") else if (dice2 == dice3) { System.out.println("Congratulations : You threw TWO - " + dice2 + "s"); System.out.println("You win $5");
}
2 mdfst13 Oct 31 2020 at 18:20
        }
        
        // Two of a kind (PRINT "dice1")
        else if (dice1 == dice2 || dice1 == dice3) {

กรุณาอย่าทำเช่นนี้ หากคุณต้องการใช้ลูกครึ่งelseโปรดเขียนสองบรรทัดติดกันเสมอ

        }
        else if (dice1 == dice2 || dice1 == dice3) {
          // Two of a kind (PRINT "dice1")

มีสองเหตุผล

  1. หากฉันต้องการทราบว่าโครงสร้างเสร็จสิ้นแล้ววิธีนี้ฉันสามารถดูได้โดยมองไปที่บรรทัดเดียวผ่าน}. ด้วยต้นฉบับของคุณฉันจะต้องดูจำนวนบรรทัดโดยพลการในคำสั่งถัดไป สิ่งนี้จะไม่ดีเป็นพิเศษเมื่อบล็อกความคิดเห็นยาวขึ้น เป็นไปได้ทั้งหมดที่จะเขียนความคิดเห็นที่สูงกว่าหน้าจอเดียว หมายความว่าแทนที่จะเลื่อนไปไกลกว่านั้นฉันจะต้องเลื่อนหน้าลงมาจากความคิดเห็นเพื่อดูว่ามีelseบล็อกอยู่
  2. หากมีคนใช้สิ่งที่ฟอร์แมตโค้ดใหม่เพื่อให้elseอยู่ในบรรทัดเดียวกับโค้ด}ก็จะต้องย้ายความคิดเห็นอยู่ดี จากนั้นแม้ว่าจะจัดรูปแบบกลับความคิดเห็นก็จะย้ายไป สิ่งนี้ทำให้เกิดความสับสนในการควบคุมแหล่งที่มา ดังนั้นให้วางวิธีที่นักปฏิรูปจะต้องทำตั้งแต่ต้น

ภาษารูปแบบ C โดยทั่วไปมีการจัดการบล็อกที่สับสน เนื่องจากใช้}ทั้งสองอย่างเพื่อสิ้นสุดโครงสร้างและเพียงเพื่อจบบล็อกในโครงสร้างต่อเนื่อง กล่าวคือพวกเขาไม่มีทางที่จะพูดได้ว่าifโครงสร้างกำลังจะสิ้นสุดเมื่อเทียบกับการดำเนินการต่อด้วยการelseเรียงลำดับ ในการชดเชยเราต้องใช้รูปแบบการเข้ารหัส และหนึ่งในรูปแบบที่ง่ายที่สุดซึ่งอยู่เหนือสไตล์คือห้ามใส่ปีกกา ( }หรือ{) มากกว่าหนึ่งบรรทัดห่างจากคีย์เวิร์ดที่เกี่ยวข้องหากมี