파이썬 실전/로또 번호 생성기

파이썬 실전) 로또 번호 생성기 7. 생성 번호 저장

마리사라 2021. 2. 23. 20:01
반응형

이번 강의는 로또 번호 생성기의 마지막인 만들어진 번호를 저장하는 기능을 만들어 보겠습니다.

 

결과 프로그램은 exe파일로 만들어서 첨부하도록 하겠습니다.

drive.google.com/file/d/1uJhHX3ofbniPuQEOZhjwe6ibwc7aNm7G/view?usp=sharing

 

lotto_number_generator.exe

 

drive.google.com


1. 코드

이번 강의는 딱히 설명할 부분이 많지 않기 때문에 바로 코드부터 보도록 하겠습니다.

 

우선 저장을 담당할 버튼을 만들어 줍니다.

self.save_button = wx.Button(panel, id=12, label="저장", pos=(5, 310))

 

그 후 저장의 기능을 만들어 줍니다. 저장은 txt 파일이나 Exel파일 아무거나 상관이 없지만, 추가적인 모듈이 필요 없는 txt 파일로 저장하도록 하겠습니다.

def save(self, event):
    with open("lotto_number.txt", "w") as f:
        for i in range(self.output.GetCount()):
            f.write(self.output.GetString(i) + "\n")
    dlg = wx.MessageDialog(self, '저장 완료', '저장', wx.OK | wx.ICON_INFORMATION)
    dlg.ShowModal()
    dlg.Destroy()

저장을 할 때에는 가급적 open을 단독으로 사용하지 마시고, with로 하시는게 좋습니다. open을 단독으로 사용하시면 사용하시고 반드시 close를 해주어야 하지만, with를 이용하면 그러한 번거로움을 줄여줍니다.

 

저장하는 방식은 ListBox의 데이터를 읽어서 한줄씩 txt 파일에 추가하는 방식입니다. GetCount로 ListBox의 원소가 몇 개가 있는지 얻어오고, GetString으로 ListBox의 해당 문자열을 읽어옵니다. 이것을 for문으로 반복해서 모든 원소를 저장하게 됩니다. 이때 줄 바꿈 문자(\n)를 뒤에 추가해 주지 않으면 한 줄에 모두 입력되게 되니 추가하시는 것을 권장합니다.

 

마지막으로 저장이 되었음을 알리기 위해 MessageDialog를 사용하여 저장 완료를 표시하면 끝입니다.

 

이제 결과를 확인해 보겠습니다.

저장 버튼 클릭
txt 파일 위치
txt 파일 내용

저장이 정상적으로 된 것을 볼 수 있습니다.


2. 최종 결과물

이제 최종적인 결과입니다.

 

메인 화면

기본적으로 이전회차 당첨번호를 볼 수 있습니다. 이것으로 고정수를 정할 때 참고하실 수 있습니다.

 

조건 없이 3회 시행

모든 시행은 독립적이며, 1부터 45의 숫자를 동일한 확률로 뽑아냅니다.

 

고정수를 조건으로 3회 시행

고정수가 선택되면 선택된 고정수를 반드시 넣어서 시행합니다. 고정수는 중복 허용 개수를 무시할 수 있습니다. 위 예시에서 이전 회차에 2와 12가 있지만, 고정수는 이를 무시하고 넣습니다. 또한 고정수 모드는 연속수 제거 모드를 무시하고 반드시 고정수를 넣습니다.

 

연속수 제거 모드로 3회 시행

연속수 제거 모드가 활성화 되면 2개 이상의 어떠한 연속 수도 허용하지 않습니다.

 

중복 허용 갯수를 6개로 하고 10회 시행

중복 허용 갯수에 따라 이전 회차와 중복되는 당첨번호의 개수가 많이 생깁니다. 중복 허용 개수를 6으로 설정하면 이전 회차와 똑같은 번호가 나올 수 도 있습니다.


3. 마치며

총 7번에 걸쳐 로또 번호 생성기를 만들어 보았습니다. 이를 통해 로또 번호를 알려준다는 사이트는 모두 허구임을 알고 굳이 돈을 쓰지 않고 이러한 생성기로 대리 만족을 하셨으면 합니다. 감사합니다.

