파이썬 스도쿠 생성기 로직과 스도쿠 PDF 생성하기
스도쿠는 전 세계적으로 사랑받는 퍼즐 게임입니다. 이 게임의 목표는 9×9 그리드를 숫자 1부터 9까지로 채우는 것인데, 각 숫자는 각 행, 열, 그리고 3×3 서브그리드마다 한 번씩만 나타나야 합니다. 이번 글에서는 파이썬을 사용하여 스도쿠 생성기의 로직을 어떻게 짤 수 있는지 설명해드리고 pdf 출력 방법까지 알려드리겠습니다.
스도쿠 생성기의 기본 원리
스도쿠 생성기는 무작위성과 규칙을 따르는 알고리즘을 기반으로 합니다. 기본적으로, 생성기는 먼저 완전한 스도쿠 보드를 생성한 다음, 여러 개의 숫자를 제거하여 플레이어가 풀 수 있는 퍼즐을 만듭니다.
파이썬으로 스도쿠 생성기 만들기
파이썬은 스도쿠 생성기를 만들기에 이상적인 언어입니다. 그 이유는 파이썬의 간결성과 라이브러리 생태계가 풍부하기 때문입니다. 먼저 다차원 배열을 쉽게 처리할 수 있는 라이브러리인 numpy를 설치하겠습니다.
import numpy as np
스도쿠 보드 생성
스도쿠 보드를 생성하는 첫 단계는 9×9 그리드를 초기화하는 것입니다. 이를 위해 numpy
라이브러리의 array
기능을 사용할 수 있습니다.
# 9x9 그리드 초기화
grid = np.zeros((9,9), dtype=int)
숫자 배치 알고리즘
스도쿠 보드에 숫자를 배치하는 것은 까다로운 작업입니다. 각 행, 열, 그리고 서브그리드에 중복 없이 숫자를 배치해야 합니다. 이를 위해 백트래킹 알고리즘을 사용할 수 있습니다.
백트래킹이란 되추적이라고도 하며, 가능한 모든 방법을 시도해보는 알고리즘입니다.
스도쿠에서는 각 칸에 들어갈 수 있는 숫자를 하나씩 넣어보고, 규칙에 맞지 않으면 이전 단계로 돌아가 다른 숫자를 시도하는 방식으로 작동합니다.
# 백트래킹을 이용한 숫자 배치
def is_valid(grid, row, col, num):
# 행, 열, 서브그리드 검사
for x in range(9):
if grid[row][x] == num or grid[x][col] == num:
return False
startRow = row - row % 3
startCol = col - col % 3
for i in range(3):
for j in range(3):
if grid[i + startRow][j + startCol] == num:
return False
return True
def solve_sudoku(grid, row, col):
if row == 8 and col == 9:
return True
if col == 9:
row += 1
col = 0
if grid[row][col] > 0:
return solve_sudoku(grid, row, col + 1)
for num in range(1, 10):
if is_valid(grid, row, col, num):
grid[row][col] = num
if solve_sudoku(grid, row, col + 1):
return True
grid[row][col] = 0
return False
퍼즐 생성
완전한 스도쿠 보드에서 숫자를 제거하여 퍼즐을 생성합니다. 이 과정은 무작위성을 가지고 있어야 하며, 퍼즐이 유일한 해답을 가져야 합니다.
# 숫자 제거하여 퍼즐 생성
def remove_numbers(grid, count):
while count > 0:
row = np.random.randint(0,9)
col = np.random.randint(0,9)
while grid[row][col] == 0:
row = np.random.randint(0,9)
col = np.random.randint(0,9)
backup = grid[row][col]
grid[row][col] = 0
grid_copy = grid.copy()
if not solve_sudoku(grid_copy, 0, 0):
grid[row][col] = backup
continue
count -= 1
PDF 파일 생성
스도쿠 보드를 PDF 파일로 생성하기 위해서는 reportlab
라이브러리를 사용할 수 있습니다. 이 라이브러리를 통해 파이썬에서 PDF 문서를 생성하고, 스도쿠 보드를 그릴 수 있습니다.
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
# 스도쿠 보드를 그리는 함수
def draw_sudoku_board(c):
c.setStrokeColorRGB(0, 0, 0)
c.setLineWidth(1)
# 외곽선 그리기
c.rect(0.5*inch, 0.5*inch, 4.5*inch, 4.5*inch, stroke=1, fill=0)
# 내부 그리드 그리기
for i in range(1, 9):
line_width = 1 if i % 3 == 0 else 0.5
c.setLineWidth(line_width)
c.line(0.5*inch, (0.5 + i*0.5)*inch, 5*inch, (0.5 + i*0.5)*inch)
c.line((0.5 + i*0.5)*inch, 0.5*inch, (0.5 + i*0.5)*inch, 5*inch)
# 스도쿠 보드에 숫자를 채우는 함수
def fill_sudoku_numbers(c, grid):
c.setFont("Helvetica", 8)
for row in range(9):
for col in range(9):
if grid[row][col] != 0:
c.drawString((0.7 + col*0.5)*inch, (4.8 - row*0.5)*inch, str(grid[row][col]))
# 스도쿠 PDF 파일을 생성하는 함수
def create_sudoku_pdf(grid, filename="sudoku_puzzle.pdf"):
c = canvas.Canvas(filename, pagesize=letter)
c.setTitle("스도쿠 퍼즐")
draw_sudoku_board(c)
fill_sudoku_numbers(c, grid)
c.save()
위에서 만든 함수들을 실행하려면 아래 코드를 써주시면 됩니다.
# 빈 스도쿠 퍼즐 생성
grid = np.zeros((9, 9), dtype=int)
solve_sudoku(grid, 0, 0)
remove_numbers(grid, 40)
# 스도쿠 퍼즐 출력
print(grid)
create_sudoku_pdf(grid)
출력 결과:
[[1 0 3 4 0 0 0 8 0]
[4 5 6 7 0 0 1 0 0]
[7 0 9 0 0 3 4 5 6]
[2 1 0 0 0 5 0 0 7]
[0 6 0 8 0 7 0 1 0]
[0 9 0 2 1 4 0 6 5]
[0 0 0 0 4 2 9 0 0]
[0 0 0 0 7 8 5 3 0]
[9 0 8 5 0 0 0 4 2]]
위 결과에 써있는 것처럼 sudoku_puzzle.pdf 파일이 생성되고 안에 숫자들이 잘 들어가 있는 것을 볼 수 있습니다.
마무리
이번에는 파이썬을 사용하여 스도쿠 생성기를 만드는 방법에 대해 알려드렸습니다. 이 로직을 기반으로 PDF 출력 디자인도 다듬어서 나만의 스도쿠 생성기를 만들어 보세요.