• We just launched and are currently in beta. Join us as we build and grow the community.

Microsoft Foundation Classes: creating a Sudoku game. Part 1.

reprapdes1887

Test-Driven Developer
R Rep
0
0
0
Rep
0
R Vouches
0
0
0
Vouches
0
Posts
128
Likes
188
Bits
2 MONTHS
2 2 MONTHS OF SERVICE
LEVEL 1 300 XP
In this article you will read about the rules of the Sudoku game and the algorithm, used to solve the Sudoku puzzle.

In the next two articles I'll describe the complete step by step guide about how to implement a Sudoku puzzle game using MFC.
The goal of the Sudoku game is to fill the 9x9 grid with numbers from 1 to 9 in the next way:
  • Each row contains all numbers from 1 to 9
  • Each column contains all numbers from 1 to 9
  • Each block of 3x3 cells contains all numbers from 1 to 9

Here is an example of the solved Sudoku:
31_0.jpg

The first step is to create the class that will represent the Sudoku puzzle. The definition of this class in my project is:
  1. #include "stdlib.h"
  2. #pragma once
  3. class

    board
  4. {
  5. public

    :
  6. int

    difficulty;

    //difficulty of the game
  7. board(

    void

    )

    ;
  8. ~board(

    void

    )

    ;
  9. int

    **

    numbers;

    //array to store the current representation of the board
  10. int

    **

    solution;

    //used to save the solution of the puzzle
  11. int

    *

    tempSol;

    //temporary element
  12. void

    generate(

    )

    ;

    //generate the random puzzle
  13. bool

    checkNumberValidity(

    int

    ,int

    ,int

    )

    ;
  14. void

    help(

    )

    ;

    //show help
  15. void

    showSolution(

    )

    ;

    //show solution
  16. bool

    win(

    )

    ;

    //check for winn
  17. private

    :
  18. void

    transpose(

    )

    ;

    //operations
  19. void

    swap_rows(

    )

    ;

    //performed
  20. void

    swap_columns(

    )

    ;

    //to generate
  21. void

    swap_rows_sector(

    )

    ;

    //a new
  22. void

    swap_columns_sector(

    )

    ;

    //puzzle
  23. void

    createProblem(

    )

    ;
  24. bool

    solve(

    )

    ;
  25. void

    placeNumber(

    int

    )

    ;
  26. bool

    checkValidity(

    int

    ,int

    ,int

    )

    ;
  27. }

    ;

The constructor of the board is very simple. It just allocates memory for the arrays and calls generate(

)

function to generate the problem:
  1. board::

    board

    (

    void

    )
  2. {
  3. difficulty =

    30

    ;
  4. numbers =

    new

    int

    *

    [

    9

    ]

    ;
  5. solution =

    new

    int

    *

    [

    9

    ]

    ;
  6. tempSol =

    new

    int

    [

    81

    ]

    ;
  7. for

    (

    int

    i =

    0

    ;

    i!

    =

    9

    ;

    ++

    i)
  8. {
  9. numbers[

    i]

    =

    new

    int

    [

    9

    ]

    ;
  10. solution[

    i]

    =

    new

    int

    [

    9

    ]

    ;
  11. }
  12. generate(

    )

    ;
  13. }

Before the description of the generate(

)

function I would like to describe the algorithm used by me. To generate a random puzzle I start from the "base grid" - a correct grid of Sudoku puzzle:
base.jpg

The next list of operations can be performed on the base grid and the rule of the Sudoku will be kept:
  • transpose grid
    trans.jpg

  • swap 2 rows
  • swap 2 columns

    345.jpg
  • swap 2 sectors of rows
  • swap 2 sectors columns

    1234.jpg

