sudoku_v2.py

Created by anaali

Created on January 25, 2024

7.25 KB


from random import choice,randint, randrange
from math import*
from kandinsky import fill_rect as rect, draw_string as txt 
from ion import *

# Sudoku 1.0 NumWorks, 27.04.2023
# Par Ilana R. & Vincent ROBERT
# https://nsi.xyz/sudoku   

def reset():
  return[[0 for i in range(9)] for j in range(9)]
 
def ligne(x):
  return [i for i in range(1,10) if i in board[x]]

def colonne(y):
  return [board[i][y] for i in range(9) if board[i][y] != 0]

def bloc(x, y):
  nums = []
  for i in range(x//3*3, x//3*3+3):
    for j in range(y//3*3, y//3*3+3):
      if board[i][j] != 0:
        nums.append(board[i][j])
  return nums

def possible(x, y):
  return [i for i in range(1,10) if i not in ligne(x)+colonne(y)+bloc(x,y)]
  
def check():
 return board == solution
  
def genere_board():
  global board
  board = reset()
  x = y = essai = 0
  while x!=9:
    essai += 1
    if essai ==42: 
      x = essai =0
      board = reset()
    y = 0
    while y!=9:
      if possible(x,y)==[]:
        board[x] = [0 for i in range(9)]
        y = 8
        x = x-1
      else:
        board[x][y] = choice(possible(x,y))
      y +=1
    x +=1
  return board 
  
def couleur(x,y,p=0):
  if (x//3 + y//3) %2 == 1:
    return (180-42*p,140-35*p,225)
  else:
    return (255,200-30*p,125-85*p)
    
def grille():
   for x in range(9):
    for y in range(9):
      rect(2+x*(22), 2+y*(22), 20, 20, couleur(x,y,0))

def dessine_nb(x,y,nb,mode):
  if board[x][y]>9:
    txt(str(0),x*22+7,y*22+3,"black",couleur(x,y,mode))
  else:
    txt(str(nb),x*22+7,y*22+3,"black",couleur(x,y,mode))
   
def is_valid(x,y,nb):
  global vie
  if not pen:
    if board[x][y]==1*10**10:
      if nb == solution[x][y]:
        board[x][y]=nb
        dessine_nb(x,y,nb,2)
      else:
        vie-=1
        perdre_vie()
  else:
    if len(str(board[x][y]))!=1:
        board[x][y]+=-1*(10**(10-nb))*(str(board[x][y])[nb]=="1")+1*(10**(10-nb))*(str(board[x][y])[nb]=="0")
        aff_draft()

def suppr(nb):
  for i in range(nb): 
    x, y = randint(0,8), randint(0,8)
    while board[x][y] == 1*10**10 :
      x, y = randint(0,8), randint(0,8)
    board[x][y] = 1*10**10
    
def aide(x,y):
  rect(200,140,200,20,(255,)*3)
  nbs = possible(x, y)  
  if len(str(board[x][y]))!=1:
    for i in range(len(nbs)):
      txt(str(nbs[i]), 265 + i * 20- len(nbs) *10, 140)
      if nbs[i]!=nbs[-1]:
        txt(",", 275+ i * 20 - len(nbs) *10, 140)
  else:
    txt("Full", 240,140)

def coeur (x,y):
  col=(255,80 ,0)
  rect(x+3,y+0,3,3, col)
  rect(x+15,y+0,3,3,col)
  rect(x+0,y+3,9,3,col)
  rect(x+12,y+3,9,3,col)
  rect(x+0,y+6,21,3,col)
  rect(x+3,y+9,15,3,col)
  rect(x+6,y+12,9,3,col)
  rect(x+9,y+15,3,3,col)
  
def perdre_vie():
    rect(272 - vie *25, 5, 21, 21, (255,) * 3)
    
def affichage_nb():
  for x in range (9):
    for y in range (9):
      if board[x][y] <10:
        dessine_nb(x,y,board[x][y],0)
        
def surbrillance(x, y, mode):
  for i in range(9):
    rect(2+i*(22), 2+y*(22), 20, 20, couleur(i, y, mode))
    rect(2+x*(22), 2+i*(22), 20, 20, couleur(x, i, mode))
    if board[i][y]<10:
      dessine_nb(i, y, board[i][y], mode)
    if board[x][i]<10:
      dessine_nb(x, i, board[x][i], mode)
  for i in range(x//3*3, x//3*3+3):
    for j in range(y//3*3, y//3*3+3):
      rect(2+i*(22), 2+j*(22), 20, 20, couleur(i, j, mode))
      if board[i][j]<10:
        dessine_nb(i, j, board[i][j], mode)
        
def aff_draft():
    x,y=pos[0],pos[1]
    if len(str(board[x][y]))!=1:
        nbs =[j for j in range (1,10) if str(board[x][y])[j]=="1"]
        rect(210,180,200,20,(255,)*3)
        for i in range(len( nbs)):
          txt(str(nbs[i]), 265 + i * 20- len(nbs) *10 -10*(len(nbs)>6), 180,)
          if nbs[i]!=nbs[-1]:
            txt(",", 275+ i * 20 - len(nbs) *10, 180)
    else:
        rect(210,180,200,20,(255,)*3)


def is_pen():
    global pen
    pen=not(pen)
    if pen:
        txt("pen: ON ", 237, 160)
        rect(210,180,200,20,(255,)*3)
    else:
        txt("pen: OFF", 237, 160)
        rect(210,180,200,20,(255,)*3)

def draw_level(s=0):
  txt("< "*s+ "  "*(s==0)+ "     "+ str(lvl)+ " >"*s + "  "*(s==0), 205, 30,(42,)*3)
  txt("Find:", 222,30,(42+106*s,42+71*s,42+180*s))

def draw_help(s=0):
  txt("< "*s+"  "*(s==0)+ "     "+str(s_help)+ ">"*s + "  "*(s==0), 202,70,(42,)*3)
  txt("Help:", 217,70,(42+106*s,42+71*s,42+180*s))
      
def wait(buttons=(0,1,2,3,4,52,30,31,32,36,37,38,42,43,44)):
  while True:
    for i in buttons:
      if keydown(i):
        while keydown(i): True
        return i
vie = 3    
rect(0, 200, 320, 22, (148, 113, 222))
txt( " chargement en cours...  ", 50, 202, (242,)*3, (148, 113,222))
genere_board()
grille()
txt( "Code by nsi.xyz/sudoku ", 50, 202, (242,)*3, (148, 113,222))
coeur(222,5), coeur(247,5), coeur(272,5)
txt("pen:", 237, 160)
lvl,s_help=32,"Off"
draw_level(1)
draw_help(0)
pen=False
keydraft= reset()
options = [32, 42, 52, 62]
diff = None
pos = 0

def select_diff():
  txt(str(options[pos]), 275, 30,(42,)*3)
  
while diff is None:
  key_pressed= wait()
  if key_pressed == 3:
    pos = (pos + 1) % len(options)
    select_diff()
  elif key_pressed == 0:
    pos = (pos - 1) % len(options)
    select_diff()
  elif key_pressed in (4,52):
    lvl= options[pos]
    break
  
draw_level(0)
draw_help(1)
options = ['Off', 'On ']
help = None
pos = 0

def select_help():
  txt(options[pos], 273, 70,(42,)*3)

while help is None:
  key_pressed = wait()
  if key_pressed == 3:
    pos = (pos + 1) % len(options)
    select_help()
  elif key_pressed == 0:
    pos = (pos - 1) % len(options)
    select_help()
  elif key_pressed in (4,52):
    s_help = options[pos]
    break

draw_help(0)

if s_help=="On ":
  txt("Valid",230, 110,(42,)*3)
  txt("numbers",225, 125,(42,)*3)
 
solution = [row.copy() for row in board]
suppr(lvl)  
affichage_nb()
draw_level(0)
pos = [4,4]
pmax = (9,9)

def deplacement():
  x, y = pos_old
  surbrillance(x,y,0)
  x, y = pos 
  surbrillance(x,y,1)
  rect(2+x*(20+2), 2+y*(20+2), 20, 20,couleur(x,y,2))
  if board[x][y]<10:
    dessine_nb(x,y,board[x][y],2)
    
while True:
  if vie==0:
    txt("Perdu!",230,5,(42,)*3,(255,)*3)
    break
  if check()==True :
    txt("  Gagné!  ",210,5,(42,)*3,(255,)*3)
    break
  key_pressed = wait()
  pos_old = list(pos)
  if key_pressed in (4,52):
    is_pen()
    
    
  elif key_pressed == 1:
    pos[1] = (pos[1]-1) % pmax[1]
    aff_draft()
    if  s_help=="On ":
      aide(pos[0],pos[1])
  elif key_pressed == 2:
    pos[1] = (pos[1]+1) % pmax[1]
    aff_draft()
    if  s_help=="On ":
      aide(pos[0],pos[1])
  elif key_pressed == 3:
     pos[0] = (pos[0]+1) % pmax[0]
     aff_draft()
     if  s_help=="On ":
       aide(pos[0],pos[1])
  elif key_pressed == 0:
    pos[0] = (pos[0]-1) % pmax[0]
    aff_draft()
    
    if  s_help=="On ":
      aide(pos[0],pos[1])
      
  elif  key_pressed == 42:
    is_valid(pos[0],pos[1],1)
  elif  key_pressed == 43:
    is_valid(pos[0],pos[1],2)
  elif  key_pressed == 44:
    is_valid(pos[0],pos[1],3)
  elif  key_pressed == 36:
    is_valid(pos[0],pos[1],4)
  elif  key_pressed == 37:
    is_valid(pos[0],pos[1],5)
  elif  key_pressed == 38:
    is_valid(pos[0],pos[1],6)
  elif key_pressed == 30:
    is_valid(pos[0],pos[1],7)
  elif  key_pressed == 31:
    is_valid(pos[0],pos[1],8)
  elif  key_pressed == 32:
    is_valid(pos[0],pos[1],9)
  if key_pressed not in (42, 43 ,44 ,36 ,37 ,38 ,30 ,31, 32) :    
    deplacement()