[JAVA] Nous avons remanié le "Bingo Judgment Program"

Après avoir vu le post de @ johejo "Bingo Judgment Program", j'ai pensé que c'était une histoire intéressante, mais c'était tout un programme procédural de méthode statique. J'ai été déçu que ce soit le cas. Puisqu'il s'agit de Java, refactorisons-le de manière orientée objet. Bien sûr, ce n'est pas la forme définitive. Je pense que nous pouvons mieux refactoriser, alors essayez-le par essais et erreurs.

3e refactoring

J'ai de nouveau reçu un commentaire de @ k73i55no5 et je n'ai retravaillé que la classe Bingo.

Vue d'ensemble de la structure de classe

Diagramme de classe

image.png

Code (cours de bingo uniquement)

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());
    }
}

Deuxième refactoring

Sur la base des commentaires de @ k73i55no5, nous avons effectué le deuxième refactoring. La masse de la carte de bingo est fixée à 5x5 et le contrôle de cohérence de la taille des données est omis. Si vous avez d'autres améliorations, veuillez commenter.

code

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 {
        //Lisez les données numériques de la carte de bingo et créez une carte de bingo
        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);
        //Lisez la chaîne de chiffres sélectionnée par l'organisateur du tournoi de bingo et réfléchissez-la sur la carte de bingo
        Files.readAllLines(Paths.get("selected.txt"))
             .stream()
             .map(Integer::parseInt)
             .forEach(card::select);
        //Afficher le statut de la carte de bingo
        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 {
    //Tableau de numéros d'index de ligne, le numéro d'index est de 0 à 24 fixe
    private static final int[][] LINES = new int[][] {
        //Ligne horizontale Ligne verticale
        { 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},
        //Ligne diagonale de haut à gauche en bas à gauche, de haut à droite en bas à gauche
        { 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();        
    }
}

1er refactoring

Des nombres aléatoires en 5 lignes et 5 colonnes sont écrits sur la carte de bingo. À proprement parler, la plage de nombres est fixe pour chaque colonne, mais je m'en fiche. Lors du tournoi de bingo, chaque personne reçoit une carte papier avec un numéro différent, et l'organisateur sélectionne au hasard une balle avec le numéro dessus, et si ce numéro est sur la carte, ce numéro Pliez-le dans l'état sélectionné. La carte comporte des lignes, des colonnes et des lignes diagonales, et chaque ligne contient cinq nombres. Si tous les numéros d'une ligne sont sélectionnés, cela deviendra un "bingo" et vous recevrez un prix. L'état de devenir un bingo quand un de plus est sélectionné est appelé «portée».

Les mots "carte", "numéro" et "ligne" sont apparus, alors faisons-en les classes Carte, Numéro et Ligne. Lorsque l'organisateur du tournoi de bingo choisit un numéro, il recherche généralement le numéro sur sa propre carte de bingo et plie le papier pour le sélectionner, mais dans le monde orienté objet, la classe peut être anthropomorphisée et utilisée. Je vais. People: Hey Card, avez-vous ce numéro? S'il y en a, veuillez choisir. Card-kun: Oh, il y en avait. Numéros, vous avez été choisi. Number-kun: Oh, tu m'as choisi? Dites-moi à quoi vous appartenez. Nami-kun: Oh, le nombre sélectionné a augmenté d'un. Card-kun, le nombre de numéros sélectionnés en ligne avec moi est maintenant de quatre. Card-kun: Oh, avez-vous les quatre, avez-vous une portée? Une fois de plus bientôt.

J'ai essayé de programmer une telle situation.

code

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;

//Carte de bingo
class Card {

    //Numéros sur la carte de bingo
    class Number {

        final int value;
        private boolean isSelected = false;
        private final List<Line> lines = new ArrayList<>();

        Number(int value) {
            this.value = value;
        }

        //Appartient aux rangées verticales, horizontales et diagonales
        void belong(Line line) {
            lines.add(line);
        }

        //Le numéro a été choisi
        void selected() {
            if (!isSelected) {
                isSelected = true;
                //Appartenir et informer
                lines.stream().forEach(line -> line.selected());
            }
        }
    }

    //Disposition sur la carte de bingo (verticale, horizontale, diagonale)
    class Line {

        private int selectedCount = 0;

        //Les numéros de la ligne ont été choisis
        void selected() {
            selectedCount++;
            //Mettre à jour l'état de la carte
            judge(this);
        }
    }

    final int size;
    int bingo = 0, reach = 0;
    private final HashMap<Integer, Number> myNumbers = new HashMap<>();

    //Génération de cartes de bingo
    Card(int[][] numbers) {
        //Créer des rangées verticales, horizontales et diagonales
        size = numbers.length;
        Line[] rowLines = new Line[size];   //Cote à cote
        Line[] colLines = new Line[size];   //Disposition verticale
        Line backslashLine = new Line();    //Disposition diagonale de haut à gauche en bas à droite
        Line slashLine = new Line();        //Disposition diagonale de haut à droite en bas à gauche
        for (int i = 0; i < size; i++) {    //Initialiser car le contenu du tableau est vide
            rowLines[i] = new Line();
            colLines[i] = new Line();
        }
        //Faire et appartenir à chaque numéro
        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);
            }
        }
    }

    //S'il y a un nombre, sélectionnez-le
    void selected(int number) {
        Number myNumber = myNumbers.get(number);
        if (myNumber != null) {
            myNumber.selected();
        }
    }

    //Mettre à jour le nombre de portée et de bingo en fonction du nombre de numéros sélectionnés dans la ligne
    void judge(Line line) {
        if (line.selectedCount == size - 1) {
            reach++;
        } else if (line.selectedCount == size) {
            reach--;    //Puisqu'il est compté au moment de l'atteinte, réduisez-le
            bingo++;
        }
    }
}

//Tournoi de bingo
public class Bingo {

    public static void main(String[] args) throws Exception {
        //Lisez les données numériques de la carte de bingo et créez une carte de bingo
        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);
        //Lisez la chaîne de chiffres sélectionnée par l'organisateur du tournoi de bingo et réfléchissez-la sur la carte de bingo
        Stream<String> selected = Files.lines(Paths.get("selected.txt"));
        selected.forEach(number -> card.selected(Integer.parseInt(number)));
        //Afficher le statut de la carte de bingo
        System.out.println("BINGO:" + card.bingo + "\nREACH:" + card.reach);
    }
}

Fichier d'entrée

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

Recommended Posts

Nous avons remanié le "Bingo Judgment Program"
Programme de jugement de bingo
Nous avons extrait les meilleurs plastiques de Dockerfile!
Jugement du calendrier