A basic sudoku game, the game is interactive even though I couldn’t create a start menu due to memory limitations.
It creates randomly a sudoku grid every restart.
You can change the difficulty by changing the number of prefilled squares.
The program will tell you if the position is legal, illegal or a solution.
Colors are also customizable, from line 60 to 67 changing the 3 values in parenthesis to some RGB values will change the colors of the things stated above. For example changing (50,50,50) under “# background color” to (0,0,0) will change the color of the background (dark grey to black in this example).
How to play:
Enter a number in the console at the beginning to set the amount of prefilled squares.
Arrows to move the cursor.
0 to empty square.
1-9 to fill a square with a number.
Exe to show a solution, it will also stop the program.
from kandinsky import fill_rect as f, draw_string as d from ion import * from time import monotonic from random import randint,choice def number(num,pos,COLORS): if 10>num>0: for x in range(7): if l[num][x]: f(pos[0]+coo[x][0],pos[1]+coo[x][1],a[x%2],a[(x+1)%2],COLORS) def possible_numbers(grid, coo): l=[1 for _ in range(9)] for a in range(9): if grid[a][coo[1]]!=-1 and coo[0]!=a: l[grid[a][coo[1]]%10]=0 if grid[coo[0]][a]!=-1 and coo[1]!=a: l[grid[coo[0]][a]%10]=0 for x in range(coo[0]-coo[0]%3,coo[0]-coo[0]%3+3): for y in range(coo[1]-coo[1]%3,coo[1]-coo[1]%3+3): if grid[x][y]!=-1 and [x,y]!=[coo[0],coo[1]]: l[grid[x][y]%10]=0 l=[x for x in range(9) if l[x]] return l def position_status(grid): grid=[[grid[x][y]-1 for y in range(9)]for x in range(9)] filled=1 for x in range(9): for y in range(9): if grid[x][y]==-1: filled=0 elif not (grid[x][y]%10 in possible_numbers(grid,[x,y])): return 0 return 1+filled def cur(COLORS): f(pos[0]*24+2*(pos[0]//3),pos[1]*24+2*(pos[1]//3),25,1,COLORS) f(pos[0]*24+2*(pos[0]//3),(pos[1]+1)*24+2*(pos[1]//3),25,1,COLORS) f((pos[0]+1)*24+2*(pos[0]//3),1+pos[1]*24+2*(pos[1]//3),1,23,COLORS) f(pos[0]*24+2*(pos[0]//3),1+pos[1]*24+2*(pos[1]//3),1,23,COLORS) def mov(vx,vy): global t,pos if monotonic()-t>0.125: t=monotonic() cur(COLORS[1]) pos[0]=(pos[0]+vx)%9 pos[1]=(pos[1]+vy)%9 cur(COLORS[3]) COLORS=( (50,50,50),#background (194,224,255),#grid & text (220,170,80),#base number & selected text (255,0,0))# cursor blanks=81-int(input("Enter prefilled spaces amount\n(80 max,20 advised): ")) show=int(input("show if position is legal ?\n1 for yes, 0 for no: ")) if not 82>blanks>0: blanks=20 text=( "Not legal", "Legal", "Solution !") keys={KEY_ZERO:0,KEY_ONE:1,KEY_TWO:2,KEY_THREE:3,KEY_FOUR:4,KEY_FIVE:5,KEY_SIX:6,KEY_SEVEN:7,KEY_EIGHT:8,KEY_NINE:9} key_pressing=[0 for _ in range(10)] key_pressed=[0 for _ in range(10)] a=2 a=(a,(21-3*a)//2) l=((1,1,1,0,1,1,1),(1,0,0,0,1,0,0),(0,1,1,1,1,1,0),(0,1,1,1,0,1,1),(1,0,1,1,0,0,1),(1,1,0,1,0,1,1),(1,1,0,1,1,1,1),(0,1,1,0,0,0,1),(1,1,1,1,1,1,1),(1,1,1,1,0,0,1)) coo=((0,a[0]),(a[0],0),(a[0]+a[1],a[0]),(a[0],a[0]+a[1]),(0,2*a[0]+a[1]),(a[0],2*a[0]+2*a[1]),(a[0]+a[1],2*a[0]+a[1])) f(222,0,98,222,COLORS[0]) f(0,0,222,222,COLORS[1]) for x in range(9): for y in range(9): f(1+24*x+2*(x//3),1+24*y+2*(y//3),23,23,COLORS[0]) if show: d("position:",224,10,COLORS[1],COLORS[0]) d("Legal",224,26,COLORS[1],COLORS[0]) d("0:",224,46,COLORS[1],COLORS[0]) d("empty",224,62,COLORS[1],COLORS[0]) d("1-9:",224,82,COLORS[1],COLORS[0]) d("fill",224,98,COLORS[1],COLORS[0]) d("Exe:",224,118,COLORS[1],COLORS[0]) d("Show a",224,136,COLORS[1],COLORS[0]) d("solution",224,154,COLORS[1],COLORS[0]) sol_grid=[[-1 for _ in range(9)] for _ in range(9)] tree=[[x for x in range(9)]] while len(tree)<82: if len(tree[-1])==0: del tree[-1] del tree[-1][tree[-1].index(sol_grid[(len(tree)-1)%9][(len(tree)-1)//9])] sol_grid[(len(tree)-1)%9][(len(tree)-1)//9]=-1 else: sol_grid[(len(tree)-1)%9][(len(tree)-1)//9]=choice(tree[-1]) tree.append(possible_numbers(sol_grid,(len(tree)%9,(len(tree)//9)%9))) for x in range(9): for y in range(9): sol_grid[x][y]+=1 del tree grid=[[y+10 for y in x] for x in sol_grid] while blanks: rand_coo=(randint(0,8),randint(0,8)) if grid[rand_coo[0]][rand_coo[1]]//10: blanks-=1 grid[rand_coo[0]][rand_coo[1]]=0 for x in range(9): for y in range(9): if grid[x][y]//10: number(grid[x][y]%10,[7+24*x+2*(x//3),2+24*y+2*(y//3)],COLORS[2]) pos=[0,0] cur(COLORS[3]) t=monotonic() run=1 while run: for k in keys: key_pressed[keys[k]]=0 if keydown(k): if not key_pressing[keys[k]]: key_pressed[keys[k]]=1 key_pressing[keys[k]]=1 else: key_pressing[keys[k]]=0 if keydown(KEY_LEFT): mov(-1,0) elif keydown(KEY_UP): mov(0,-1) elif keydown(KEY_DOWN): mov(0,1) elif keydown(KEY_RIGHT): mov(1,0) elif keydown(KEY_EXE): cur(COLORS[1]) for x in range(9): for y in range(9): f(1+24*x+2*(x//3),1+24*y+2*(y//3),23,23,COLORS[0]) number(sol_grid[x][y]%10,(7+x*24+2*(x//3),2+y*24+2*(y//3)),COLORS[2]) run=0 elif not grid[pos[0]][pos[1]]//10: for n,k in enumerate(key_pressed): if k: grid[pos[0]][pos[1]]=n f(1+pos[0]*24+2*(pos[0]//3),1+pos[1]*24+2*(pos[1]//3),23,23,COLORS[0]) f(224,26,96,18,COLORS[0]) if show: state=position_status(grid) d(text[state],224,26,COLORS[1],COLORS[0]) if n: number(n,(7+24*pos[0]+2*(pos[0]//3),2+24*pos[1]+2*(pos[1]//3)),COLORS[1])