'app-plug-in 'menu Su-doku '$Id: sudoku.bas,v 1.6 2006-02-03 03:45:16 zeeb90au Exp $ const text_size = textwidth("9") const cell_size = text_size*5 const x1 = 10 const y1 = 10 const x2 = x1+(cell_size*9) const y2 = y1+(cell_size*9) const ky1 = y2+10 const ky2 = ky1+cell_size const kx2 = x2+(cell_size*2) 'sets the text position for the given grid reference sub at_grid(x,y) at x1+(x*cell_size)+(text_size*2), y1+(y*cell_size)+text_size+4 end ' displays the game grid sub showGrid(byref grid) local x,y,i,j cls 'draw line segments i = x1 for x = 0 to 9 line i,y1,i,y2,0 i += cell_size next x j = y1 for y = 0 to 9 line x1,j,x2,j,0 j += cell_size next y 'draw heavy black borders rect x1+1,y1+1,x2+1,y2+1,0 i = x1+(cell_size*3)+1 line i,y1,i,y2,0 i = x1+(cell_size*6)+1 line i,y1,i,y2,0 j = y1+(cell_size*3)+1 line x1,j,x2,j,0 j = y1+(cell_size*6)+1 line x1,j,x2,j,0 for y = 0 to 8 for x = 0 to 8 if grid(x,y) > 0 then at_grid x,y ? cat(1)+grid(x,y) fi next next ? cat(-1) end 'show a keypad key sub showKey(n) if (n = 9) then ? "C" elif (n = 10) then ? "T" else ? n+1 fi end 'display the game keypad sub showKeypad local i,x i = x1 for x = 0 to 10 line i,ky1,i,ky2,0 at i+(text_size*2),ky1+text_size+4 showKey x i += cell_size next x rect x1,ky1,kx2,ky2,0 end 'returns 1 when n is unique in the given column func uniqueCol(byref grid, x, y, n) local yy if grid(x,y) != 9 then uniqueCol=0 'cell not empty exit sub fi y-- for yy = 0 to y if grid(x,yy) = n then uniqueCol = 0 'same number in previous row exit sub fi next uniqueCol = 1 end 'returns 1 when n is unique within its 3x3 cell func uniqueCell(byref grid, x, y, n) local x1,x2,y1,y2,xx,yy '012 345 678 if x > 5 then x1 = 6 elif x > 2 then x1 = 3 else x1 = 0 fi if y > 5 then y1 = 6 elif y > 2 then y1 = 3 else y1 = 0 fi x2 = x1+2 y2 = y1+2 for xx = x1 to x2 for yy = y1 to y2 if grid(xx,yy) = n then uniqueCell=0 exit sub fi next xx next yy uniqueCell=1 end 'creates the game grid func makeGrid(byref grid) local x,y,i,n for y = 0 to 8 for x = 0 to 8 grid(x,y) = 9 next next for n = 1 to 8 'calc each number for y = 0 to 8 'visit each row i = 0 'check for invalid pattern while 1 x = rnd*10000%9 i++ if i>40 then makeGrid = 0 cls ? "Thinking ..." exit sub fi if uniqueCol(grid,x,y,n) then if uniqueCell(grid,x,y,n) then exit loop 'break from while - AND short-circuit fi fi wend grid(x,y) = n next next makeGrid = 1 end 'randomly hide cells sub hideCells(byref grid) local x,y,n for y = 0 to 8 for x = 0 to 8 n = int(rnd*10000)%2 if n = 0 then grid(x,y) = -1 fi next next end 'returns the current mouse position func getPen pen on repeat until pen(0) getPen = [Pen(1), Pen(2)] pen off end 'return true if the x-y location is in given rect func ptInRect(byref p, x1,x2,y1,y2) local x,y x = p(0) y = p(1) if (x < x1) then ptInRect=0 exit sub fi if (x > x2) then ptInRect=0 exit sub fi if (y < y1) then ptInRect=0 exit sub fi if (y > y2) then ptInRect=0 exit sub fi ptInRect=1 end 'convert the x-y location to game grid coordinates func ptToGrid(p) ptToGrid = [int((p(0)-x1)/cell_size), int((p(1)-y1)/cell_size)] end 'convert the x-y location to the keypad key number func ptToKey(p) ptToKey = int((p(0)-x1)/cell_size) end 'highlight the active grid cell sub showFocus(p, show, mode) local x,y,i,j i = p(0) j = p(1) if (i<9 && j<9) then x = x1+(i*cell_size) y = y1+(j*cell_size) rect x, y, x+cell_size, y+cell_size, if(show, if(mode!=0,12,14), 0) fi end 'erase the given cell sub clearCell(p) local x,y,i,j i = p(0) j = p(1) if (i<9 && j<9) then x = x1+(i*cell_size)+2 y = y1+(j*cell_size)+2 rect x, y, x+cell_size-2, y+cell_size-2, 15 filled fi end 'set the given cell into the given cell location sub setKey(grid, focus, key, mode) local x,y,xx,yy x = focus(0) y = focus(1) atx = x1+(x*cell_size)+(text_size*2) aty = y1+(y*cell_size)+text_size+5 n = key+1 select mode case 1 atx += 10 aty += 8 case 2 atx -= 10 aty += 8 case 3 atx -= 10 aty -= 8 case 4 atx += 10 aty -= 8 end select 'validate selection if n > 9 then exit sub fi if grid(x,y) != -1 then 'don't change clue cell exit sub fi if uniqueCell(grid,x,y,n) = 0 then exit sub fi for xx = 0 to 8 if grid(xx,y) = n then exit sub fi next for yy = 0 to 8 if grid(x,yy) = n then exit sub fi next grid(i,j) = -n at atx,aty ? n end 'show or hide the selected keypad key sub showClick(key, show) local x,y if key < 11 then x = x1+(key*cell_size) y = ky1 rect x+1, y+1, x+cell_size, y+cell_size, if(show, 12, 15) filled at x+(text_size*2),y+text_size+5 showKey key fi end 'main game loop sub main local p,focus,focus_click,key,key_click,mode dim focus(2) dim grid(9,9) cls randomize focus = [0,0] key = 1 mode = 0 repeat i = makeGrid(grid) until i hideCells grid showGrid grid showFocus focus, true, mode showKeypad while 1 p = getPen if ptInRect(p,x1,x2,y1,y2) then 'clicked inside the game grid focus_click = ptToGrid(p) if focus_click != focus then showFocus focus, false, 0 showFocus focus_click, true, 0 focus = focus_click fi elif ptInRect(p,x1,kx2,ky1,ky2) then 'clicked inside the keypad key_click = ptToKey(p) if (key_click = 9) then clearCell focus showFocus focus, true, mode elif (key_click = 10) then mode = if(mode > 0, 0, 1) showFocus focus, true, mode showClick key_click, mode else showClick key, false showClick key_click, true key = key_click setKey grid, focus, key, mode if mode != 0 then mode++ if mode = 5 then mode = 1 fi fi fi fi wend end main