/*
@startuml
class Bingo {
- final char letter
- final int number
- static final Random rand
+ Bingo()
+ Bingo(letter: char, number: int)
- generateRandomNumber(letter: char): int
- isValidLetter(letter: char): boolean
- isValidNumber(letter: char, number: int): boolean
+ getLetter(): char
+ getNumber(): int
+ toString(): String
}
class BingoGame {
+ main(args: String[]): void
- testValidBingoCalls(): void
- testInvalidBingoCalls(): void
}
BingoGame --> Bingo : "Creates & Controls"
Bingo ..> java.util.Random : "Uses"
@enduml
*/
import java.util.Random;
/**
* Represents a Bingo call with a letter (B, I, N, G, O) and a number
*/
class Bingo {
private final char letter; // Stores the letter (B, I, N, G, O)
private final int number; // Stores the number corresponding to the letter
private static final Random rand = new Random(); // Shared Random instance
/**
* Default constructor - generates a random Bingo call
*/
public Bingo() {
char[] letters = {'B', 'I', 'N', 'G', 'O'};
this.letter = letters[rand.nextInt(5)];
this.number = generateRandomNumber(letter);
}
/**
* Constructor with specific letter and number
* If invalid, defaults to "N, FREE"
*/
public Bingo(char letter, int number) {
if (isValidLetter(letter) && isValidNumber(letter, number)) {
this.letter = letter;
this.number = number;
} else {
this.letter = 'N';
this.number = 0; // Defaults to "N, FREE" if invalid
}
}
/**
* Generates a random number based on the Bingo letter category
*/
private int generateRandomNumber(char letter) {
return switch (letter) {
case 'B' -> rand.nextInt(15) + 1; // 1 to 15
case 'I' -> rand.nextInt(15) + 16; // 16 to 30
case 'N' -> rand.nextInt(15) + 31; // 31 to 45
case 'G' -> rand.nextInt(15) + 46; // 46 to 60
case 'O' -> rand.nextInt(15) + 61; // 61 to 75
default -> 0; // Should not occur
};
}
/**
* Validate if the letter is in "BINGO"
*/
private boolean isValidLetter(char letter) {
return "BINGO".indexOf(letter) != -1;
}
/**
* Validate if the number is within the correct range for the letter
*/
private boolean isValidNumber(char letter, int number) {
return switch (letter) {
case 'B' -> number >= 1 && number <= 15;
case 'I' -> number >= 16 && number <= 30;
case 'N' -> number >= 31 && number <= 45;
case 'G' -> number >= 46 && number <= 60;
case 'O' -> number >= 61 && number <= 75;
default -> false;
};
}
/**
* Converts Bingo object to a string format like "B, 12"
*/
@Override
public String toString() {
return String.format("%s, %s", letter, (number == 0 ? "FREE" : number));
}
}
/**
* Main driver class for testing Bingo calls
*/
public class BingoGame {
public static void main(String[] args) {
System.out.println("------ 20 Random Bingo Calls ------");
for (int i = 0; i < 20; i++) {
Bingo bingoCall = new Bingo();
System.out.println(bingoCall);
}
System.out.println("\n------ Valid Bingo Calls (Boundary & Mid-Range) ------");
testValidBingoCalls();
System.out.println("\n------ Invalid Bingo Calls (Should Default to N, FREE) ------");
testInvalidBingoCalls();
}
/**
* Method to test valid Bingo calls (Boundary & Mid-Range)
*/
private static void testValidBingoCalls() {
char[] letters = {'B', 'I', 'N', 'G', 'O'};
int[][] testNumbers = {
{1, 7, 15}, // B column
{16, 22, 30}, // I column
{31, 38, 45}, // N column
{46, 53, 60}, // G column
{61, 69, 75} // O column
};
for (int i = 0; i < letters.length; i++) {
for (int j = 0; j < testNumbers[i].length; j++) {
System.out.println(new Bingo(letters[i], testNumbers[i][j]));
}
}
}
/**
* Method to test invalid Bingo calls
*/
private static void testInvalidBingoCalls() {
Bingo[] invalidCalls = {
new Bingo('X', 10), // Invalid letter
new Bingo('B', 42), // Invalid number for B
new Bingo('I', 11), // Invalid number for I
new Bingo('N', 75), // Invalid number for N
new Bingo('G', 1), // Invalid number for G
new Bingo('O', 80) // Invalid number for O
};
for (Bingo call : invalidCalls) {
System.out.println(call);
}
}
}