본문 바로가기
개발자의 일상/개발

[Python]Lotto 번호 생성기 만들기-1

by 아니집사 2021. 9. 1.

파이썬을 이용해 로또번호생성기를 만들어보자.

기획의도
- 단순 난수생성기(.random)이 아닌 내가 원하는 알고리즘에 대한 가중치를 두어 번호를 생성하도록 한다.
- 화면을 만들어 콘솔 화면이 아닌 창에서 확인할 수 있도록 한다.
- 실행프로그램(.exe)으로 만들어 파일을 가진 누구나 실행을 할 수 있도록 한다.

동작방식
- 화면상의 버튼을 클릭하면 메세지박스로 로또번호 6개를 생성한다.
- 로또번호는 생성될 때 랜덤으로 생성되도록 한다.
- 랜덤으로 생성되는 숫자는 이전에 당첨번호들에 영향을 줄 수 있는 가중치를 부여한다

주의사항
- 난수 생성시 중복되는 숫자가 발생하지 않도록 처리한다.

가중치
- 이전에 당첨된 번호는 다음 당첨번호와 관계가 있다.

cf.
기본적으로 로또번호 중 '1' 이라는 숫자가 나올 가능성은 1/45이며 다음으로 '2'에 대한 확률은 1/44가 된다.
여기에서 '1'과 '2'를 다른 숫자로 바꾸더라도 확률은 변하지 않는다. 뭐 독립시행이라 하는데,
근데 로또 당첨 숫자들을 보면 유독 당첨 번호에 잘나오는 숫자들이 보이기도 하고, 마치 패턴이 있는 것 처럼 연속되는 정보들이 가끔씩은 보이는 것도 같다. (본인 피셜)
그래서 이번 로또번호 생성기에서의 가중치 설정은
1회차 당첨번호가 [10,23,29,33,37,40] 이고 2회차가 [9,13,21,25,32,42,2] 라면 1회차의 당첨번호가 나왔을 때 2회차의 당첨번호들이 다음에 나올 가능성이 높다. 라는 가정하에 가중치 비율을 추가하는 방식으로 로또생성기를 만들고자 한다.




======
해당 당첨번호를 정리하여 1회차에서부터 978회차(08.28)까지 당첨번호를
board = ([10,23,29,33,37,40,16],[9,13,21,25,32,42,2],[11,16,19,21,27,31,30],...,[2,9,10,14,22,44,16], [1,7,15,32,34,42,8])
로 선언하여 관리한다.
이부분은 개인적 취향에 따라 메모장이나 엑셀로 저장한 뒤 fopen 또는 selenium을 이용하여 읽어와도 무방하다.

그러고 난 뒤 가중취를 저장할
45*45 사이즈의 배열을 할당하고
gravity = [[0] * 45 for _ in range(45)]

마지막 당첨번호의 각 당첨번호를 변수에 할당한다.
destiny_num1 = board[len(board)-1][0]
destiny_num2 = board[len(board)-1][1]
destiny_num3 = board[len(board)-1][2]
destiny_num4 = board[len(board)-1][3]
destiny_num5 = board[len(board)-1][4]
destiny_num6 = board[len(board)-1][5]

여기까지가 완료가 되면
각 당첨번호들에 대한 가중치 적용을 위해

numpy를 이용하여 각 당첨번호들을 재할당한 뒤,
마지막 당첨번호의 당첨 위치를 확인하고 select_num에 저장한다.
board = numpy.array(board)
select_num = numpy.where(board == destiny_num1)[0]

그다음은 2중 for문을 이용하여 당첨번호(1)가 동일하게 존재하는 회차를 찾고 그 다음에 당첨번호(2)를 확인하여
가중치 배열에 해당 당첨번호(2)에 대해 가중치(2) 를 부여한다.
이 때 가중치는 조율 가능하다(가중치 값에 따라 영향도를 크게 혹은 작게 줄일 수 있다).

for i in range(7):
for j in range(len(select_num)):
if len(board) - (select_num[j]+1) > 0 :
gravity[destiny_num1-1][(board[select_num[j]+1][i])-1] += 2
else :
continue

이와 같은 작업을 당첨번호 7개(보너스 포함)에 대해 모두 동일하게 진행을 한다.

그리고 난수생성기(.random)을 이용하여 당첨번호를 생성한다.
이때 앞서 생성한 가중치를 부여한다.

함수를 생성하는데,
random.choices("범위", "가중치")를 이용하면 가중치를 부여할 수 있는데
범위와 가중치를 1대1로 대응시키면 된다.
또한 생성된 숫자가 앞서 생성된 숫자 들 중 중복값은 없는지 확인 후
중복생성된 경우 중복이 아닐 때까지 while문을 이용하여 재생성 시킨다.
이후 생성된 숫자를 .sort() 이용하여 정렬시키고 반환한다.

def 함수명():
bunholist=[]
for i in range(1):
a = random.choices("로또번호 1- 45",gravity[destiny_num1-1])
bunholist.append(a)

...중략(반복)


