Python PyGame Kütüphanesi İle Sudoku Oyunu Yapımı
Pygame Oyun Örneklerine bir yenisini ekliyoruz. Daha önce pygame oyun örneği paylaşmıştık. Python ile oyun yapmak isteyenlerin bir numaralı kütüphanesi pygame ile ilginç bir GUI uygulamasına geliyoruz. Temel olarak, pygame bir python modülüdür ve onu python kodumuza aktardıktan sonra ondan birkaç oyun yapabiliriz. Aşağıda, ünlü Sudoku oyununu Python ile arayüzü olacak biçimde geliştiriyoruz.
Bu yazımızda ana amacımız arayüzü olan basit bir sudoku oyunu geliştirmek olacaktır. Daha önce Python kullanarak Sudoku oyununu otomatik olarak çözebilen farklı algoritmaları yazmıştık. Bu projeyi önceki yazımızdaki ile birleştirerek herhangi bir sudoku oyununu kendi kendine çözebilen bir uygulama geliştirebilirsiniz. Hatta yine sitemizde yer verdiğimiz OpenCv derslerini de kontrol ederek görüntü işleme teknolojilerinide kullanan bir sudoku çözme uygulaması geliştirilebilir.
Şimdi oyunumuzu yapmaya başlayalım.
İçerik Tablosu
Pygame Oyun Örnekleri
Adım 1: Gerekli Kütüphaneleri Yükleme
Sudoku oyunumuzu geliştirmek için ilk olarak pygame kütüphanesini sistemimize yüklememiz gerekiyor. Bunun için
pip install pygame
komutlarını komut satırına yazmamız yeterli olacaktır. Bu sayede pygame kütüphanesini yükledik.

