Programming/Practice

Java Swing 가중치 랜덤 복권 번호 생성기 프로젝트 회고

재은초 2024. 5. 20. 15:31
반응형

 

14일 동안 JAVA, JDBC랑 오라클 PL/SQL만을 사용해서 자바 스윙 프로젝트를 만들라는 미션을 받았다

자바로 하는 프로젝트는 처음이라 과연 내가 할 수 있을까 걱정이 많았는데, 언어는 다르지만 이전에 자바스크립트로 프로젝트를 완성했던 경험이 많이 도움이 되었다.

첫 프로젝트 때는 끝내는 것에만 급급했는데 이번 프로젝트는 회고를 한번 해보기로 했다.

 

 

일확천금의 꿈도 없지 않아 있지만, 복권 기금이 소외 계층 복지에 사용된다는 말을 듣고 그때부터 취미삼아 복권을 사기 시작했다.

그래서 매주 복권을 사는데 수학적으로 보자면 숫자가 뽑히는 확률은 동일하겠지만 복권 당첨 숫자들을 보면 또 뽑힌게 또 뽑히는 것 같았다.

그래서 언제 시간되면 기당첨된 복권 번호 기반 가중치 알고리즘을 적용한 로또 복권 번호 생성기를 만들어보고 싶었는데 동료도 좋다 그래서 프로젝트를 실행했다.

 

 

전체적인 레이아웃이나 번호 생성 방법은 동행복권 사이트를 참고해서 만들었다

사실 백엔드 부분은 기본적인 CRUD라 어려운건 없었는데 프론트가 너무 어려웠다

예를 들어 버튼 선택 번호 확인에서 한 줄 삭제하면 그 줄에 다시 새 데이터 들어가게 하거나, 아니면 반자동이랑 수동 버튼 클릭시 저장된 숫자들을 수정할 때 다시 보여주는 기능 등등...

역시 프론트엔드가 쉬운것 같아보여도 할 게 산더미라는걸 다시 한번 깨달았다

 

package com;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import com.dao.LotteryDAO;
import com.dto.LotteryVO;

public class Lottery extends JPanel {
	
	LotteryDAO lotteryDao = new LotteryDAO();
	WeightedRandom weightedRandom = new WeightedRandom();
	
	int userNo;

	private JPanel[] categoryPanels;
    private boolean[] categoryCellStates;
    private int selectedIndex = -1;

    private JPanel[][] numberPanels;
    private int[][] numberCellValues;
    private boolean[][] numberCellStates;
    private ArrayList<Integer> selectedNumbers;
    private ArrayList<Integer> savedNumbers;
    private final int NUMBER_ROWS = 7;
    private final int NUMBER_COLS = 7;
    private final int NUMBER_ARRAY_SIZE = 6;

    private JPanel[][] resultPanels;
    private JLabel[][] resultLabels;
    private final int RESULT_ROWS = 5;
    private final int RESULT_COLS = 3;   
    private boolean allSlotsFilled = true;

