After seeing @ johejo's post "Bingo Judgment Program", I thought it was an interesting story, but it was all a static method procedural program. I was disappointed that it was. Since it's Java, let's refactor it in an object-oriented manner. Of course, this is not the final form. I think you can do better refactoring, so please try it out by trial and error.
I received a comment from @ k73i55no5 again and refactored only the Bingo class.
public class Bingo {
public static void main(String[] args) throws Exception {
Bingo bingo = new Bingo(loadCardNumbers("board.txt"));
bingo.select(loadSelectionNumbers("selected.txt"));
bingo.show();
}
public static int[][] loadCardNumbers(String filename) throws IOException {
return Files.readAllLines(Paths.get(filename))
.stream()
.map(line -> Arrays.stream(line.split(" "))
.mapToInt(Integer::parseInt)
.toArray())
.toArray(int[][]::new);
}
public static int[] loadSelectionNumbers(String filename) throws IOException {
return Files.readAllLines(Paths.get(filename))
.stream()
.mapToInt(Integer::parseInt)
.toArray();
}
private final BingoCard card;
public Bingo(int[][] numbers) {
this(new BingoCard(numbers));
}
Bingo(BingoCard card) {
this.card = card;
}
public void select(int[] numbers) {
Arrays.stream(numbers).forEach(card::select);
}
public void show() {
System.out.println("BINGO:" + card.countBingo());
System.out.println("REACH:" + card.countReach());
}
}
Based on the comments made by @ k73i55no5, we carried out the second refactoring. The cell of the bingo card is fixed at 5x5, and the data size consistency check is omitted. If you have any further improvements, please comment.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;
public class Bingo {
public static void main(String[] args) throws Exception {
//Read the number data of the bingo card and create a bingo card
int[][] numbers = Files.readAllLines(Paths.get("board.txt"))
.stream()
.map(line -> Arrays.stream(line.split(" "))
.mapToInt(Integer::parseInt)
.toArray())
.toArray(int[][]::new);
BingoCard card = new BingoCard(numbers);
//Read the number string selected by the bingo tournament organizer and reflect it on the bingo card
Files.readAllLines(Paths.get("selected.txt"))
.stream()
.map(Integer::parseInt)
.forEach(card::select);
//Display the status of bingo cards
System.out.println("BINGO:" + card.countBingo());
System.out.println("REACH:" + card.countReach());
}
}
class BingoCard {
private final SelectableNumbers numbers;
private final BingoLines lines;
public BingoCard(int[][] numbers) {
this.numbers = new SelectableNumbers(numbers);
this.lines = new BingoLines(this.numbers);
}
public void select(int number) {
numbers.select(number);
}
public long countReach() {
return lines.countReach();
}
public long countBingo() {
return lines.countBingo();
}
}
class SelectableNumber {
public final int number;
private boolean selected = false;
public SelectableNumber(int number) {
this.number = number;
}
public void select() {
selected = true;
}
public boolean isSelected() {
return selected;
}
}
class SelectableNumbers {
private final SelectableNumber[] numbers;
private static SelectableNumber[] flattenNumbers(int[][] numbers) {
return Stream.of(numbers)
.flatMapToInt(Arrays::stream)
.mapToObj(SelectableNumber::new)
.toArray(SelectableNumber[]::new);
}
public SelectableNumbers(int[][] numbers) {
this.numbers = flattenNumbers(numbers);
}
public SelectableNumber getAt(int index) {
return numbers[index];
}
public void select(int number) {
Stream.of(numbers)
.filter(n -> n.number == number)
.forEach(n -> n.select());
}
}
class BingoLine {
private final SelectableNumber[] numbers;
public BingoLine(SelectableNumber[] numbers) {
this.numbers = numbers;
}
private long countSelectedNumbers() {
return Stream.of(numbers).filter(number -> number.isSelected()).count();
}
public boolean isReach() {
return countSelectedNumbers() == numbers.length - 1;
}
public boolean isBingo() {
return countSelectedNumbers() == numbers.length;
}
}
class BingoLines {
//Line index number array, index number is 0 to 24 fixed
private static final int[][] LINES = new int[][] {
//Horizontal line Vertical line
{ 0, 1, 2, 3, 4}, {0, 5, 10, 15, 20},
{ 5, 6, 7, 8, 9}, {1, 6, 11, 16, 21},
{10, 11, 12, 13, 14}, {2, 7, 12, 17, 22},
{15, 16, 17, 18, 19}, {3, 8, 13, 18, 23},
{20, 21, 21, 23, 24}, {4, 9, 14, 19, 24},
//Diagonal line from top left to bottom left, top right to bottom left
{ 0, 6, 12, 18, 19}, {4, 8, 12, 16, 20},
};
private static BingoLine[] makeBingoLines(SelectableNumbers numbers) {
return Stream.of(LINES)
.map(line -> Arrays.stream(line)
.mapToObj(numbers::getAt)
.toArray(SelectableNumber[]::new))
.map(BingoLine::new)
.toArray(BingoLine[]::new);
}
private final BingoLine[] lines;
public BingoLines(SelectableNumbers numbers) {
lines = makeBingoLines(numbers);
}
public long countReach() {
return Stream.of(lines).filter(line -> line.isReach()).count();
}
public long countBingo() {
return Stream.of(lines).filter(line -> line.isBingo()).count();
}
}
Random numbers in 5 rows and 5 columns are written on the bingo card. Strictly speaking, the range of numbers is decided for each column, but I don't care about that. At the bingo tournament, each person is dealt a paper card with a different number written on it, the organizer randomly selects a ball with the number written on it, and if that number is in the card, that number part Fold it to the selected state. Cards have rows, columns, and diagonal rows, with one row containing five numbers. If all the numbers in one line are selected, it will become "Bingo" and you will receive a prize. The state of becoming a bingo when one more is selected is called "reach".
The words "card", "number", and "line" have come up, so let's make them into the Card, Number, and Line classes. When the bingo tournament organizer chooses a number, he usually searches for the number in his bingo card and folds the paper to select it, but in the object-oriented world, the class can be anthropomorphized and used. I will. People: Hey Card, do you have this number? If there is, please choose. Card-kun: Oh, there was. Numbers, you were chosen. Number-kun: Oh, did you choose me? Tell me what you belong to. Nami-kun: Oh, the number chosen has increased by one. Card-kun, the number of numbers selected for me is now four. Card-kun: Oh, did you have all four, do you have a reach? One more time soon.
I tried to program such a situation.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Stream;
//Bingo card
class Card {
//Numbers on bingo cards
class Number {
final int value;
private boolean isSelected = false;
private final List<Line> lines = new ArrayList<>();
Number(int value) {
this.value = value;
}
//Belongs to vertical, horizontal, diagonal rows
void belong(Line line) {
lines.add(line);
}
//The numbers were chosen
void selected() {
if (!isSelected) {
isSelected = true;
//Belong and inform
lines.stream().forEach(line -> line.selected());
}
}
}
//Arrangement on bingo cards (vertical, horizontal, diagonal)
class Line {
private int selectedCount = 0;
//The numbers in the line were chosen
void selected() {
selectedCount++;
//Update card status
judge(this);
}
}
final int size;
int bingo = 0, reach = 0;
private final HashMap<Integer, Number> myNumbers = new HashMap<>();
//Bingo card generation
Card(int[][] numbers) {
//Make vertical, horizontal and diagonal rows
size = numbers.length;
Line[] rowLines = new Line[size]; //Side by side
Line[] colLines = new Line[size]; //Vertical arrangement
Line backslashLine = new Line(); //Diagonal arrangement from top left to bottom right
Line slashLine = new Line(); //Diagonal arrangement from top right to bottom left
for (int i = 0; i < size; i++) { //Initialize because the contents of the array are empty
rowLines[i] = new Line();
colLines[i] = new Line();
}
//Make and belong to each number
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
Number number = new Number(numbers[row][col]);
number.belong(rowLines[row]);
number.belong(colLines[col]);
if (row == col) {
number.belong(backslashLine);
}
if (row == size - col - 1) {
number.belong(slashLine);
}
myNumbers.put(number.value, number);
}
}
}
//If there is a number, make it the selected state
void selected(int number) {
Number myNumber = myNumbers.get(number);
if (myNumber != null) {
myNumber.selected();
}
}
//Update the number of reach and bingo according to the number of selected numbers in the line
void judge(Line line) {
if (line.selectedCount == size - 1) {
reach++;
} else if (line.selectedCount == size) {
reach--; //Since it is counted at the time of reach, reduce it
bingo++;
}
}
}
//Bingo tournament
public class Bingo {
public static void main(String[] args) throws Exception {
//Read the number data of the bingo card and create a bingo card
List<String> board = Files.readAllLines(Paths.get("board.txt"));
int size = board.size();
int[][] numbers = new int[size][size];
for (int row = 0; row < size; row++) {
String[] values = board.get(row).split(" ");
for (int col = 0; col < size; col++) {
numbers[row][col] = Integer.parseInt(values[col]);
}
}
Card card = new Card(numbers);
//Read the number string selected by the bingo tournament organizer and reflect it on the bingo card
Stream<String> selected = Files.lines(Paths.get("selected.txt"));
selected.forEach(number -> card.selected(Integer.parseInt(number)));
//Display the status of bingo cards
System.out.println("BINGO:" + card.bingo + "\nREACH:" + card.reach);
}
}
Input file
biard.txt
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
selected.txt
1
7
13
19
2
3
4