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/