from random import randint, shuffle, random # za generiranje naključnega sudokuja from copy import deepcopy # za kopiranje že rešenega sudokuja from time import time # za merjenje časa sudoku = [ # začnemo s praznim sudokujem [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0] ] class GeneratorSudokuja: def veljavna(self, sudoku, stevilka, vrstica, stolpec): # funkcija, ki preveri veljavnost številke na določenem mestu, kjer sta vrstica in stolpec enaka i in j (j,i) = (x,y) for i in range(9): if stevilka == sudoku[vrstica][i] or stevilka == sudoku[i][stolpec] or stevilka == sudoku[3 * (vrstica//3) + i // 3][3 * (stolpec//3) + i % 3]: return False # če je številka enaka katerikoli izmed treh možnosti (v vrstici, v stolpcu ali pa v 3x3 mreži), funkcija vrne False return True # drugače True def generiraj(self, sudoku): # funkcija, ki generira sudoku for i in range(9): for j in range(9): if sudoku[i][j] == 0: stevila = list(range(1,10)) # seznam od 1 do 9, tako se nobena ne ponavlja shuffle(stevila) # jih premešamo npr. [5, 2, 7, 6, 1, 9, 3, 8, 4] for stevilka in stevila: if self.veljavna(sudoku, stevilka, i, j): # za vsako številko preverimo, če je na mestu [i][j] veljavna sudoku[i][j] = stevilka # če je, jo na mesto [i][j] vpišemo, tam ni več 0 if self.generiraj(sudoku) == True: return True # če je sudoku s tisto številko zgeneriran, bo tam ostala sudoku[i][j] = 0 # če ne, pa program vpiše na mesto 0 in proba z drugo naključno številko return False # če ni nobena številka na tistem mestu veljavna, vrne False return True def odstranjevanje(self, sudoku, koliko): # funkcija, ki odstranjuje številke iz sudokuja st = 0 while st < koliko: # odstranjujemo, dokler ne pride st do koliko i = randint(0, 8) # naključni koordinati j = randint(0, 8) if sudoku[i][j] != 0: # odstrani samo, ko ni enako 0, da program ne bi odšel recimo na enem mestu trikrat. sudoku[i][j] = 0 st += 1 # igra print("SUDOKU") print() tezavnost = input("Izberi težavnost(lahka, srednja, težka, nemogoča):") while tezavnost != "lahka" and tezavnost != "težka" and tezavnost != "srednja" and tezavnost != "nemogoča": print("Še enkrat jasno napiši.") tezavnost = input("Izberi težavnost(lahka, srednja, težka, nemogoča):") if tezavnost == "lahka": # težavnost pove, koliko številk moramo odstraniti odstrani = 35 elif tezavnost == "srednja": odstrani = 42 elif tezavnost == "težka": odstrani = 49 elif tezavnost == "nemogoča": odstrani = 56 generator = GeneratorSudokuja() generator.generiraj(sudoku) # zgeneriramo sudoku resensudoku = deepcopy(sudoku) # kopiramo rešen sudoku in ga damo v spremenljivko generator.odstranjevanje(sudoku, odstrani) # odstrani nam pove, koliko jih moramo odstraniti, odstrani = koliko def izpisisudoku(): # funkcija za izpisovanje sudokuja print() for i, vrstica in enumerate(sudoku): # v terminal narišemo sudoku # enumerate vrne indeks vrstice(i) in vrstico. if i % 3 == 0 and i != 0: # ko je indeks večkratnik od 3, bo program vrinil med številke vrsto črtic. print("-" * 21) for j, stevilo in enumerate(vrstica): # j je indeks vsake številke v vrstici, ko je ta večkratnik od 3, se bo vrinila navpična črta, končana s presledkom if j % 3 == 0 and j != 0: print("|", end=" ") if stevilo == 0: print(0, end=" ") # 0 so bele else: print("\033[34m"+str(stevilo)+"\033[0m", end=" ") # če j ni večkratnik števila 3, program napiše barvno številko in konča s presledkom print() # ko se ena vrstica konča, gre program v novo vrstico print() izpisisudoku() # tu program prvič izpiše sudoku pomote = 0 # štetje pomot namigi = 0 # štetje namigov start = time() # štetje časa while True: # s tem poskrbimo, da vedno znova (ob vsakem vnosu) program pogleda najprej, če je sudoku rešen, potem če je admin ali pa namig # šele po vseh teh preverbah program razdeli vnos if sudoku == resensudoku: break # ko pride uporabnik do konca, gre program iz While zanke vnos = input('Vnesi številko in koordinate le-te (npr. 6,1,5)(če žeiš namig, napiši "namig").:') if vnos == "end": # easter egg break elif vnos.upper() == "ADM": # samo za admina za preverjanje kode e = randint(0,8) f = randint(0,8) while sudoku[f][e] != 0: e = randint(0,8) f = randint(0,8) sudoku[f][e] = resensudoku[f][e] print() print("Goljufaš. To je samo za admina.") izpisisudoku() continue elif vnos == "namig": # uporabnik lahko zaprosi za namig, če je obtičal namigi += 1 e = randint(0,8) f = randint(0,8) while sudoku[f][e] != 0: e = randint(0,8) # program generira nove koordinate, dokler ne naleti na 0 f = randint(0,8) print() print("Na koordinatah x =",e+1,"in y =",f+1,"je število", resensudoku[f][e]) izpisisudoku() # izpiše sudoku continue vnos = vnos.split(",") # ko vnos ni več "end" ali pa "namig", program vnos (npr. "6,1,5") razčleni v seznamu (["6", "1", "5"]). if len(vnos) != 3: # če se uporabnik zatipka (npr. 6,5 namesto 6,1,5), se program ne bo ustavil (line 130 index out of range), pač pa mu dal še eno priložnost print() print("Zatipkal si se. Poskusi ponovno.") izpisisudoku() # izpiše sudoku continue try: vnos_st = int(vnos[0]) # 6 vnos_x = int(vnos[1])-1 # 0 -> ker program sudoku mrežo bere od 0-8, ne od 1-9 vnos_y = int(vnos[2])-1 # 4 -> isto except ValueError: print() print('Vnesi le števila ali pa "namig".') izpisisudoku() # izpiše sudoku continue if vnos_st not in range(1,10) or vnos_x not in range(9) or vnos_y not in range(9): # v primeru tiskarske napake; print() print("Napaka. Vpiši števila med 1 in 9.") else: if sudoku[vnos_y][vnos_x] != 0: # če je uporabnik dislektičen print() print("Napaka. Številko vpiši v prazno polje.") else: sudoku[vnos_y][vnos_x] = vnos_st # vpišemo številko na prazno polje if resensudoku[vnos_y][vnos_x] != vnos_st: # če se ne ujema s številko v rešenem sudokuju, se številka ne vpiše (line 148) print() print("Pomota. Poskusi ponovno.") sudoku[vnos_y][vnos_x] = 0 pomote += 1 # število pomot gre gor else: odgovori = ["Pravilno!","Odlično!","Točno tako!","Prav je!","Super!","Bravo!","Zadetek!","Natančno!","Fantastično!"] print() print(odgovori[randint(0,len(odgovori)-1)]) # potrdilo izpisisudoku() # izpiše sudoku end = time() # ko je zanke konec, se merjenje časa ustavi cas = end - start if vnos == "end": # če uporabnik predčasno konča igro print("Škoda. Več sreče prihodnjič. Število namigov:", namigi, "Število pomot:", pomote) else: # če pride do konca print("Čestitke, sudoku si pravilno rešil v", int(cas//60), "min in", int(cas % 60) ,"sek. Število namigov:", namigi, "Število pomot:", pomote)