    public Lottery(int userNo) {
        setSize(1000, 500);
        setVisible(true);
        
        JPanel mainPanel = new JPanel(new BorderLayout());        

        // 1. 카테고리: 자동, 반자동, 수동
        categoryPanels = new JPanel[3];
        categoryCellStates = new boolean[3];

        JPanel categoryPanel = new JPanel(new GridLayout(1, 3));
        categoryPanel.setPreferredSize(new Dimension(400, 50));
        add(categoryPanel);

        for (int i = 0; i < 3; i++) {
            categoryPanels[i] = new JPanel(new GridBagLayout());
            categoryPanels[i].setBackground(Color.WHITE);
            categoryPanels[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));

            JLabel categoryLabel = new JLabel(getCategoryName(i));
            categoryPanels[i].add(categoryLabel);

            final int index = i;
            categoryPanels[i].addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    toggleCategory(index);
                }
            });
            categoryPanel.add(categoryPanels[i]);
        }

        // 2. 숫자 6자리 입력
        numberPanels = new JPanel[NUMBER_ROWS][NUMBER_COLS];
        numberCellValues = new int[NUMBER_ROWS][NUMBER_COLS];
        numberCellStates = new boolean[NUMBER_ROWS][NUMBER_COLS];
        selectedNumbers = new ArrayList<Integer>();

        JPanel numberPanel = new JPanel(new GridLayout(NUMBER_ROWS, NUMBER_COLS));
        numberPanel.setPreferredSize(new Dimension(400, 400));
        
        int num = 1;
        for (int i = 0; i < NUMBER_ROWS; i++) {
            for (int j = 0; j < NUMBER_COLS; j++) {
                numberPanels[i][j] = new JPanel(new GridBagLayout());
                numberPanels[i][j].setBackground(Color.WHITE);
                numberPanels[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                
                if (num <= 45) {
                    numberCellValues[i][j] = num;
                    JLabel label = new JLabel(String.valueOf(numberCellValues[i][j]));
                    numberPanels[i][j].add(label);
                    
                    final int row = i;
                    final int col = j;
                    
                    numberPanels[i][j].addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseClicked(MouseEvent e) {
                            toggleNumber(row, col);
                        }
                    });
                }
                else {
                    JLabel emptyLabel = new JLabel("");
                    numberPanels[i][j].add(emptyLabel);
                    numberPanels[i][j].setEnabled(false);
                }
                numberPanel.add(numberPanels[i][j]);
                num++;
            }
        }

        // 3. 복권 번호 선택하기
        JPanel confirmPanel = new JPanel(new GridBagLayout());
        confirmPanel.setPreferredSize(new Dimension(400, 50));
        confirmPanel.setOpaque(true);
        confirmPanel.setBackground(Color.WHITE);
        confirmPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

        JLabel confirmLabel = new JLabel("선택하기", SwingConstants.CENTER);
        confirmPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                selectLottery(userNo);
            }
        });
        confirmPanel.add(confirmLabel);

        // 왼쪽 사이드
        JPanel inputPanel = new JPanel(new BorderLayout());
        inputPanel.setPreferredSize(new Dimension(400, 500));
        inputPanel.add(categoryPanel, BorderLayout.NORTH);
        inputPanel.add(numberPanel, BorderLayout.CENTER);
        inputPanel.add(confirmPanel, BorderLayout.SOUTH);

        // ----------------- OUTPUT -----------------
        // 1. 메뉴바
        JPanel menuPanel = new JPanel(new GridLayout(1, 1));
        JLabel menuLabel = new JLabel("선택 번호 확인", SwingConstants.CENTER);
        menuPanel.setPreferredSize(new Dimension(600, 50));
        menuPanel.setBackground(Color.WHITE);
        menuPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        menuPanel.add(menuLabel);

        // 2. 결과 출력
        resultPanels = new JPanel[RESULT_ROWS][RESULT_COLS];
        savedNumbers = new ArrayList<Integer>();

        JPanel resultPanel = new JPanel(new GridLayout(RESULT_ROWS, RESULT_COLS));
        resultPanel.setPreferredSize(new Dimension(600, 400));

        String emptyValue = "";
        resultLabels = new JLabel[RESULT_ROWS][RESULT_COLS];

        for (int i = 0; i < RESULT_ROWS; i++) {
            for (int j = 0; j < RESULT_COLS; j++) {
                resultPanels[i][j] = new JPanel(new GridBagLayout());
                resultPanels[i][j].setBackground(Color.WHITE);
                resultPanels[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));

                resultLabels[i][j] = new JLabel(emptyValue);
                resultPanels[i][j].add(resultLabels[i][j]);

                if (j == 2) {
                    JPanel buttonPanel = new JPanel(new GridLayout(1, 2));

                    int rowIndex = i;

                    // 수정 버튼
                    JLabel modifyLabel = new JLabel("수정", SwingConstants.CENTER);
                    modifyLabel.setPreferredSize(new Dimension(50, 30));
                    modifyLabel.addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseClicked(MouseEvent e) {
                            modifyLottery(rowIndex);
                        }
                    });

                    // 삭제 버튼
                    JLabel deleteLabel = new JLabel("삭제", SwingConstants.CENTER);
                    deleteLabel.setPreferredSize(new Dimension(50, 30));
                    deleteLabel.addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseClicked(MouseEvent e) {
                            deleteLottery(rowIndex);
                        }
                    });

                    buttonPanel.add(modifyLabel);
                    buttonPanel.add(deleteLabel);
                    buttonPanel.setBackground(Color.WHITE);

                    resultPanels[i][j].setLayout(new BorderLayout());
                    resultPanels[i][j].add(buttonPanel, BorderLayout.CENTER);
                }
                resultPanel.add(resultPanels[i][j]);
            }
        }

        // 3. 저장하기
        JPanel registerPanel = new JPanel(new GridBagLayout());
        registerPanel.setPreferredSize(new Dimension(600, 50));
        registerPanel.setOpaque(true);
        registerPanel.setBackground(Color.WHITE);
        registerPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

        JLabel registerLabel = new JLabel("저장하기", SwingConstants.CENTER);
        registerPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                lotteryDao.saveLottery(userNo, saveLottery());
            }
        });
        registerPanel.add(registerLabel);

        // 오른쪽 사이드
        JPanel outputPanel = new JPanel(new BorderLayout());
        outputPanel.setPreferredSize(new Dimension(600, 500));
        outputPanel.add(menuPanel, BorderLayout.NORTH);
        outputPanel.add(resultPanel, BorderLayout.CENTER);
        outputPanel.add(registerPanel, BorderLayout.SOUTH);

        // 메인 배치
        mainPanel.add(inputPanel, BorderLayout.WEST);
        mainPanel.add(outputPanel, BorderLayout.CENTER);
        
        add(mainPanel, BorderLayout.CENTER);
    }
    // ----------------- Methods -----------------
    // 카테고리 선택 효과
    private void toggleCategory(int index) {
        if (selectedIndex != -1) {
            categoryPanels[selectedIndex].setBackground(Color.WHITE);
            categoryPanels[selectedIndex].setForeground(Color.BLACK);
            categoryCellStates[selectedIndex] = false;
        }

        if (selectedIndex == index) {
            selectedIndex = -1;
        } else {
            resetNumbers(); // 다른 카테고리가 선택된 경우 숫자 패널 초기화
            categoryPanels[index].setBackground(Color.GRAY);
            categoryPanels[index].setForeground(Color.WHITE);
            categoryCellStates[index] = true;
            selectedIndex = index;
        }
    }

    // 숫자 선택 효과
    private void toggleNumber(int row, int col) {
        // 6개 이상 선택할 때
        if (selectedNumbers.size() >= NUMBER_ARRAY_SIZE && !numberCellStates[row][col]) {
            return;
        }
        
        // 자동 카테고리가 선택된 경우
        if (selectedIndex == 0) { 
            JOptionPane.showMessageDialog(null, "자동 카테고리에서는 숫자를 선택할 수 없습니다.");
            return;
        // 반자동 카테고리가 선택된 경우
        } else if (selectedIndex == 1 && selectedNumbers.size() >= NUMBER_ARRAY_SIZE - 1 && !numberCellStates[row][col]) { 
        	JOptionPane.showMessageDialog(null, "반자동일 경우 수동 번호는 최대 5개까지 선택 가능합니다");
    		return;
        }
        
        numberCellStates[row][col] = !numberCellStates[row][col];
        Color bg = numberCellStates[row][col] ? Color.GRAY : Color.WHITE;
        Color fg = numberCellStates[row][col] ? Color.RED : Color.BLACK;
        numberPanels[row][col].setBackground(bg);
        numberPanels[row][col].setForeground(fg);

        // 선택 숫자 업데이트
        int value = numberCellValues[row][col];
        if (numberCellStates[row][col]) {
            if (!selectedNumbers.contains(value)) {
                selectedNumbers.add(value);
                savedNumbers.add(value);
            }
        } else {
            selectedNumbers.remove(Integer.valueOf(value));
            savedNumbers.remove(Integer.valueOf(value));
        }
    }

    // 선택 초기화
    private void resetCategory() {
        if (selectedIndex != -1) {
            categoryPanels[selectedIndex].setBackground(Color.WHITE);
            categoryPanels[selectedIndex].setForeground(Color.BLACK);
            categoryCellStates[selectedIndex] = false;
            selectedIndex = -1;
        }
        selectedNumbers.clear();         // 선택된 숫자 리스트 초기화
    }
    
    // 숫자 초기화
    private void resetNumbers() {
        for (int i = 0; i < NUMBER_ROWS; i++) {
            for (int j = 0; j < NUMBER_COLS; j++) {
                numberCellStates[i][j] = false;
                numberPanels[i][j].setBackground(Color.WHITE);
                numberPanels[i][j].setForeground(Color.BLACK);
                numberPanels[i][j].setEnabled(true); // 선택 가능하도록 설정
            }
        }
        selectedNumbers.clear();         // 선택된 숫자 리스트 초기화
    }
    
    // 결과 초기화
    private void resetResults() {
        for (int i = 0; i < RESULT_ROWS; i++) {
        	deleteLottery(i);
        }
    }
    
    // 선택된 카테고리와 숫자 출력
    private void selectLottery(int userNo) {    	
        // 1부터 45까지의 숫자가 담긴 리스트 생성
        ArrayList<Integer> randomNumbers = new ArrayList<>();
        for (int i = 1; i <= 45; i++) {
            randomNumbers.add(i);
        }
        
        // 로그인 유저 체크
    	if (userNo == 0) {
            JOptionPane.showMessageDialog(null, "로그인 사용자만 복권 번호 생성이 가능합니다");
        } else {       	
        	// 카테고리 미선택시
            if (selectedIndex == -1) {
                JOptionPane.showMessageDialog(null, "카테고리를 선택해주세요");
                return;
            }

            // 자동 카테고리: 무작위로 6개의 숫자 선택
            if (selectedIndex == 0) {
            	List<Integer> Weightedrandom = weightedRandom.selectNumbers();
            	System.out.println(Weightedrandom);
            	
            	for (Integer num : Weightedrandom) {
            	    selectedNumbers.add(num);
            	}
                
            // 반자동 카테고리: 선택된 숫자 이외 숫자 자동 선택
            } else if (selectedIndex == 1) {
                int selectedlength = selectedNumbers.size();
                if (selectedlength == 0) {
                    JOptionPane.showMessageDialog(null, "반자동일 경우 수동 번호는 최소 1개는 선택해주세요");
                    return;
                } else {
                    Set<Integer> randomNumbersSet = new HashSet<>();
                    Random random = new Random();
                    for (int i = 0; i < NUMBER_ARRAY_SIZE - selectedlength; i++) {
                        int randomNumber;
                        do {
                            randomNumber = random.nextInt(45) + 1;
                        } while (selectedNumbers.contains(randomNumber) || randomNumbersSet.contains(randomNumber));
                        randomNumbersSet.add(randomNumber);
                    }
                    selectedNumbers.addAll(randomNumbersSet);
                }
            // 수동 카테고리
            } else if (selectedIndex == 2) {
                if (selectedNumbers.size() != NUMBER_ARRAY_SIZE || selectedIndex == -1) {
                    JOptionPane.showMessageDialog(null, "카테고리와 " + NUMBER_ARRAY_SIZE + "개 숫자를 선택해주세요");
                    return;
                }
            }

            Collections.sort(selectedNumbers);

            // 카테고리와 숫자를 맵형식으로 저장
            Map<String, Object> selectionMap = new HashMap<>();
            if (selectedIndex != -1) {
                String selectedCategory = getCategoryName(selectedIndex);
                selectionMap.put("category", selectedCategory);
            }

            selectionMap.put("numbers", selectedNumbers);

            // 비어 있는 행에 결과 입력
            for (int i = 0; i < RESULT_ROWS; i++) {
                if (resultLabels[i][0].getText().isEmpty()) {
                    for (Map.Entry<String, Object> entry : selectionMap.entrySet()) {
                        if (entry.getKey().equals("category")) {
                            resultLabels[i][0].setText(entry.getValue().toString());
                        } else if (entry.getKey().equals("numbers")) {
                            resultLabels[i][1].setText(entry.getValue().toString());
                        }
                    }
                    break;
                }
            }
            
            // 이미 5개의 복권 번호 세트가 존재하면 추가 저장 차단         
            getResultState();

            resetCategory(); // 초기화
            resetNumbers();
            
        }
    }

    private String getCategoryName(int index) {
    	if (index == 0) {
    		return "자동";
    	} else if (index == 1) {
    		return "반자동";
    	} else {
    		return "수동";
    	}
    }
    
    private int[] getSavedNumbers() {
        // 수동으로 선택된 숫자만 배열로 반환
        int[] result = new int[savedNumbers.size()];
        int index = 0;
        for (int num : savedNumbers) {
            result[index++] = num;
        }
        return result;
    }
    
    private void getResultState() {
    	for (int i = 0; i < RESULT_ROWS; i++) {
            if (resultLabels[i][1].getText().isEmpty()) {
                allSlotsFilled = false;
                break;
            }
        }
    	if (allSlotsFilled) {
            JOptionPane.showMessageDialog(null, "복권 번호 생성은 한번에 5개까지 가능합니다");
            return;
        }
    }
    
    private void modifyLottery(int rowIndex) {
    	String category = resultLabels[rowIndex][0].getText();
    	if (category.equals("자동")) {
    		toggleCategory(0);
    	} else if (category.equals("반자동")) {
    		toggleCategory(1);
    	} else if (category.equals("수동")) {
    		toggleCategory(2);
    	}
    	selectedNumbers.clear();
    	
    	for (int i = 0; i < NUMBER_ROWS; i++) {
            for (int j = 0; j < NUMBER_COLS; j++) {
                int value = numberCellValues[i][j];
                if (savedNumbers.contains(value)) {
                    toggleNumber(i, j);
                }
            }
        }
        deleteLottery(rowIndex);
    }
    
    private void deleteLottery(int rowIndex) {
    	if (rowIndex < RESULT_ROWS) { // 인덱스가 범위 내에 있는지 확인
            for (int i = 0; i < 2; i++) {
                resultLabels[rowIndex][i].setText("");
            }
        }
    }
    
    private Map<Integer, Object> saveLottery() {
    	// 카테고리와 숫자를 맵형식으로 저장
    	Map<Integer, Object> lotteryMap = new HashMap<>();
    	
    	for (int i = 0; i < RESULT_ROWS; i++) { // 수정: <= 대신에 <
            String category = resultLabels[i][0].getText();
            String numbers = resultLabels[i][1].getText();

            if (!category.isEmpty()) {
                lotteryMap.put(i + 1, new String[]{category, numbers});
            }
        }
        
        resetResults();
        return lotteryMap;
    }
}

 

