167 lines
8.9 KiB
Python
167 lines
8.9 KiB
Python
from random import randint, shuffle # 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
|
|
|
|
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()
|
|
|
|
|
|
|
|
# ----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# igra
|
|
# ----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
print("SUDOKU")
|
|
print()
|
|
tezavnost = input("Izberi težavnost(lahka, srednja, težka, nemogoča):")
|
|
while tezavnost.lower() != "lahka" and tezavnost.lower() != "težka" and tezavnost.lower() != "srednja" and tezavnost.lower() != "nemogoča":
|
|
print("Še enkrat jasno napiši.")
|
|
tezavnost = input("Izberi težavnost(lahka, srednja, težka, nemogoča):")
|
|
if tezavnost.lower() == "lahka": # težavnost pove, koliko številk moramo odstraniti
|
|
odstrani = 35
|
|
elif tezavnost.lower() == "srednja":
|
|
odstrani = 42
|
|
elif tezavnost.lower() == "težka":
|
|
odstrani = 49
|
|
elif tezavnost.lower() == "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
|
|
|
|
|
|
izpisisudoku() # tu program prvič izpiše sudoku
|
|
odgovori = ["Pravilno!","Odlično!","Točno tako!","Prav je!","Super!","Bravo!","Zadetek!","Natančno!","Fantastično!"] # množica odgovorov za pravilno rešitev
|
|
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 (vnos.split(","))
|
|
if sudoku == resensudoku:
|
|
break # ko pride uporabnik do konca, gre program iz While zanke
|
|
vnos = input('Vnesi številko in koordinate le-te.:')
|
|
if vnos.upper() == "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] # program avtomatsko reši eno prazno polje
|
|
print()
|
|
print("Goljufaš. To je samo za admina.")
|
|
izpisisudoku()
|
|
continue
|
|
elif vnos.upper() == "NAMIG": # uporabnik lahko zaprosi za namig, če je obtičal
|
|
namigi += 1 # program prišteje en uporabljen namig
|
|
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 136 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: # če pride do ValueErrorja, program ne bo crashal, pač pa se bo vrnil na začetek zanke
|
|
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 napake pri vnosu velikosti števila
|
|
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 154)
|
|
print()
|
|
print("Pomota. Poskusi ponovno.")
|
|
sudoku[vnos_y][vnos_x] = 0
|
|
pomote += 1 # število pomot gre gor
|
|
else:
|
|
print()
|
|
print(odgovori[randint(0,len(odgovori)-1)]) # potrdilo, vzeto iz množice odgovorov (line 94)
|
|
izpisisudoku() # izpiše sudoku
|
|
|
|
|
|
end = time() # ko je zanke konec, se merjenje časa ustavi
|
|
cas = end - start
|
|
if vnos.upper() == "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) |