sudoku.py

Created by anaali

Created on May 09, 2023

6.41 KB

𝗦𝘂𝗱𝗼𝗸𝘂


Python Game 🎮 v1.01 for Numworks, all models.

By Ilana R. & Vincent ROBERT avril 2023.

Un projet libre réalisé dans la cadre de l'enseignement de spécialité NSI.

Learn more about Sudoku on: nsi.xyz/sudoku (FR)

Changelog

Convert v1.0 - 30/04/2023:
- Initial version


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():
  c=0
  for i in range (9):
    for j in range (9):
      if board[i][j]!=0:
        c+=1
  return c==81
  
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):
  txt(str(nb),x*22+7,y*22+3,"black",couleur(x,y,mode))
   
def is_valid(x,y,nb):
  global vie
  if board[x][y]==0:
    if nb == solution[x][y]:
      dessine_nb(x,y,nb,1)
      board[x][y]=nb
    else:
      vie-=1
      perdre_vie()
      
def suppr(nb):
  for i in range(nb):
    x, y = randint(0,8), randint(0,8)
    while board[x][y] == 0:
      x, y = randint(0,8), randint(0,8)
    board[x][y] = 0
    
def aide(x,y):
  rect(200,155 ,200,20,(255,)*3)
  nbs = possible(x, y)  
  if board[x][y]==0:
    for i in range(len(nbs)):
      txt(str(nbs[i]), 265 + i * 20- len(nbs) *10, 155)
      if nbs[i]!=nbs[-1]:
        txt(",", 275+ i * 20 - len(nbs) *10, 155)
  else:
    txt("Full", 240,155)

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] != 0 :
        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] != 0:
      dessine_nb(i, y, board[i][y], mode)
    if board[x][i] != 0:
      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] != 0:
        dessine_nb(i, j, board[i][j], mode)
        
def draw_level(s=0):
  txt("Find", 237,35,(42+106*s,42+71*s,42+180*s))
  txt("< "*s+ "  "*(s==0) + str(lvl)+ " >"*s + "  "*(s==0), 225, 50,(42,)*3)

def draw_help(s=0):
  txt("Help", 237,80,(42+106*s,42+71*s,42+180*s))
  txt("< "*s+"  "*(s==0)+str(s_help)+ " >"*s + "  "*(s==0), 222,100,(42,)*3)
      
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
#init
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)
lvl,s_help=32,"Off"
draw_level(1)
draw_help(0)

options = [32, 42, 52, 62]
diff = None
pos = 0

def select_diff():
  txt(str(options[pos]), 246, 50,(42,)*3)
  
while diff is None:
  key_pressed= wait()
  if key_pressed == 3: # fleche droite
    pos = (pos + 1) % len(options)
    select_diff()
  elif key_pressed == 0: # fleche gauche
    pos = (pos - 1) % len(options)
    select_diff()
  elif key_pressed in (4,52): # touche OK caclu+ordi
    lvl= options[pos]
    break
  
draw_level(0)
draw_help(1)
options = ['Off', 'On ']
help = None
pos = 0

def select_help():
  txt(options[pos], 243, 100,(42,)*3)

while help is None:
  key_pressed = wait()
  if key_pressed == 3: # fleche droite
    pos = (pos + 1) % len(options)
    select_help()
  elif key_pressed == 0: # fleche gauche
    pos = (pos - 1) % len(options)
    select_help()
  elif key_pressed in (4,52): # touche OK caclu+ordi
    s_help = options[pos]
    break

draw_help(0)

if s_help=="On ":
  txt("Valid",230, 125,(42,)*3)
  txt("numbers",225, 140,(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]!=0:
    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 == 1:  # fleche haut
    pos[1] = (pos[1]-1) % pmax[1]
    if  s_help=="On ":
      aide(pos[0],pos[1])
  elif key_pressed == 2: # fleche bas
    pos[1] = (pos[1]+1) % pmax[1]
    if  s_help=="On ":
      aide(pos[0],pos[1])
  elif key_pressed == 3: #fleche droite
     pos[0] = (pos[0]+1) % pmax[0]
     if  s_help=="On ":
       aide(pos[0],pos[1])
  elif key_pressed == 0: # fleche gauche
    pos[0] = (pos[0]-1) % pmax[0]
    if  s_help=="On ":
      aide(pos[0],pos[1])
  elif  key_pressed == 42: #1
    is_valid(pos[0],pos[1],1)
  elif  key_pressed == 43: #2
    is_valid(pos[0],pos[1],2)
  elif  key_pressed == 44: #3
    is_valid(pos[0],pos[1],3)
  elif  key_pressed == 36: #4
    is_valid(pos[0],pos[1],4)
  elif  key_pressed == 37: #5
    is_valid(pos[0],pos[1],5)
  elif  key_pressed == 38: #6
    is_valid(pos[0],pos[1],6)
  elif key_pressed == 30: #7
    is_valid(pos[0],pos[1],7)
  elif  key_pressed == 31: #8
    is_valid(pos[0],pos[1],8)
  elif  key_pressed == 32: #9
    is_valid(pos[0],pos[1],9)
  if key_pressed not in (42, 43 ,44 ,36 ,37 ,38 ,30 ,31, 32) :    
    deplacement()