1-1118회 당첨 번호 내역: https://www.dhlottery.co.kr/gameResult.do?method=statByNumber

 

복권 구매 방식에는 자동, 반자동, 수동이 있는데, 우리의 목표는 자동에 가중치 알고리즘을 적용하는 것이었다

기본 원리는 당첨 횟수가 높을수록 해당 번호가 선택될 확률을 높이는 것이고, 당첨 횟수 기반으로 가중치를 계산하는데, 가중치는 해당 번호의 당첨 횟수 / 전체 당첨 횟수로 구했다.

예를 들어, 숫자 1번의 가중치 = 당첨 횟수 185회 / 전체 당첨 횟수 7826회 = 0.02364로 숫자 1은 전체 선택의 대략 2.36%의 확률로 선택된다.

 

가중치를 구하는 코드를 작성하는건 어렵지 않았는데, 가중치에 따라 번호 선택을 하는 코드를 구현하는건 많이 막막했다.

다행히 구글링이랑 챗GPT의 도움으로 짰는데, 누적 확률 구간에서 해당 숫자가 선택될 확률을 적용해서 구했다.

사실 통계에 무지랭이라서 이 방법이 맞는지는 잘 모르겠는데, 혹시나 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다.

 

검증의 경우에는 10000번 시뮬레이션 통해 랜덤 선택된 복권 번호 확률을 기존 가중치와 비교해서 비슷한지 확인하는 방법을 선택했다. 신기하게도 확률이 얼추 비슷하게 나왔다.

 

