Python PyGame Kütüphanesi İle Sudoku Oyunu Yapımı

0 2.066

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.

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.

python pygames yükleme
python pygames yükleme

 

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 pygame
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

  1. İlk Olarak kullanacağımız fonksiyonlara bakalım :
    1. init: Satır, sütun, yükseklik, genişlik vb. girmek için
    2. update_model: Satır ve sütunu güncellemek için
    3. place: Satır ve sütunun değerini yerleştirmek için
    4. sketch
    5. draw
    6. select
    7. clear
    8. click
    9. is_finished
    10. solved
    11. slove_gui
    12. draw_change
    13. set
    14. set_temp
    15. find_empty
    16. valid
    17. redraw_window
    18. format_time
    19. play_time
  2. Kullandığımız Classlar ise
    1. Sudoku
    2. 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/

 

Cevap bırakın

E-posta hesabınız yayımlanmayacak.

Bu web sitesi deneyiminizi geliştirmek için çerezleri kullanır. Bununla iyi olduğunuzu varsayacağız, ancak isterseniz vazgeçebilirsiniz. Kabul etmek Mesajları Oku