a = random.choices("로또번호 1- 45",gravity[destiny_num6-1])
while a in bunholist:
a = random.choices("로또번호 1- 45",gravity[destiny_num6-1])
bunholist.append(a)

bunholist.sort()
return bunholist

여기까지 진행하면 번호를 생성하는데는 아무 문제가 없다.
앞서 생성한 함수만 실행하면 번호가 생성될 것이다.
사용성을 좀더 쉽게 하기 위해

창을 생성한다. 창은 tk를 이용하여 생성한다.
창 크기를 설정하고 탭을 생성한다(해당 탭을 이용해 추가 기능들을 부여가 가능해질 수 있기 때문에 확장성을 고려하여 탭 안에 생성)
탭의 이름을 정하고 메뉴도 만들어 간단하게 종료버튼과 버전정보 확인 메뉴를 생성한다.

root = tk.Tk()
root.title("Decoder")
notebook=tkinter.ttk.Notebook(root, width=200, height=200)
notebook.pack()
tab1=tkinter.Frame(root)
notebook.add(tab1, text=" Lotto ")
menubar = tk.Menu(root)

def close():
root.quit()
root.destroy()

def func_open() :
messagebox.showinfo("버전", "20210901_0.1v")

filemenu = tk.Menu(menubar)
filemenu.add_command(label="exit", command=close)
menubar.add_cascade(label="File", menu=filemenu)

filemenu2 = tk.Menu(menubar)
filemenu2.add_command(label="info", command=func_open)
menubar.add_cascade(label="help", menu=filemenu2)

root.config(menu=menubar)

이후,
탭 내에 버튼을 생성하여 버튼 클릭시 로또생성 함수를 동작하도록 설정한다.
이 때 로또번호의 값을 메세지 박스로 띄우도록 한다.

def getTextInput():
messagebox.showinfo("당첨번호", 함수명())

btnRead=tk.Button(tab1, height=2, width=20, text="생성", command=getTextInput)
btnRead.place(x=30, y=60)

여기 까지 완료가 되었다면 메세지박스를 통해서 로또번호가 생성되는 것을 확인 할 수 있을 것이다.
이 후에는 #pyinstaller를 이용하여 실행파일로 생성만 하면 끝.

 

 

======전체 소스 코드======

import numpy
import random
import tkinter as tk
from tkinter import Menu
import tkinter.ttk
from tkinter import messagebox

root = tk.Tk()
root.title("Decoder")
notebook=tkinter.ttk.Notebook(root, width=200, height=200)
notebook.pack()
basic = 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,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45

tab1=tkinter.Frame(root)
notebook.add(tab1, text=" Lotto ")

menubar = tk.Menu(root)

def close():
    root.quit()
    root.destroy()

def func_open() :    
    messagebox.showinfo("버전", "20210831_0.1v")


filemenu = tk.Menu(menubar)
filemenu.add_command(label="exit", command=close)
menubar.add_cascade(label="File", menu=filemenu)
filemenu2 = tk.Menu(menubar)
filemenu2.add_command(label="info", command=func_open)
menubar.add_cascade(label="help", menu=filemenu2)
root.config(menu=menubar)
gravity = [[0] * 45 for _ in range(45)]
board = [[0] * 7 for _ in range(10000)]


board = ([10,23,29,33,37,40,16],...(이부분은 너무 길어 중략....) [1,7,15,32,34,42,8])

destiny_num = [board[len(board)-1][0],board[len(board)-1][1],board[len(board)-1][2],board[len(board)-1][3],board[len(board)-1][4],board[len(board)-1][5]]
board = numpy.array(board)

for t in range(6):
    select_num = numpy.where(board == destiny_num[t])[0]    
    for i in range(7):
        for j in range(len(select_num)):
            if len(board) - (select_num[j]+1) > 0 :            
                gravity[destiny_num[t]-1][(board[select_num[j]+1][i])-1] += 100            
            else :
                continue

def qordjr():
    alist=[]     
    for i in range(6):                    
        a = random.choices(basic,gravity[destiny_num[i]-1])
        while a in alist :
            a = random.choices(basic,gravity[destiny_num[i]-1])        
        alist.append(a)       
    alist.sort()  
    return alist

def getTextInput():    
    messagebox.showinfo("당첨번호", qordjr())    

btnRead=tk.Button(tab1, height=2, width=20, text="생성", command=getTextInput)
btnRead.place(x=30, y=60)

 

=====================

 



.마치며
현재 로또번호 생성기는 매회차 당첨번호를 소스코드에 수동으로 추가해야 하는 불편함이 존재하기 때문에 사용성이 떨어진다. 이 후에 로또생성기2에서는 크롤러를 이용하여 매회차 당첨번호를 자동으로 저장하고 가중치 외에 추가적인 요소를 추가해보도록 하겠다.

'개발자의 일상 > 개발' 카테고리의 다른 글

css background-image 가운데 정렬  (0) 2021.08.20
.getElementsByClassName  (0) 2021.08.16

댓글