package com;

import java.util.*;

public class WeightedRandom {
	private static final Map<Integer, Integer> lotteryData = initializeLottoData();
    private static final Map<Integer, Double> weights = calculateWeights();
    private static final Random random = new Random();
    private static int number;
    private static double weight;

	// 복권 번호 리스트
    private static Map<Integer, Integer> initializeLottoData() {
        Map<Integer, Integer> lotteryData = new HashMap<>();
        lotteryData.put(1, 185);
        lotteryData.put(2, 174);
        lotteryData.put(3, 180);
        lotteryData.put(4, 182);
        lotteryData.put(5, 162);
        lotteryData.put(6, 177);
        lotteryData.put(7, 179);
        lotteryData.put(8, 163);
        lotteryData.put(9, 141);
        lotteryData.put(10, 176);
        lotteryData.put(11, 176);
        lotteryData.put(12, 190);
        lotteryData.put(13, 186);
        lotteryData.put(14, 182);
        lotteryData.put(15, 172);
        lotteryData.put(16, 177);
        lotteryData.put(17, 187);
        lotteryData.put(18, 183);
        lotteryData.put(19, 170);
        lotteryData.put(20, 182);
        lotteryData.put(21, 173);
        lotteryData.put(22, 148);
        lotteryData.put(23, 154);
        lotteryData.put(24, 178);
        lotteryData.put(25, 156);
        lotteryData.put(26, 180);
        lotteryData.put(27, 187);
        lotteryData.put(28, 156);
        lotteryData.put(29, 155);
        lotteryData.put(30, 171);
        lotteryData.put(31, 177);
        lotteryData.put(32, 162);
        lotteryData.put(33, 187);
        lotteryData.put(34, 191);
        lotteryData.put(35, 174);
        lotteryData.put(36, 175);
        lotteryData.put(37, 177);
        lotteryData.put(38, 178);
        lotteryData.put(39, 177);
        lotteryData.put(40, 180);
        lotteryData.put(41, 154);
        lotteryData.put(42, 167);
        lotteryData.put(43, 192);
        lotteryData.put(44, 174);
        lotteryData.put(45, 179);
        return lotteryData;
    }
    
