The mechanics of Sudoku
The rules of Sudoku are so simple (see Sudoku puzzles screen capture) that it seems easy to write the mechanics of the puzzle in Fox. It took 20 minutes to write this. Move the mouse over a desired square and type a digit key. ‘0’ means erase what’s there. It doesn’t know any of the rules, but is a tool that can help you solve a puzzle.
It includes a rudimentary input/storage/output mechanism of saving Sudoku puzzles as a text string of 81 digits. A blank space is represented by 0 (how convenient!)
The 2 Sudoku puzzles included (myvar and myvar2) are the same: one is more solved than the other.
You can write a subclass of this code and add some methods to actually give hints or even generate Sudoku puzzles
If you improve upon this please let me know.
CLEAR ALL
CLEAR
PUBLIC ox
#define CELLHEIGHT 60
#define CELLWIDTH 60
#define NCELLSX 9
#define NCELLSY 9
#define XOFFSET 50
#define YOFFSET 50
#define CELLOFFX CELLWIDTH/3
#define CELLOFFY CELLHEIGHT/3
#define BOLDLINE 0xff0000
#define NORMLINE 0xffff
ox=CREATEOBJECT("Sudoku")
ox.show
DEFINE CLASS Sudoku AS FORM
left=200
backcolor=0xffffff
fontname="Courier New"
allowoutput=.f.
DIMENSION aSq[NCELLSX, NCELLSY]
PROCEDURE Init
this.DrawGrid
TEXT TO myvar
704002603
602730590
305006070
456900030
238641957
179325468
063200005
027060309
041803726
ENDTEXT
TEXT TO myvar2
004002600
002030090
300000070
400900030
000641000
070005008
060000005
020060030
001800700
ENDTEXT
this.aSq=0
IF ALINES(aal,myvar)=NCELLSX
FOR j = 1 TO ALEN(aal,1)
FOR i = 1 TO LEN(aal[j])
this.aSq[i,j]=VAL(SUBSTR(aal[j],i,1))
ENDFOR
ENDFOR
ENDIF
this.ShowNums
PROCEDURE ShowNums
thisform.ForeColor=0
thisform.FontSize=20
FOR i = 1 TO NCELLSX
FOR j = 1 TO NCELLSY
this.shownum(i-1,j-1,this.aSQ[i,j])
ENDFOR
ENDFOR
PROCEDURE ShowNum(i,j,num)
thisform.Print(IIF(num=0," ",TRANSFORM(num)),CELLOFFX+XOFFSET +i * CELLWIDTH , CELLOFFY+YOFFSET + j * CELLHEIGHT)
PROCEDURE keypress(p1,p2)
DO CASE
CASE p1=27
thisform.Release
CASE p1=ASC("C") OR p1=ASC("c")
OTHERWISE
IF p1 >= 48 AND p1 < 58
AMOUSEOBJ(aa,1)
i=1+INT((aa[3]-XOFFSET)/CELLWIDTH)
j=1+INT((aa[4]-YOFFSET)/CELLHEIGHT)
IF i>0 AND i <= NCELLSX AND J>0 AND j<=NCELLSY
thisform.asq[i,j]=p1-48
thisform.ForeColor=0xff0000
thisform.ShowNum(i-1,j-1,p1-48)
ELSE
?"Illegal"
ENDIF
ELSE
?p1,p2
ENDIF
ENDCASE
PROCEDURE DrawGrid
WITH this as Form
.Width = CELLWIDTH * NCELLSX+XOFFSET*2
.Height = CELLHEIGHT * NCELLSY+YOFFSET*2
FOR i = 0 TO NCELLSY && draw horiz
IF MOD(i,3)=0
.ForeColor=BOLDLINE
FOR j = -1 TO 1
.Line(XOFFSET,YOFFSET+ CELLWIDTH*i+j, XOFFSET+CELLWIDTH * NCELLSX, YOFFSET+ CELLWIDTH*i+j)
ENDFOR
ELSE
.ForeColor=NORMLINE
.Line(XOFFSET,YOFFSET+ CELLWIDTH*i, XOFFSET+CELLWIDTH * NCELLSX, YOFFSET+ CELLWIDTH*i)
ENDIF
ENDFOR
FOR i = 0 TO NCELLSX && draw VERT
IF MOD(i,3)=0
.ForeColor=BOLDLINE
FOR j = -1 TO 1
.Line(j+XOFFSET+ CELLHEIGHT*i,YOFFSET, j+XOFFSET+ CELLHEIGHT*i,YOFFSET+ CELLHEiGHT * NCELLSY)
ENDFOR
ELSE
.ForeColor=NORMLINE
.Line(XOFFSET+ CELLHEIGHT*i,YOFFSET, XOFFSET+ CELLHEIGHT*i,YOFFSET+ CELLHEiGHT * NCELLSY)
ENDIF
ENDFOR
ENDWITH
ENDDEFINE
Comments
Anonymous
August 18, 2005
hey, how 'bout making it ink ready for tabletters?Anonymous
August 18, 2005
The comment has been removedAnonymous
August 19, 2005
Wonderful Calvin. Thanks. I don't have any code to add, but if you are looking at enhancements, take a look at what this person has done with an XLS spreadsheet. It is what we use for our Sudoku plays.
http://www.sudoku-xls.com/ It is a pretty complete package for playing the game.
CraigAnonymous
September 22, 2005
I modified the code so that conflicting numbers are shown in red. It required redrawing all the numbers each time a new number is added / removed, but here is the code:
<pre>
! CLEAR ALL
CLEAR
PUBLIC ox
#define CELLHEIGHT 60
#define CELLWIDTH 60
#define NCELLSX 9
#define NCELLSY 9
#define NDIVX 3
#define NDIVY 3
#define XOFFSET 50
#define YOFFSET 50
#define CELLOFFX CELLWIDTH/3
#define CELLOFFY CELLHEIGHT/3
#define BOLDLINE 0xff0000
#define NORMLINE 0xffff
ox=CREATEOBJECT("Sudoku")
ox.show
DEFINE CLASS Sudoku AS FORM
left=200
backcolor=0xffffff
fontname="Courier New"
allowoutput=.f.
windowtype = 1
name="sudoku"
DIMENSION aSq[NCELLSX, NCELLSY]
PROCEDURE Init
this.DrawGrid
TEXT TO myvar
704002603
602730590
305006070
456900030
238641957
179325468
063200005
027060309
041803726
ENDTEXT
TEXT TO myvar2
004002600
002030090
300000070
400900030
000641000
070005008
060000005
020060030
001800700
ENDTEXT
this.aSq=0
IF ALINES(aal,myvar)=NCELLSX
FOR j = 1 TO ALEN(aal,1)
FOR i = 1 TO LEN(aal[j])
this.aSq[i,j]=VAL(SUBSTR(aal[j],i,1))
ENDFOR
ENDFOR
ENDIF
this.ShowNums
PROCEDURE ShowNums
thisform.ForeColor=0
thisform.FontSize=20
FOR i = 1 TO NCELLSX
FOR j = 1 TO NCELLSY
IF this.aSQ[i,j] > 0
lnColor = 0
FOR k = 1 to NCELLSX
IF i#k AND this.aSQ[i,j] = this.aSQ[k,j]
lnColor = 255
EXIT
ENDIF
ENDFOR
IF m.lnColor = 0
FOR k = 1 to NCELLSY
IF j#k AND this.aSQ[i,j] = this.aSQ[i,k]
lnColor = 255
EXIT
ENDIF
ENDFOR
IF m.lnColor = 0
subx = FLOOR((i-1)/NDIVX) * NDIVX + 1
suby = FLOOR((j-1)/NDIVY) * NDIVY + 1
FOR k = subx to subx + NDIVX - 1
FOR l = suby to suby + NDIVY - 1
IF i#k AND j#l AND this.aSQ[i,j] = this.aSQ[k,l]
lnColor = 255
EXIT
ENDIF
ENDFOR
IF m.lnColor = 255
EXIT
ENDIF
ENDFOR
ENDIF
ENDIF
thisform.ForeColor=m.lnColor
ENDIF
this.shownum(i-1,j-1,this.aSQ[i,j])
ENDFOR
ENDFOR
PROCEDURE ShowNum(i,j,num)
thisform.Print(IIF(num=0," ",TRANSFORM(num)),CELLOFFX+XOFFSET +i * CELLWIDTH , CELLOFFY+YOFFSET + j * CELLHEIGHT)
PROCEDURE keypress(p1,p2)
DO CASE
CASE p1=27
thisform.Release
CASE p1=ASC("C") OR p1=ASC("c")
OTHERWISE
IF p1 >= 48 AND p1 < 58
AMOUSEOBJ(aa,1)
i=1+INT((aa[3]-XOFFSET)/CELLWIDTH)
j=1+INT((aa[4]-YOFFSET)/CELLHEIGHT)
IF i>0 AND i <= NCELLSX AND J>0 AND j<=NCELLSY
thisform.asq[i,j]=p1-48
thisform.ShowNums()
! thisform.ForeColor=0xff0000
! thisform.ShowNum(i-1,j-1,p1-48)
ELSE
?"Illegal"
ENDIF
ELSE
?p1,p2
ENDIF
ENDCASE
PROCEDURE DrawGrid
WITH this && as Form
.Width = CELLWIDTH * NCELLSX+XOFFSET2
.Height = CELLHEIGHT * NCELLSY+YOFFSET2
FOR i = 0 TO NCELLSY && draw horiz
IF MOD(i,3)=0
.ForeColor=BOLDLINE
FOR j = -1 TO 1
.Line(XOFFSET,YOFFSET+ CELLWIDTHi+j, XOFFSET+CELLWIDTH * NCELLSX, YOFFSET+ CELLWIDTHi+j)
ENDFOR
ELSE
.ForeColor=NORMLINE
.Line(XOFFSET,YOFFSET+ CELLWIDTHi, XOFFSET+CELLWIDTH * NCELLSX, YOFFSET+ CELLWIDTHi)
ENDIF
ENDFOR
FOR i = 0 TO NCELLSX && draw VERT
IF MOD(i,3)=0
.ForeColor=BOLDLINE
FOR j = -1 TO 1
.Line(j+XOFFSET+ CELLHEIGHTi,YOFFSET, j+XOFFSET+ CELLHEIGHTi,YOFFSET+ CELLHEiGHT * NCELLSY)
ENDFOR
ELSE
.ForeColor=NORMLINE
.Line(XOFFSET+ CELLHEIGHTi,YOFFSET, XOFFSET+ CELLHEIGHTi,YOFFSET+ CELLHEiGHT * NCELLSY)
ENDIF
ENDFOR
ENDWITH
ENDDEFINE
</pre>Anonymous
November 30, 2005
You were discovering Sudoku about the same time I was. I posted some code to solve a puzzle at www.universalthread.com in message ID 1073558.Anonymous
April 03, 2006
Several months ago, I wrote The mechanics of Sudoku and Sudoku puzzles screen capture. As a result, Stephen...Anonymous
February 14, 2009
My wife and I like to listen to PuzzleMaster Will Shortz.on NPR. This week’s challenge is from one ofAnonymous
June 08, 2009
PingBack from http://insomniacuresite.info/story.php?id=2091