쉬는시간에 시간 애껴서 만들었음… 아니 근데 솔직히 재밌어보이지 않습니까?
import numpy as np
import random
일단 이거 돌리려면 넘파이가 설치되어 있어야 한다. 일단 개발은 3.10에서 하긴 했는데 뭐 버전타는건 없겠지… 있으면 큰일난다… 나 3.10에서만 돌려봄…
# OOP 서타일은 클래스에서 시작이여
class Bingo:
# 기본값은 5*5(기본 범위는 25)
def __init__(self, size = 5, n = 25):
self.size = size
self.bingo_max = n
self.bingo_range = range(1, self.bingo_max + 1)
self.board = None
self.number_list = list(self.bingo_range)
# 빙고판 생성
def make_bingo(self):
self.board = np.random.choice(self.bingo_range, size=(self.size, self.size), replace=False)
# 숫자 뽑기
def draw_number(self):
if len(self.number_list) > 0:
bingo_pop = random.choice(self.number_list)
self.number_list.remove(bingo_pop)
return bingo_pop
else:
print('No more draw!')
return None
# 빙고 체크 함수
def isbingo(self, n = 1):
count = 0
# 줄
count += np.sum(np.all(self.board == 0, axis=1))
count += np.sum(np.all(self.board == 0, axis=0))
count += np.all(np.diag(self.board) == 0) # 대각선(좌상-우하)
count += np.all(np.diag(np.fliplr(self.board)) == 0) # 대각선(우상-좌하)
# 빙고가 됐어?
return count >= n
# 마킹
def marking(self, jebi):
if jebi in self.board:
self.board[self.board == jebi] = 0
return True
return False
# 출력 관련임다. 깔끔하게 뽑을라고...
def print_board(self):
for row in self.board:
print(" ".join(f"{num:2}" for num in row))
print("+-----------------------+")
OOP 서타일의 완성은 모든걸 다 클래스에 때려박아서 각 역할별로 각 메소드가 책임지게 만드는 것이다. 물론 처음에는 클래스 없이 절차지향으로 했던거 저기다가 다 때려박는 정말 개같은 난이도가 날 기다리고 있었지만… 그래서 쟤들이 빙고를 할 때 필요한 것들을 다 할 거다.
# 기본값은 5*5(기본 범위는 25)
def __init__(self, size = 5, n = 25):
self.size = size
self.bingo_max = n
self.bingo_range = range(1, self.bingo_max + 1)
self.board = None
self.number_list = list(self.bingo_range)
생성자다. 여기서는 빙고의 크기와 빙고게임 숫자 범위(1부터 n까지)를 정하고 보드와 뽑기통을 만든다.
# 빙고판 생성
def make_bingo(self):
self.board = np.random.choice(self.bingo_range, size=(self.size, self.size), replace=False)
# 숫자 뽑기
def draw_number(self):
if len(self.number_list) > 0:
bingo_pop = random.choice(self.number_list)
self.number_list.remove(bingo_pop)
return bingo_pop
else:
print('No more draw!')
return None
이건 간단하니까 두개 같이 설명드림. 위에껀 생성자에서 받은 숫자 범위로 빙고판을 만드는거고(1부터 50까지를 입력하면 1부터 50까지 중에서 랜덤으로 숫자를 뽑아 n*n 정사각형 배열에 들어갈 빙고판을 만든다), 아래는 위에 만들어진 뽑기통에서 숫자를 뽑는거다.
# 빙고 체크 함수
def isbingo(self, n = 1):
count = 0
# 줄
count += np.sum(np.all(self.board == 0, axis=1))
count += np.sum(np.all(self.board == 0, axis=0))
count += np.all(np.diag(self.board) == 0) # 대각선(좌상-우하)
count += np.all(np.diag(np.fliplr(self.board)) == 0) # 대각선(우상-좌하)
# 빙고가 됐어?
return count >= n
그니까 우리가 마킹하다가 가로세로대각선 한줄 지워지면 빙고잖아요? 그걸 판별하는 메소드다. 근데 diag는 뭐냐고? 주대각선이요. 행렬의 좌상->우하로 가는 대각선이 주대각선이고 밑에건 거꾸로 뒤집는거다. 플립 들어갔을 때 알아봄.
# 마킹
def marking(self, jebi):
if jebi in self.board:
self.board[self.board == jebi] = 0
return True
return False
마킹하는 애다. 근데 리턴트류 리턴폴스는 왜 있냐고? 보드가 5*5인데 숫자가 1부터 50까지면 보드에 안 들어가는 숫자도 있잖아요? 그럴 때 폴스가 뜬다.
# 출력 관련임다. 깔끔하게 뽑을라고...
def print_board(self):
for row in self.board:
print(" ".join(f"{num:2}" for num in row))
print("+-----------------------+")
얘는 뭐 크게 볼 건 없고 출력 관련이다. 아니 이게 언패킹을 했더니 개같이 안이쁜거야... 그렇다고 []를 뗄 수는 없잖아요... 그런거임. 저것도 숫자 3~4자리 되면 num 뒤에 숫자 바꿔야 할 수도 있음. 아니면 범위를 1~99로 제한하던가...
# 빙고 보드 생성
while True:
bingo_num = int(input('Write maximum number: '))
size = 5 # 여기 바꾸시면 빙고 크기 바껴요! (기본 5*5)
try:
if bingo_num < size ** 2:
raise ValueError
else:
game = Bingo(size, bingo_num)
break
except ValueError:
print(f'Out ot range: You have to input number larger than {size ** 2}')
# 목표 설정
while True:
max_line = 2 * size + 2
bingo_line = int(input('How many lines for end game?: '))
try:
if bingo_line >= 1 and bingo_line <= max_line:
break
else:
raise ValueError
except ValueError:
print(f'Out ot range: You have to input number between 1 and {max_line}')
보드 생성하고 목표 설정에는 트롤링 방지 장치가 있어서 긴거고 나머지는 심플하다. 숫자 범위의 경우 5*5로 해놓고 범위가 25보다 작으면 넘파이가 이건 뭐 배열을 뭐 어쩌라는겨 하면서 오류를 토함. 그래서 그거 관련으로 준 거고... 그 빙고판의 크기에 따라서 빙고 줄 수 최댓값 있는거 아셨음? 나도 인제 알았음. 가로+세로+대각선 해서 사이즈 * 2 + 2가 최대다. 그리고 0줄은 있을 수 없으니까 1부터 최댓값까지 제한을 거는 것.
# 빙고판 생성
game.make_bingo()
# 몇트째임?
bingo_cnt = 1
# 이 숫자가 빙고판에 있으면 지우고, 없으면 패스.
# 일단 가로세로대각선 1빙고 될 때까지 해봅시다.
while True:
# 랜덤으로 숫자 하나를 뽑는다. (범위는 위에 빙고판 숫자랑 동일)
bingo_jebi = game.draw_number()
# 물론 그럴 일은 없겠지만 리스트 거덜나면 끝납니다.
if bingo_jebi is None:
print("No more draw! Game over.")
break
# 체크(위에 있음)
if game.marking(bingo_jebi):
print(f'{bingo_cnt}: {bingo_jebi} hit! 👏')
else:
print(f'{bingo_cnt}: {bingo_jebi} no hits... 😭')
game.print_board()
# 조건 ㅇㅋ->시마이
bingo_cnt += 1
if game.isbingo(bingo_line):
print(f'🎉Congratulations!')
break
나머지는 판 만들고 몇판째인지 세고 빙고게임 하는게 다임. 뽑기통 거덜나면 끝나는 로직도 넣어두긴 했는데 그 전에 빙고게임이 끝나겠지 지피티야…
'Coding > Python' 카테고리의 다른 글
| 의도와 많이 달라졌지만 Python으로 ARIMA를 해보자 (0) | 2025.12.26 |
|---|---|
| loc, iloc, at, iat (0) | 2025.12.24 |
| 힙 정렬을 구현해보자 (0) | 2025.12.13 |
| BFS, DFS (0) | 2025.12.11 |
| 이중 연결 리스트 (0) | 2025.12.10 |