import random
import wx
import requests
from bs4 import BeautifulSoup


class Mainframe(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(300, 450))
        panel = wx.Panel(self)
        self.count = wx.TextCtrl(panel, id=1, pos=(5, 40))
        self.count.SetHint("시행 횟수 입력")
        self.generate_button = wx.Button(panel, id=2, label='생성', pos=(5, 70))
        self.output = wx.ListBox(panel, id=3, choices=[], pos=(130, 5), size=(150, 400))

        fixed_number_box = wx.StaticBox(panel, id=5, label="고정수", pos=(5, 100), size=(80, 50))
        self.fixed_number_1 = wx.TextCtrl(fixed_number_box, id=6, size=(30, 20), pos=(5, 20))
        self.fixed_number_2 = wx.TextCtrl(fixed_number_box, id=7, size=(30, 20), pos=(40, 20))
        self.fixed_number_check = wx.CheckBox(panel, id=8, pos=(100, 120))

        self.consecutive_number = wx.CheckBox(panel, id=9, pos=(10, 160), label="연속수 제거")

        self.previous_number = self.extractor()
        previous_number_text = wx.StaticText(panel, id=10, label='이전회차 당첨번호\n' + str(self.previous_number), pos=(5, 5))

        self.duplicates_list = ['0', '1', '2', '3', '4', '5', '6']
        self.duplicates = wx.RadioBox(panel, id=11, label="중복 허용 갯수", pos=(5, 200), size=wx.DefaultSize, choices=self.duplicates_list, majorDimension=3, style=wx.RA_SPECIFY_COLS)

        self.save_button = wx.Button(panel, id=12, label="저장", pos=(5, 310))

        self.Bind(wx.EVT_BUTTON, self.lotto, id=2)
        self.Bind(wx.EVT_BUTTON, self.save, id=12)

    def lotto(self, event):
        for i in range(int(self.count.GetValue())):
            number = set()
            if self.fixed_number_check.GetValue():
                number = self.fixed_number(number)
            while len(number) < 6:
                number.add(random.randint(1, 45))
                if len(number) == 6:
                    intersection = number & set(self.previous_number)
                    if len(intersection) > self.duplicates.GetSelection():
                        number.remove(list(intersection)[0])
                    number = list(number)
                    number.sort()
                    if self.consecutive_number.GetValue():
                        for j in range(len(number) - 1):
                            try:
                                if number[j] + 1 == number[j + 1]:
                                    del number[j + 1]
                            except:
                                pass
                    if not len(number) == 6:
                        number = set(number)
                        if self.fixed_number_check.GetValue():
                            number = self.fixed_number(number)
                        if len(number) == 6:
                            number = list(number)
                            number.sort()
            self.output.Append(str(number))

    def save(self, event):
        with open("lotto_number.txt", "w") as f:
            for i in range(self.output.GetCount()):
                f.write(self.output.GetString(i) + "\n")
        dlg = wx.MessageDialog(self, '저장 완료', '저장', wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def fixed_number(self, number):
        try:
            fixed_number_1 = int(self.fixed_number_1.GetValue())
            number.add(fixed_number_1)
        except:
            pass
        try:
            fixed_number_2 = int(self.fixed_number_2.GetValue())
            number.add(fixed_number_2)
        except:
            pass
        return number

    def extractor(self):
        url = "https://dhlottery.co.kr/common.do?method=main"
        query = requests.get(url=url)
        soup = BeautifulSoup(query.content, "html.parser")
        no_1 = soup.find("span", {"id": "drwtNo1"})
        no_2 = soup.find("span", {"id": "drwtNo2"})
        no_3 = soup.find("span", {"id": "drwtNo3"})
        no_4 = soup.find("span", {"id": "drwtNo4"})
        no_5 = soup.find("span", {"id": "drwtNo5"})
        no_6 = soup.find("span", {"id": "drwtNo6"})
        extract_number = [int(no_1.get_text()), int(no_2.get_text()), int(no_3.get_text()), int(no_4.get_text()),
                          int(no_5.get_text()), int(no_6.get_text())]
        return extract_number


def run():
    app = wx.App()
    frame = Mainframe(None, -1, 'Lotto Number Generator')
    frame.Show()
    app.MainLoop()


run()
반응형