Results 1 to 19 of 19

Thread: Random Sudoku board generator

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Random Sudoku board generator

    Hello ,

    So i am trying to generate a sudoku board that would be solvable, with 20 random digits in random positions , but when I run the code numbers appear in different places then they should be , for example
    my function generates y = 8 x = 8 value = 5 , but on my board that tile is empty and 5 appears in other position. Could someone tell me how to fix this?

    Thank you

    Qt Code:
    1. // widget.h
    2. #ifndef WIDGET_H
    3. #define WIDGET_H
    4.  
    5. #include <QWidget>
    6.  
    7. QT_BEGIN_NAMESPACE
    8. class QLineEdit;
    9. QT_END_NAMESPACE
    10.  
    11.  
    12.  
    13. class SudokuWidget : public QWidget
    14. {
    15. Q_OBJECT;
    16.  
    17. public:
    18. SudokuWidget( QWidget *parent );
    19.  
    20.  
    21. private slots:
    22. // void onMapped( int rowColId );
    23. // void on_pushButton_clicked();
    24.  
    25. private:
    26. // QSignalMapper *mapper;
    27. QVector < QLineEdit *> tiles;
    28.  
    29. QVector <QPair <int, int>> random_pos_value;
    30. void random_position(int digits, QVector < QPair <int, int> > &pos_value);
    31.  
    32. bool is_legal_row(int value, int y, int x, QVector< QVector < QLineEdit* >> &tiles1);
    33. bool is_legal_colum(int value, int y, int x, QVector< QVector < QLineEdit* >> &tiles1);
    34.  
    35. int box_position(int y, int x);
    36. bool is_legal_box(int value, int y,int x, QVector< QVector < QLineEdit* >> &tiles1);
    37. };
    38.  
    39.  
    40. #endif // WIDGET_H
    41.  
    42. // widget.cpp
    43.  
    44. #include "widget.h"
    45. #include "ui_widget.h"
    46.  
    47. #include <QGridLayout>
    48. #include <QFrame>
    49. #include <QLineEdit>
    50. #include <QIntValidator>
    51. #include <QMessageBox>
    52. #include <QPushButton>
    53. #include <QRandomGenerator>
    54. #include <QDateTime>
    55. #include <QSet>
    56. #include <iostream>
    57.  
    58.  
    59. SudokuWidget::SudokuWidget(QWidget * parent)
    60. : QWidget(parent) {
    61.  
    62. QIntValidator *pValidator = new QIntValidator( this );
    63. pValidator->setRange( 1, 9 );
    64.  
    65. int square_counter = 0;
    66. random_position(20, random_pos_value);
    67.  
    68.  
    69. QGridLayout *mainLayout = new QGridLayout(this);
    70. mainLayout->setSpacing(0);
    71.  
    72. for (int mr = 0; mr < 3; mr++) {
    73. for(int mc = 0; mc < 3; mc++) {
    74.  
    75. QFrame *widget = new QFrame;
    76. widget->setFrameStyle(QFrame::Plain);
    77. widget->setFrameShape(QFrame::Box);
    78.  
    79. QGridLayout *gridLayout = new QGridLayout(widget);
    80. gridLayout->setSpacing(0);
    81. gridLayout->setMargin(0);
    82.  
    83. for(int r = 0; r < 3; r++) {
    84. for (int c = 0; c < 3; c++) {
    85.  
    86. QLineEdit *tile = new QLineEdit("");
    87. square_counter++;
    88.  
    89. tile->setMaxLength(1);
    90. tile->setFixedSize(30,30);
    91. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-style: solid; border-color: black black black black; }");
    92. tile->setAlignment(Qt::AlignCenter);
    93. tile->setFrame(QFrame::Box);
    94. tile->setValidator(pValidator);
    95.  
    96. tiles.push_back( tile );
    97.  
    98. gridLayout->addWidget(tile, r, c, 1, 1, Qt::AlignCenter);
    99. }
    100. }
    101. mainLayout->addWidget(widget, mr, mc, 1, 1, Qt::AlignCenter);
    102. }
    103. }
    104. for (int i = 0;i < 80; i++){
    105. for (int j = 0;j < 20; j++){
    106. if (random_pos_value[j].first == i){
    107. tiles[i]->setText(QString::number(random_pos_value[j].second));
    108. tiles[i]->setReadOnly(true);
    109. }
    110. }
    111. }
    112.  
    113. setLayout(mainLayout);
    114. }
    115.  
    116.  
    117. bool SudokuWidget::is_legal_row(int value,int y, int x, QVector< QVector < QLineEdit* >> &tiles1)
    118. {
    119. int count = 0;
    120. for (int i = 0;i < 9; i++){
    121. if (QString::number(value) == tiles1[y][i]->text()){
    122. count++;
    123. }
    124. }
    125. if (count == 1){
    126. return true;
    127. }
    128. return false;
    129. }
    130.  
    131. bool SudokuWidget::is_legal_colum(int value,int y, int x, QVector<QVector<QLineEdit *> > &tiles1)
    132. {
    133. int count = 0;
    134. for (int i = 0;i < 9; i++){
    135. if (QString::number(value) == tiles1[i][x]->text()){
    136. count++;
    137. }
    138. }
    139. if (count == 1){
    140. return true;
    141. }
    142. return false;
    143. }
    144.  
    145. void SudokuWidget::random_position(int digits, QVector <QPair <int, int> > &random_pos_value)
    146. {
    147.  
    148. QVector < QVector < QLineEdit* > > random_boards(81);
    149. for (int y1 = 0;y1 < 9; y1++){
    150. for (int x1 = 0;x1 < 9; x1++){
    151. QLineEdit *line_edit = new QLineEdit("0");
    152. random_boards[y1].push_back(line_edit);
    153. }
    154. }
    155. qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
    156. int count = 0;
    157. int value;
    158. while (true){
    159. int position = (qrand() % 80) + 0;
    160. int y = position / 9;
    161. int x = position % 9;
    162. if (random_boards[y][x]->text() == "0"){
    163. while (true){
    164. value = (qrand() % 9) + 1;
    165. random_boards[y][x]->setText(QString::number(value));
    166. if (is_legal_box(value, y, x, random_boards) && is_legal_colum(value, y, x, random_boards) ){
    167. break;
    168. }
    169. random_boards[y][x]->setText("0");
    170. }
    171. QPair <int, int> values = {position,value};
    172. random_pos_value.push_back(values);
    173. count++;
    174. if (count == digits){
    175. break;
    176. }
    177. }
    178. }
    179. }
    180.  
    181.  
    182. int SudokuWidget::box_position(int y, int x)
    183. {
    184. return 3*(y/3) + (x/3);
    185. }
    186.  
    187. bool SudokuWidget::is_legal_box(int value, int y1, int x1, QVector<QVector<QLineEdit *> > &tiles1)
    188. {
    189. //box
    190. int count = 0;
    191. int square_position = box_position(y1, x1);
    192. QVector <QString> values;
    193. for (int y = (square_position / 3) * 3; y < ((square_position / 3) * 3) + 3;y++){
    194. for (int x = (square_position % 3) * 3; x < ((square_position % 3) * 3) + 3;x++){
    195. if (tiles1[y][x]->text() == QString::number(value)){
    196. count++;
    197. }
    198. }
    199.  
    200. }
    201. if (count == 1){
    202. return true;
    203. }
    204. return false;
    205. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by laurynas2003; 10th April 2020 at 12:02.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Random Sudoku board generator

    Qt Code:
    1. for (int i = 0;i < 80; i++){
    2. for (int j = 0;j < 20; j++){
    3. if (random_pos_value[j].first == i){
    4. tiles[i]->setText(QString::number(random_pos_value[j].second));
    5. tiles[i]->setReadOnly(true);
    6. }
    7. }
    8. }
    To copy to clipboard, switch view to plain text mode 

    Think about this loop. The innermost part of it runs 3200 times. Is that what you want to do?
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Random Sudoku board generator

    Qt Code:
    1. for (int i = 0;i < 20; i++){
    2. tiles[random_pos_value[i].first]->setText(QString::number(random_pos_value[i].second));
    3. QMessageBox::about(this,"????????", "(" + QString::number(random_pos_value[i].first / 9) + ", " + QString::number(random_pos_value[i].first % 9) + ")" + " = " +
    4. QString::number(random_pos_value[i].second));
    5. tiles[i]->setReadOnly(true);
    6. }
    To copy to clipboard, switch view to plain text mode 

    I change it to this code , but still doesnt work properly. With MessageBox i check where the tile value should be.


    Added after 59 minutes:


    Qt Code:
    1. if (is_legal_box(value, y, x, random_boards) && is_legal_colum(value, y, x, random_boards ) && is_legal_row(value, y, x, random_boards) ){ // i forgot to add is_legal_row
    2. break;
    3. }
    To copy to clipboard, switch view to plain text mode 


    Ohh I forgot to add is_legal function to random_position function, but still doesn't work . I think my random_position function is fine, because I checked with QMessageBox every coordinate that it gave and wrote it on paper Sudoku board, and that board was fine.
    Last edited by laurynas2003; 10th April 2020 at 20:46.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Random Sudoku board generator

    tiles[i]->setReadOnly(true);
    So if you have 81 tiles on your board, and you are setting 20 of them to fixed numbers, and you are using the variable "i" to count from 0 to 19, which tiles do you think this code is setting to read-only?

    Hint: Why don't you write a little function:

    Qt Code:
    1. int SudokuWidget::mapRowAndColumnToTileIndex( int row, int column ) const
    2. {
    3. int tileIndex = -1; // ALWAYS initialize; -1 means an invalid row or column was passed
    4.  
    5. if ( row >= 0 && row < 9 && column >= 0 && column < 9 )
    6. {
    7. // it's a valid row / column location
    8. // add code here to compute index into the tiles array from row and column
    9. }
    10. return tileIndex;
    11. }
    To copy to clipboard, switch view to plain text mode 

    and use that function every time you need to get a tile from a row and column. You could even write the reverse mapping function

    Qt Code:
    1. bool SudokuWidget::mapTileIndexToRowAndColumn( int tileIndex, int & row, int & column ) const
    2. {
    3. bool bValid = false; // set to true if the index is within range
    4. if ( tileIndex >= 0 && tileIndex < tiles.size() )
    5. {
    6. bValid = true;
    7.  
    8. // add code here to compute row and column from index
    9. }
    10. return bValid;
    11. }
    To copy to clipboard, switch view to plain text mode 

    and use it every time you need to go the other way. The code you need to add is in an answer I gave to one of your other posts, if I remember correctly...
    Last edited by d_stranz; 11th April 2020 at 00:19.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Random Sudoku board generator

    Qt Code:
    1. #include "widget.h"
    2. #include "ui_widget.h"
    3.  
    4. #include <QGridLayout>
    5. #include <QFrame>
    6. #include <QLineEdit>
    7. #include <QIntValidator>
    8. #include <QMessageBox>
    9. #include <QPushButton>
    10. #include <QRandomGenerator>
    11. #include <QDateTime>
    12. #include <QSet>
    13. #include <iostream>
    14. #include <QSignalMapper>
    15.  
    16.  
    17.  
    18. SudokuWidget::SudokuWidget(QWidget * parent)
    19. : QWidget(parent) {
    20.  
    21. mapper = new QSignalMapper( this );
    22.  
    23. for (int y = 0;y < 9; y++){
    24. for (int x =0; x < 9; x++){
    25. game_data[y].push_back(0);
    26. }
    27. }
    28.  
    29. QIntValidator *pValidator = new QIntValidator( this );
    30. pValidator->setRange( 1, 9 );
    31.  
    32. int square_counter = 0;
    33.  
    34. // random_position(20, random_pos_value); // QVector <QPair <int, int>
    35.  
    36.  
    37. QGridLayout *mainLayout = new QGridLayout(this);
    38. mainLayout->setSpacing(0);
    39. mainLayout->setAlignment(Qt::AlignCenter);
    40.  
    41.  
    42. for (int mr = 0; mr < 3; mr++) {
    43. for(int mc = 0; mc < 3; mc++) {
    44.  
    45. QFrame *widget = new QFrame;
    46. widget->setFrameStyle(QFrame::Plain);
    47. widget->setFrameShape(QFrame::Box); /
    48.  
    49. QGridLayout *gridLayout = new QGridLayout(widget);
    50. gridLayout->setSpacing(0);
    51. gridLayout->setMargin(0);
    52.  
    53. for(int r = 0; r < 3; r++) {
    54. for (int c = 0; c < 3; c++) {
    55.  
    56. QLineEdit *tile = new QLineEdit(this);
    57.  
    58. int rowColId = (square_counter / 9) + (square_counter % 9) * 10;
    59. mapper->setMapping( tile, rowColId );
    60. connect(tile, &QLineEdit::editingFinished, mapper, &QSignalMapper::map ); // error - no matching member function for call to connect
    61.  
    62. tile->setMaxLength(1);
    63. tile->setFixedSize(30,30);
    64. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-style: solid; border-color: black black black black; }");
    65. tile->setAlignment(Qt::AlignCenter);
    66. tile->setFrame(QFrame::Box);
    67. tile->setValidator(pValidator);
    68.  
    69. tiles.push_back( tile );
    70. square_counter++;
    71. gridLayout->addWidget(tile, r, c, 1, 1, Qt::AlignCenter);
    72. }
    73. }
    74. mainLayout->addWidget(widget, mr, mc, 1, 1, Qt::AlignCenter);
    75. }
    76. }
    77. connect( mapper, SIGNAL( mapped( int ) ), this, SLOT( onMapped( int ) ) );
    78. // for (int i = 0;i < 20; i++){
    79.  
    80. // tiles[random_pos_value[i].first]->setText(QString::number(random_pos_value[i].second));
    81. // QMessageBox::about(this,"????????", "(" + QString::number(random_pos_value[i].first / 9) + ", " + QString::number(random_pos_value[i].first % 9) + ")" + " = " + QString::number(random_pos_value[i].second));
    82.  
    83. // tiles[random_pos_value[i].first]->setReadOnly(true);
    84. // }
    85.  
    86. //setLayout(mainLayout);
    87. }
    88.  
    89. void SudokuWidget::onMapped( int rowColId )
    90. {
    91. int row = rowColId / 10;
    92. int col = rowColId % 10;
    93.  
    94. QLineEdit * tile = tiles[ row * 9 + col ];
    95.  
    96. int square_value = tile->text().split(" ")[0].toInt(); // Retrieve the QString text from the QLineEdit, convert it to an int,
    97.  
    98. // store it in your game data structure, check to see if it is correct,
    99. game_data[col][row] = square_value;
    100. if (is_legal_box(square_value, col, row, game_data) && is_legal_row(square_value, col, game_data) && is_legal_colum(square_value, row, game_data) ){
    101. QMessageBox::about(this, "?", "Its working"); // whatever your game decides to do.
    102. }
    103.  
    104.  
    105.  
    106.  
    107.  
    108.  
    109. }
    110.  
    111. bool SudokuWidget::is_legal_row(int value, int y, QVector< QVector < int >> &tiles1)
    112. {
    113. int count = 0;
    114. for (int i = 0;i < 9; i++){
    115. if (value == tiles1[y][i]){
    116. count++;
    117. }
    118. }
    119. if (count == 1){
    120. return true;
    121. }
    122. return false;
    123. }
    124.  
    125. bool SudokuWidget::is_legal_colum(int value, int x, QVector<QVector< int > > &tiles1)
    126. {
    127. int count = 0;
    128. for (int i = 0;i < 9; i++){
    129. if (value == tiles1[i][x]){
    130. count++;
    131. }
    132. }
    133. if (count == 1){
    134. return true;
    135. }
    136. return false;
    137. }
    138.  
    139. //void SudokuWidget::random_position(int digits, QVector <QPair <int, int> > &random_pos_value)
    140. //{
    141.  
    142. // QVector < QVector < QLineEdit* > > random_boards(81);
    143. // for (int y1 = 0;y1 < 9; y1++){
    144. // for (int x1 = 0;x1 < 9; x1++){
    145. // QLineEdit *line_edit = new QLineEdit("0");
    146. // random_boards[y1].push_back(line_edit);
    147. // }
    148. // }
    149. // qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
    150. // int count = 0;
    151. // int value;
    152. // while (true){
    153. // int position = (qrand() % 80) + 0;
    154. // int y = position / 9;
    155. // int x = position % 9;
    156. // if (random_boards[y][x]->text() == "0"){
    157. // while (true){
    158. // value = (qrand() % 9) + 1;
    159. // random_boards[y][x]->setText(QString::number(value));
    160. // if (is_legal_box(value, y, x, random_boards) && is_legal_colum(value, x, random_boards) && is_legal_row(value, y, random_boards)){
    161. // break;
    162. // }
    163. // random_boards[y][x]->setText("0");
    164. // }
    165. // QPair <int, int> values = {position,value};
    166. // random_pos_value.push_back(values);
    167. // count++;
    168. // if (count == digits){
    169. // break;
    170. // }
    171. // }
    172. // }
    173. //}
    174.  
    175.  
    176. int SudokuWidget::box_position(int y, int x)
    177. {
    178. return 3*(y/3) + (x/3);
    179. }
    180.  
    181. bool SudokuWidget::is_legal_box(int value, int y1, int x1, QVector<QVector< int > > &tiles1)
    182. {
    183. //box
    184. int count = 0;
    185. int square_position = box_position(y1, x1);
    186. QVector <QString> values;
    187. for (int y = (square_position / 3) * 3; y < ((square_position / 3) * 3) + 3;y++){
    188. for (int x = (square_position % 3) * 3; x < ((square_position % 3) * 3) + 3;x++){
    189. if (tiles1[y][x] == value){
    190. count++;
    191. }
    192. }
    193.  
    194. }
    195. if (count == 1){
    196. return true;
    197. }
    198. return false;
    199. }
    To copy to clipboard, switch view to plain text mode 


    So i changed it to this code, but now i am getting an error "no matching member function for call to connect"

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Random Sudoku board generator

    So i changed it to this code, but now i am getting an error "no matching member function for call to connect"
    It is an obscure error, and I have been burned by it more than once. It is because QSignalMapper::map() is an overloaded function, and the compiler cannot determine which one of the two overloads to use.

    There are two solutions:

    1 - Use the "old style" form of connect:

    Qt Code:
    1. connect( tile, SIGNAL( editingFinished() ), mapper, SLOT( map() ) );
    To copy to clipboard, switch view to plain text mode 

    2 - Use the new style, with a special template which resolves the overload so it can compile:

    Qt Code:
    1. connect( tile, &QLineEdit::editingFinished, mapper, QOverload<>::of( &QSignalMapper::map ) ); // C++11
    2.  
    3. // or
    4.  
    5. connect( tile, &QLineEdit::editingFinished, mapper, qOverload<>( &QSignalMapper::map ) ); // C++14
    To copy to clipboard, switch view to plain text mode 

    Even though the new style is more complex, you should use it instead of the old style if you can, because it allows the connect() arguments to be evaluated at -compile- time.

    The old style will always compile, even if the signal or slot are not defined at all and it will not be caught until run time. Even then, all that happens is a warning, and the program will run (incorrectly because the connection won't be made between signal and slot). This makes it really hard to debug a program unless you happen to pay attention to all of the startup warnings and messages that are displayed in the Qt Creator or Visual Studio Output window.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. The following user says thank you to d_stranz for this useful post:

    laurynas2003 (11th April 2020)

  8. #7
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Random Sudoku board generator

    By the way i just figured out why my first code didn't work.

    I thought that my square positions were like that:

    0 1 2 3 4 5 6 7 8
    9 10 11...

    but actually it looks like that:

    0 1 2 9 10 11 18 19 20....
    3 4 5 12 13 14
    6 7 8 15 16 17

  9. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Random Sudoku board generator

    but actually it looks like that:
    Yes, my mistake, too. It is because your code to create the 3 x 3 grid of tiles is inside another two loops to create the 3 x 3 grid of big squares. It would probably be a good idea to change your grid creating code so the the cell indexes are like the first case (0 1 2 3 4 5 6 7 8...). It will make it much easier to design your game logic.

    I would create the outer grid of big squares first, in a 3 x 3 loop. Then outside of that, in a 9 x 9 loop, create the tiles and put them in the right position in the big grids.

    You actually don't need the big grid at all, I don't think. Just a 9 x 9 grid is all you really need. Grids within grids just makes everything harder.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  10. The following user says thank you to d_stranz for this useful post:

    laurynas2003 (11th April 2020)

  11. #9
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Random Sudoku board generator

    Quote Originally Posted by d_stranz View Post
    I would create the outer grid of big squares first, in a 3 x 3 loop. Then outside of that, in a 9 x 9 loop, create the tiles and put them in the right position in the big grids.
    Maybe you could show me how to make it because I can't figure out how to make that without using another gridlayout ?
    Last edited by laurynas2003; 11th April 2020 at 22:05.

  12. #10
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Random Sudoku board generator

    Qt Code:
    1. // SudokuWidget constructor
    2.  
    3. QGridLayout * pMainLayout( this );
    4.  
    5. // Make the 3 x 3 array of grid layouts
    6. QVector< QGridLayout * > bigGrids;
    7. for ( int row = 0; row < 3; row++ )
    8. {
    9. for ( int col = 0; col < 3; col++ )
    10. {
    11. QGridLayout * pInnerGrid = new QGridLayout( this );
    12. pMainLayout->addLayout( pInnerGrid, row, col );
    13. bigGrids.push_back( pInnerGrid );
    14. }
    15. }
    16.  
    17. // Big grid array corresponds to these positions
    18. // 0 1 2
    19. // 3 4 5
    20. // 6 7 8
    21.  
    22. // Now make the 9 x 9 arrays of tiles
    23. // These will have indexes
    24. // 0 1 2 3 4 5 6 7 8
    25. // 9 10 11 12 13 14 15 16 17
    26. // 18 19 20 21 22 23 24 25 25
    27. // ...
    28. // 72 73 74 75 76 77 78 79 80
    29.  
    30. // QVector< QLineEdit * > tiles is a member variable
    31. // Resize the tiles array, set all pointers to null
    32. tiles.resize( 81, nullptr );
    33.  
    34. for ( int row = 0; row < 9; row++ )
    35. {
    36. for ( int col = 0; col < 9; col++ )
    37. {
    38. // index of grid in bigGrids array
    39. int bigGridIndex = 3 * (row / 3 ) + col / 3; // ex: if row = 5 and col = 4, index = 3 + 1 = 4
    40. QGridLayout * pInnerGrid = bigGrids[ bigGridIndex ];
    41.  
    42. // row, col coordinates of line edit inside of inner grid
    43. int gridRow = row % 3;
    44. int gridCol = col %3;
    45.  
    46. QLineEdit * tile = new QLineEdit( this );
    47. pInnerGrid->addWidget( tile, gridRow, gridCol );
    48.  
    49. // index of tile in tiles array
    50. int tileIndex = row * 9 + col;
    51. tiles[ tileIndex ] = tile;
    52. }
    53. }
    54.  
    55. setLayout( pMainLayout );
    To copy to clipboard, switch view to plain text mode 

    Now you have a SudokuWidget with a grid layout inside it. This grid layout has 9 smaller grid layouts inside it.
    In each of these 9 smaller grids, there are 9 QLineEdit tiles.

    The tiles are stored in a QVector of QLineEdit pointers. The tiles are numbered as a 9 x 9 grid like above (row = 0 .. 8, col = 0 .. 8).

    Helpful functions:

    Qt Code:
    1. QVector< QLineEdit * > SudokuWidget::tilesForColumn( int col )
    2. {
    3. QVector< QLineEdit * > colTiles;
    4. for ( int row = 0; row < 9; row++ )
    5. {
    6. int tileIndex = col + row * 9;
    7. colTiles.push_back( tiles[ tileIndex ] );
    8. }
    9. return colTiles;
    10. }
    11.  
    12. QVector< QLineEdit * > SudokuWidget::tilesForRow( int row )
    13. {
    14. QVector< QLineEdit * > rowTiles;
    15. for ( int col = 0; col < 9; col++ )
    16. {
    17. int tileIndex = col + row * 9;
    18. rowTiles.push_back( tiles[ tileIndex ] );
    19. }
    20. return rowTiles;
    21. }
    To copy to clipboard, switch view to plain text mode 

    Another function you will probably want is tilesForSquare( int row, int col ), which gives you the 9 tiles in the inner grid that contains row and col.
    Last edited by d_stranz; 12th April 2020 at 00:54.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  13. The following user says thank you to d_stranz for this useful post:

    laurynas2003 (11th April 2020)

  14. #11
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Random Sudoku board generator

    Could you tell me how to change outer grid of big squares size?

  15. #12
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Random Sudoku board generator

    What do you mean, "change the size"? Make the widget bigger or smaller? Change the number of squares inside it?

    Show some of your code for how you are creating your SudokuWidget instance and a screenshot of the result.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  16. #13
    Join Date
    Apr 2020
    Location
    Lithuania
    Posts
    24
    Thanks
    17
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Random Sudoku board generator

    Qt Code:
    1. // widget.cpp
    2.  
    3.  
    4. #include "widget.h"
    5. #include "ui_widget.h"
    6.  
    7. #include <QGridLayout>
    8. #include <QFrame>
    9. #include <QLineEdit>
    10. #include <QIntValidator>
    11. #include <QMessageBox>
    12. #include <QPushButton>
    13. #include <QRandomGenerator>
    14. #include <QDateTime>
    15. #include <QSet>
    16. #include <iostream>
    17. #include <QSignalMapper>
    18.  
    19.  
    20.  
    21. SudokuWidget::SudokuWidget(QWidget * parent)
    22. : QWidget(parent) {
    23.  
    24. QIntValidator *pValidator = new QIntValidator( this ); // user can input only 1 - 9
    25. pValidator->setRange( 1, 9 ); // 1 - 9
    26.  
    27. QGridLayout *pMainLayout = new QGridLayout( this );
    28. pMainLayout->setSpacing(0);
    29. pMainLayout->setAlignment(Qt::AlignCenter);
    30. QRect size = QRect(0,0,5000,1000);
    31. this->setGeometry(size);
    32.  
    33.  
    34.  
    35.  
    36.  
    37. // 3 x 3 array of grid layouts
    38. QVector< QGridLayout * > bigGrids;
    39. for ( int y = 0; y < 3; y++ ){
    40. for ( int x = 0; x < 3; x++ ){
    41. QGridLayout *pInnerGrid = new QGridLayout( this );
    42.  
    43. pInnerGrid->setAlignment(Qt::AlignHCenter);
    44. pInnerGrid->setSpacing(0);
    45. pInnerGrid->setMargin(0);
    46.  
    47. pMainLayout->addLayout( pInnerGrid, y, x );
    48. bigGrids.push_back( pInnerGrid );
    49. }
    50. }
    51.  
    52. tiles.resize(81);
    53. solve_data.resize(81);
    54.  
    55. for (int y = 0; y < 9; y++){
    56. for (int x = 0; x < 9; x++){
    57. int bigGridIndex = box_position( y, x);
    58. QGridLayout *pInnerGrid = bigGrids[bigGridIndex];
    59.  
    60. // square coordinates in the box
    61. int grid_y = y % 3;
    62. int grid_x = x % 3;
    63.  
    64. QLineEdit *tile = new QLineEdit( this );
    65.  
    66. // tile customization
    67. tile->setValidator(pValidator); // input 1 - 9
    68. tile->setMaxLength(1);
    69. tile->setFixedSize(30,30);
    70. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-style: solid; border-color: gray gray gray gray; }");
    71. tile->setAlignment(Qt::AlignCenter);
    72. tile->setFrame(QFrame::Box);
    73.  
    74. if (y == 0){
    75. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-style: solid; border-color: black gray gray gray; }");
    76. }
    77.  
    78. if (x == 8){
    79. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-right: 5px; border-style: solid; border-color: gray black gray gray; }");
    80. }
    81. if (y == 8){
    82. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-style: solid; border-color: gray gray black gray; }");
    83. }
    84. if (x == 0){
    85. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-left: 5px; border-style: solid; border-color: gray gray gray black; }");
    86. }
    87. if (x == 0 && y == 0){
    88. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-left: 5px; border-style: solid; border-color: black gray gray black; }");
    89. }
    90. if (x == 8 && y == 0){
    91. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-right: 5px; border-style: solid; border-color: black black gray gray; }");
    92. }
    93. if (x == 8 && y == 8){
    94. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black black; }");
    95. }
    96. if (x == 0 && y == 8){
    97. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-left: 5px; border-style: solid; border-color: gray gray black black; }");
    98. }
    99. if (x == 5 || x == 2){
    100. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-right: 5px; border-style: solid; border-color: gray black gray gray; }");
    101. }
    102. if (y == 2 || y == 5){
    103. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-style: solid; border-color: gray gray black gray; }");
    104. }
    105. if (x == 2 && y == 8){
    106. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
    107. }
    108. if (x == 5 && y == 8){
    109. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
    110. }
    111. if ( ( x == 2 || x == 5 || x == 8 ) && y == 5){
    112. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
    113. }
    114. if ( ( x == 2 || x == 5 || x == 8 ) && y == 2){
    115. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
    116. }
    117. if (x == 0 && (y == 2 || y == 5)){
    118. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-left: 5px; border-style: solid; border-color: gray gray black black; }");
    119. }
    120. if ( y == 0 && ( x == 2 || x == 5 ) ){
    121. tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-right: 5px; border-style: solid; border-color: black black gray gray; }");
    122. }
    123.  
    124.  
    125.  
    126. pInnerGrid->addWidget( tile, grid_y, grid_x);
    127.  
    128. // inedex of tile in tiles array
    129. int tileIndex = y * 9 + x;
    130. tiles [tileIndex] = tile;
    131. }
    132. }
    133.  
    134. // Generate random digits with solvable solution ( 20 digs )
    135. random_position(20, random_pos_value);
    136. for (int i = 0;i < 20; i++){
    137. tiles[random_pos_value[i].first]->setText(QString::number(random_pos_value[i].second));
    138. tiles[random_pos_value[i].first]->setReadOnly(true);
    139. }
    140. // solve button
    141. Solve = new QPushButton( "Solve", this);
    142. connect( Solve, SIGNAL(released()), this, SLOT(on_Solve_clicked()) );
    143. pMainLayout->addWidget(Solve, 5, 0);
    144.  
    145. setLayout( pMainLayout );
    146. }
    147. // .......
    To copy to clipboard, switch view to plain text mode 

    I want to make my whole widget bigger, it is very small if you compare it to the window, and i attached Screenshot to see how it looks
    Attached Images Attached Images
    Last edited by laurynas2003; 12th April 2020 at 18:21.

Similar Threads

  1. Replies: 6
    Last Post: 21st April 2019, 01:28
  2. Random Generator for Androidx86 in Qt5
    By alexo in forum Newbie
    Replies: 1
    Last Post: 8th September 2014, 07:30
  3. Replies: 1
    Last Post: 7th April 2010, 17:26
  4. Random No Generator in C/C++
    By ankurjain in forum General Programming
    Replies: 1
    Last Post: 6th July 2006, 12:33

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.