These transformations have next realization:
  1. void

    board::

    swap_rows

    (

    )
  2. {

  3. srand

    (

    time

    (

    NULL

    )

    )

    ;
  4. int

    sector =

    rand

    (

    )

    %

    3

    ;

  5. int

    row_number1 =

    rand

    (

    )

    %

    3

    ;
  6. int

    row_number2;
  7. do
  8. row_number2 =

    rand

    (

    )

    %

    3

    ;
  9. while

    (

    row_number1 ==

    row_number2)

    ;

  10. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  11. {
  12. int

    temp =

    numbers[

    sector*

    3

    +

    row_number2]

    [

    i]

    ;
  13. numbers[

    sector*

    3

    +

    row_number2]

    [

    i]

    =

    numbers[

    sector*

    3

    +

    row_number1]

    [

    i]

    ;
  14. numbers[

    sector*

    3

    +

    row_number1]

    [

    i]

    =

    temp;
  15. }
  16. }
  17. void

    board::

    swap_columns

    (

    )
  18. {
  19. transpose(

    )

    ;
  20. swap_rows(

    )

    ;
  21. transpose(

    )

    ;
  22. }
  23. void

    board::

    transpose

    (

    )
  24. {
  25. int

    **

    temp;
  26. temp =

    new

    int

    *

    [

    9

    ]

    ;
  27. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  28. temp[

    i]

    =

    new

    int

    [

    9

    ]

    ;
  29. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  30. for

    (

    int

    j =

    0

    ;

    j !

    =

    9

    ;

    ++

    j)
  31. temp[

    i]

    [

    j]

    =

    numbers[

    j]

    [

    i]

    ;
  32. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  33. for

    (

    int

    j =

    0

    ;

    j!

    =

    9

    ;

    ++

    j)
  34. numbers[

    i]

    [

    j]

    =

    temp[

    i]

    [

    j]

    ;
  35. }
  36. void

    board::

    swap_rows_sector

    (

    )
  37. {
  38. srand

    (

    time

    (

    NULL

    )

    )

    ;
  39. int

    sector1 =

    rand

    (

    )

    %

    3

    ;
  40. int

    sector2;
  41. do
  42. sector2 =

    rand

    (

    )

    %

    3

    ;
  43. while

    (

    sector1 ==

    sector2)

    ;
  44. for

    (

    int

    i =

    0

    ;

    i !

    =

    3

    ;

    ++

    i)
  45. {
  46. for

    (

    int

    j =

    0

    ;

    j !

    =

    9

    ;

    ++

    j)
  47. {
  48. int

    temp =

    numbers[

    sector2*

    3

    +

    i]

    [

    j]

    ;
  49. numbers[

    sector2*

    3

    +

    i]

    [

    j]

    =

    numbers[

    sector1*

    3

    +

    i]

    [

    j]

    ;
  50. numbers[

    sector1*

    3

    +

    i]

    [

    j]

    =

    temp;
  51. }
  52. }
  53. }
  54. void

    board::

    swap_columns_sector

    (

    )
  55. {
  56. transpose(

    )

    ;
  57. swap_rows_sector(

    )

    ;
  58. transpose(

    )

    ;
  59. }

As you can see the swapping of the columns and columns sectors are done using already defined functions: transpose(

)

and swap_rows(

)

, swap_rows_sector(

)

;

The generation of the puzzle is done by random number of these transformations:
  1. void

    board::

    generate

    (

    )
  2. {
  3. for

    (

    int

    i1 =

    0

    ,k =

    0

    ;

    i1 !

    =

    9

    ;

    ++

    i1,k +

    =

    3

    )

    {
  4. for

    (

    int

    i2 =

    0

    ;

    i2 !

    =

    9

    ;

    ++

    i2,k++

    )

    {
  5. numbers[

    i1]

    [

    i2]

    =

    k%

    9

    +

    1

    ;
  6. }
  7. if

    (

    i1==

    2

    )
  8. k++

    ;
  9. if

    (

    i1 ==

    5

    )
  10. k++

    ;
  11. }

  12. srand

    (

    time

    (

    NULL

    )

    )

    ;
  13. for

    (

    int

    i =

    0

    ;

    i !

    =

    100

    ;

    ++

    i)
  14. {
  15. switch

    (

    rand

    (

    )

    %

    5

    )
  16. {
  17. case

    0

    :

    transpose(

    )

    ;
  18. break

    ;
  19. case

    1

    :

    swap_rows(

    )

    ;
  20. break

    ;
  21. case

    2

    :

    swap_columns(

    )

    ;
  22. break

    ;
  23. case

    3

    :

    swap_rows_sector(

    )

    ;
  24. break

    ;
  25. case

    4

    :

    swap_columns_sector(

    )

    ;
  26. break

    ;
  27. }
  28. }

  29. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  30. for

    (

    int

    j =

    0

    ;

    j !

    =

    9

    ;

    ++

    j)
  31. solution[

    i]

    [

    j]

    =

    numbers[

    i]

    [

    j]

    ;

  32. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)

    {
  33. for

    (

    int

    j =

    0

    ;

    j !

    =

    9

    ;

    ++

    j)
  34. tempSol[

    i*

    9

    +

    j]

    =

    numbers[

    i]

    [

    j]

    ;
  35. }
  36. createProblem(

    )

    ;
  37. }

In this function we create a random already solved puzzle and save it's representation. After this we need to create a problem for the user: we need to erase some numbers from cells. It's done by createProblem(

)