    // 가중치 계산
    private static Map<Integer, Double> calculateWeights() {
        Map<Integer, Double> weights = new HashMap<>();
        
        // 전체값 계산
        int totalFrequency = 0;
        for (int frequency : lotteryData.values()) {
            totalFrequency += frequency;
        }
        
        // 각 당첨횟수 / 전체값
        for (Map.Entry<Integer, Integer> entry : lotteryData.entrySet()) {
            int number = entry.getKey();
            int frequency = entry.getValue();
            double weight = (double) frequency / totalFrequency;
            weights.put(number, weight);
        }
        return weights;
    }
    
    // 가중치에 따라 번호 선택
    static List<Integer> selectNumbers() {
        Set<Integer> selectedNumbersSet = new HashSet<>();
        
        while (selectedNumbersSet.size() < 6) {
            double randomNumber = random.nextDouble(); // 0부터 1사이의 랜덤한 수 생성
            double cumulativeProbability = 0.0;
            
            // 누적 확률에 따라 번호 선택
            for (Map.Entry<Integer, Double> entry : weights.entrySet()) {
                int number = entry.getKey();
                double weight = entry.getValue();
                
                cumulativeProbability += weight;
                if (randomNumber <= cumulativeProbability) {
                    selectedNumbersSet.add(number);
                    break;
                }
            }
        }
        
        // Set을 List로 변환하여 반환
        return new ArrayList<>(selectedNumbersSet);
    }

// // 검증 코드
//    public static void main(String[] args) {
//        // 결과를 저장할 맵 초기화
//        Map<Integer, Integer> numberCounts = new HashMap<>();
//        for (int i = 1; i <= 45; i++) {
//            numberCounts.put(i, 0);
//        }
//
//        // 시뮬레이션 실행
//        int simulations = 10000;
//        for (int i = 0; i < simulations; i++) {
//            List<Integer> selectedNumbers = selectNumbers();
//
//            // 선택된 번호들의 빈도수 증가
//            for (int number : selectedNumbers) {
//                numberCounts.put(number, numberCounts.get(number) + 1);
//            }
//        }
//
//        // 각 숫자의 확률 출력
//        for (Map.Entry<Integer, Integer> entry : numberCounts.entrySet()) {
//            int number = entry.getKey();
//            int count = entry.getValue();
//            double probability = (double) count / (simulations * 6); // 6은 복권에서 선택되는 번호의 개수
////            System.out.println(number + " " + probability);
//            System.out.println(probability);
//        }
//    }
}

 

 

그리고 대망의 당첨 후기!!!!

테스트하면서 그냥 자바 랜덤 번호 뽑아서 복권을 샀는데 5만원이 당첨됬다!!!!!

사실 가중치 알고리즘 적용한 것도 아니고 걍 무작위 랜덤이었는데 저게 당첨될 줄은 꿈에도 상상못함 ㅎㅎ 신기하다

 

자세한 코드가 필요하신 분들은 아래 깃허브 소스를 참조하시면 된다

https://github.com/iamjaeeuncho/LotteryProject

 

GitHub - iamjaeeuncho/LotteryProject

Contribute to iamjaeeuncho/LotteryProject development by creating an account on GitHub.

github.com

 

반응형