Adım 2: Gerekli kütüphaneleri dahil etme
Pyhton ile geliştirdiğimiz sudoku oyunumuz için önceki adımda yüklediğimiz pygame ve time kütüphanelerini projemize dahil etmemiz gerekiyor.
import time
Adım 3. Sudoku Problemini Belirleme
Oyunu mümkün olduğunca basit tutmak adına oyun ilk açıldığında kullanıcıya gösterilecek problemi biz belirliyoruz. İstenirse problemler bir dosyada hazırlanılıp rasgele birinin gelmesi istenebilir. Hatta python ile rasgele bir sudoku problemi hazırlanması istenebilir.
class Sudoku:
board = [
[7, 8, 0, 4, 0, 0, 1, 2, 0],
[6, 0, 0, 0, 7, 5, 0, 0, 9],
[0, 0, 0, 6, 0, 1, 0, 7, 8],
[0, 0, 7, 0, 4, 0, 2, 6, 0],
[0, 0, 1, 0, 5, 0, 9, 3, 0],
[9, 0, 4, 0, 6, 0, 0, 0, 5],
[0, 7, 0, 3, 0, 0, 0, 1, 2],
[1, 2, 0, 0, 0, 7, 4, 0, 0],
[0, 4, 9, 2, 0, 6, 0, 0, 7]
]
Adım 4. Kodları Analiz Edelim
Kodlarımızı adım adım analiz edecek olursak
- İlk Olarak kullanacağımız fonksiyonlara bakalım :
- init: Satır, sütun, yükseklik, genişlik vb. girmek için
- update_model: Satır ve sütunu güncellemek için
- place: Satır ve sütunun değerini yerleştirmek için
- sketch
- draw
- select
- clear
- click
- is_finished
- solved
- slove_gui
- draw_change
- set
- set_temp
- find_empty
- valid
- redraw_window
- format_time
- play_time
- Kullandığımız Classlar ise
- Sudoku
- Cube
Adım 5: Kodların Tamamı:
import pygame
import time
pygame.font.init()
class Sudoku:
board = [
[7, 8, 0, 4, 0, 0, 1, 2, 0],
[6, 0, 0, 0, 7, 5, 0, 0, 9],
[0, 0, 0, 6, 0, 1, 0, 7, 8],
[0, 0, 7, 0, 4, 0, 2, 6, 0],
[0, 0, 1, 0, 5, 0, 9, 3, 0],
[9, 0, 4, 0, 6, 0, 0, 0, 5],
[0, 7, 0, 3, 0, 0, 0, 1, 2],
[1, 2, 0, 0, 0, 7, 4, 0, 0],
[0, 4, 9, 2, 0, 6, 0, 0, 7]
]
def __init__(self, rows, cols, width, height, win):
self.rows = rows
self.cols = cols
self.cubes = [[Cube(self.board[i][j], i, j, width, height) for j in range(cols)] for i in range(rows)]
self.width = width
self.height = height
self.model = None
self.update_model()
self.selected = None
self.win = win
def update_model(self):
self.model = [[self.cubes[i][j].value for j in range(self.cols)] for i in range(self.rows)]
def place(self, val):
row, col = self.selected
if self.cubes[row][col].value == 0:
self.cubes[row][col].set(val)
self.update_model()
if valid(self.model, val, (row,col)) and self.solve():
return True
else:
self.cubes[row][col].set(0)
self.cubes[row][col].set_temp(0)
self.update_model()
return False
def sketch(self, val):
row, col = self.selected
self.cubes[row][col].set_temp(val)
def draw(self):
# Draw Grid Lines
gap = self.width / 9
for i in range(self.rows+1):
if i % 3 == 0 and i != 0:
thick = 4
else:
thick = 1
pygame.draw.line(self.win, (0,0,0), (0, i*gap), (self.width, i*gap), thick)
pygame.draw.line(self.win, (0, 0, 0), (i * gap, 0), (i * gap, self.height), thick)
# Draw Cubes
for i in range(self.rows):
for j in range(self.cols):
self.cubes[i][j].draw(self.win)
def select(self, row, col):
# Reset all other
for i in range(self.rows):
for j in range(self.cols):
self.cubes[i][j].selected = False
self.cubes[row][col].selected = True
self.selected = (row, col)
def clear(self):
row, col = self.selected
if self.cubes[row][col].value == 0:
self.cubes[row][col].set_temp(0)
def click(self, pos):
"""
:param: pos
:return: (row, col)
"""
if pos[0] < self.width and pos[1] < self.height:
gap = self.width / 9
x = pos[0] // gap
y = pos[1] // gap
return (int(y),int(x))
else:
return None
def is_finished(self):
for i in range(self.rows):
for j in range(self.cols):
if self.cubes[i][j].value == 0:
return False
return True
def solve(self):
find = find_empty(self.model)
if not find:
return True
else:
row, col = find
for i in range(1, 10):
if valid(self.model, i, (row, col)):
self.model[row][col] = i
if self.solve():
return True
self.model[row][col] = 0
return False
def solve_gui(self):
find = find_empty(self.model)
if not find:
return True
else:
row, col = find
for i in range(1, 10):
if valid(self.model, i, (row, col)):
self.model[row][col] = i
self.cubes[row][col].set(i)
self.cubes[row][col].draw_change(self.win, True)
self.update_model()
pygame.display.update()
pygame.time.delay(100)
if self.solve_gui():
return True
self.model[row][col] = 0
self.cubes[row][col].set(0)
self.update_model()
self.cubes[row][col].draw_change(self.win, False)
pygame.display.update()
pygame.time.delay(100)
return False
class Cube:
rows = 9
cols = 9
def __init__(self, value, row, col, width, height):
self.value = value
self.temp = 0
self.row = row
self.col = col
self.width = width
self.height = height
self.selected = False
def draw(self, win):
fnt = pygame.font.SysFont("comicsans", 40)
gap = self.width / 9
x = self.col * gap
y = self.row * gap
if self.temp != 0 and self.value == 0:
text = fnt.render(str(self.temp), 1, (128,128,128))
win.blit(text, (x+5, y+5))
elif not(self.value == 0):
text = fnt.render(str(self.value), 1, (0, 0, 0))
win.blit(text, (x + (gap/2 - text.get_width()/2), y + (gap/2 - text.get_height()/2)))
if self.selected:
pygame.draw.rect(win, (255,0,0), (x,y, gap ,gap), 3)
def draw_change(self, win, g=True):
fnt = pygame.font.SysFont("comicsans", 40)
gap = self.width / 9
x = self.col * gap
y = self.row * gap
pygame.draw.rect(win, (255, 255, 255), (x, y, gap, gap), 0)
text = fnt.render(str(self.value), 1, (0, 0, 0))
win.blit(text, (x + (gap / 2 - text.get_width() / 2), y + (gap / 2 - text.get_height() / 2)))
if g:
pygame.draw.rect(win, (0, 255, 0), (x, y, gap, gap), 3)
else:
pygame.draw.rect(win, (255, 0, 0), (x, y, gap, gap), 3)
def set(self, val):
self.value = val
def set_temp(self, val):
self.temp = val
def find_empty(bo):
for i in range(len(bo)):
for j in range(len(bo[0])):
if bo[i][j] == 0:
return (i, j) # row, col
return None
def valid(bo, num, pos):
# Check row
for i in range(len(bo[0])):
if bo[pos[0]][i] == num and pos[1] != i:
return False
# Check column
for i in range(len(bo)):
if bo[i][pos[1]] == num and pos[0] != i:
return False
# Check box
box_x = pos[1] // 3
box_y = pos[0] // 3
for i in range(box_y*3, box_y*3 + 3):
for j in range(box_x * 3, box_x*3 + 3):
if bo[i][j] == num and (i,j) != pos:
return False
return True
def redraw_window(win, board, time, strikes):
win.fill((255,255,255))
# Draw time
fnt = pygame.font.SysFont("comicsans", 40)
text = fnt.render("Time: " + format_time(time), 1, (0,0,0))
win.blit(text, (540 - 160, 560))
# Draw Strikes
text = fnt.render("X " * strikes, 1, (255, 0, 0))
win.blit(text, (20, 560))
# Draw grid and board
board.draw()
def format_time(secs):
sec = secs%60
minute = secs//60
hour = minute//60
mat = " " + str(minute) + ":" + str(sec)
return mat
def main():
win = pygame.display.set_mode((540,600))
pygame.display.set_caption("Sudoku")
board = Sudoku(9, 9, 540, 540, win)
key = None
run = True
start = time.time()
strikes = 0
while run:
play_time = round(time.time() - start)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
key = 1
if event.key == pygame.K_2:
key = 2
if event.key == pygame.K_3:
key = 3
if event.key == pygame.K_4:
key = 4
if event.key == pygame.K_5:
key = 5
if event.key == pygame.K_6:
key = 6
if event.key == pygame.K_7:
key = 7
if event.key == pygame.K_8:
key = 8
if event.key == pygame.K_9:
key = 9
if event.key == pygame.K_DELETE:
board.clear()
key = None
if event.key == pygame.K_SPACE:
board.solve_gui()
if event.key == pygame.K_RETURN:
i, j = board.selected
if board.cubes[i][j].temp != 0:
if board.place(board.cubes[i][j].temp):
print("Success")
else:
print("Wrong")
strikes += 1
key = None
if board.is_finished():
print("Game over")
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
clicked = board.click(pos)
if clicked:
board.select(clicked[0], clicked[1])
key = None
if board.selected and key != None:
board.sketch(key)
redraw_window(win, board, play_time, strikes)
pygame.display.update()
main()
pygame.quit()
Artık Sudoku adlı yeni bir GUI penceresinin görünür olduğunu görebilirsiniz. Bunun için her boş alana sayı yazıp girerek bulmacayı çözebilirsiniz. Ayrıca orada bir zamanlayıcı görebilirsiniz ve her yanlış denemeden sonra konsolda yanlış bir ifade görünecektir. Aynı şekilde, her doğru girişim için orada bir doğru ifade olacaktır. En sonunda, bulmacayı çözmek için sadece boşluk tuşuna basın ve Sudoku otomatik olarak doldurulacaktır. En güzel şey, burada sudoku’yu otomatik olarak doldurmak için geri izleme yaklaşımını kullanmamızdır. Geri izleme, algoritmada hesaplamak için en popüler tekniklerden biridir.
Şimdi, burada daha iyi anlamak için videoyu izleyebilirsiniz.
Kaynak: https://iot4beginners.com/five-best-python-projects-for-beginners/