function:
  1. void

    board::

    createProblem

    (

    )
  2. {
  3. for

    (

    int

    k =

    0

    ;

    k !

    =

    difficulty;

    )
  4. {
  5. int

    i;
  6. int

    j;
  7. do
  8. {
  9. i =

    rand

    (

    )

    %

    9

    ;
  10. j =

    rand

    (

    )

    %

    9

    ;
  11. }
  12. while

    (

    numbers[

    i]

    [

    j]

    ==

    0

    )

    ;
  13. int

    save =

    numbers[

    i]

    [

    j]

    ;
  14. numbers[

    i]

    [

    j]

    =

    0

    ;
  15. tempSol[

    i*

    9

    +

    j]

    =

    0

    ;
  16. if

    (

    !

    solve(

    )

    )
  17. {
  18. numbers[

    i]

    [

    j]

    =

    save;
  19. tempSol[

    i*

    9

    +

    j]

    =

    save;
  20. }
  21. else
  22. ++

    k;
  23. }
  24. }

In this method numbers from the grid are randomly eliminated. After the cell is eliminated, the program checks if the problem can be resolved in a single way. If it can be resolved - number is deleted from cell. The check of the valid elimination is performed by the next functions:
  1. bool

    board::

    solve

    (

    )
  2. {
  3. try

    {
  4. placeNumber(

    0

    )

    ;
  5. return

    false

    ;
  6. }

    catch

    (

    char

    *

    ex)

    {
  7. return

    true

    ;
  8. }
  9. }
  10. void

    board::

    placeNumber

    (

    int

    position)
  11. {
  12. if

    (

    position==

    81

    )
  13. throw

    (

    char

    *

    )

    "Finished!"

    ;
  14. if

    (

    tempSol[

    position]

    )
  15. {
  16. placeNumber(

    position+

    1

    )

    ;
  17. return

    ;
  18. }
  19. for

    (

    int

    n =

    1

    ;

    n!

    =

    10

    ;

    ++

    n)
  20. {
  21. if

    (

    checkValidity(

    n,position%

    9

    , position /

    9

    )

    )
  22. {
  23. tempSol[

    position]

    =

    n;
  24. placeNumber(

    position+

    1

    )

    ;
  25. tempSol[

    position]

    =

    0

    ;
  26. }
  27. }
  28. }
  29. bool

    board::

    checkValidity

    (

    int

    value, int

    x, int

    y)
  30. {
  31. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  32. {
  33. if

    (

    tempSol[

    y*

    9

    +

    i]

    ==

    value ||

    tempSol[

    i*

    9

    +

    x]

    ==

    value)
  34. return

    false

    ;
  35. }
  36. int

    startX =

    (

    x /

    3

    )

    *

    3

    ;
  37. int

    startY =

    (

    y /

    3

    )

    *

    3

    ;
  38. for

    (

    int

    i =

    startY;

    i <

    startY +

    3

    ;

    i++

    )

    {
  39. for

    (

    int

    j =

    startX;

    j <

    startX +

    3

    ;

    j++

    )

    {
  40. if

    (

    tempSol[

    i *

    9

    +

    j]

    ==

    value)
  41. return

    false

    ;
  42. }
  43. }
  44. return

    true

    ;
  45. }
  46. bool

    board::

    checkNumberValidity

    (

    int

    value, int

    x, int

    y)
  47. {
  48. for

    (

    int

    i =

    0

    ;

    i !

    =

    9

    ;

    ++

    i)
  49. {
  50. if

    (

    numbers[

    x]

    [

    i]

    ==

    value ||

    numbers[

    i]

    [

    y]

    ==

    value)
  51. return

    false

    ;
  52. }
  53. int

    startX =

    (

    x /

    3

    )

    *

    3

    ;
  54. int

    startY =

    (

    y /

    3

    )

    *

    3

    ;
  55. for

    (

    int

    i =

    startY;

    i <

    startY +

    3

    ;

    i++

    )

    {
  56. for

    (

    int

    j =

    startX;

    j <

    startX +

    3

    ;

    j++

    )

    {
  57. if

    (

    numbers[

    j]

    [

    i]

    ==

    value)
  58. return

    false

    ;
  59. }
  60. }
  61. return

    true

    ;
  62. }

These functions use the depth search algorithm with backtracking to find if any solution for the current state can be found.
As the result of generate(

)

function we have next things:
  • A grid that represents the solution of the Sudoku puzzle
  • A grid a copy of the solution but without some numbers in cells

So, we have the full implementation of the Sudoku logic. In the next article I'll tell you how to create the interface of the Sudoku game.

 

452,292

323,341

323,350

Top