Partager via


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 removed

  • Anonymous
    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.

    Craig

  • Anonymous
    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+YOFFSET
    2
    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 of

  • Anonymous
    June 08, 2009
    PingBack from http://insomniacuresite.info/story.php?id=2091