So A friend and I are new to C++ and we are trying to create a sudoku project and are trying to figure out different ways to do so. Right now we are stuck at the repetition checking. I was wondering if anyone could help us out?? We are trying to figure out how to check a row of numbers for repetition our code so far for the checking is as follows...

#include <iostream>
#include <ctime>
using namespace std;

char rows(int grid[][9], int rows, int cols, char& choice)
{
  //Variables
  int i, j, k=1, strTime, stpTime, totTime;
  bool repChecker = false;
  srand (time (0));

  strTime = time(0); //Initializes a starting time

  //Creates the 2D array with out repititons in the rows
  for(i=0; i<9; i++)
  {
     for(j=0; j<9; j++)
     {
       grid[i][j] = rand( )%9 + 1;

         if(grid[i][j]==grid[i][j-k])
           --j;
     }                         // inner for loop
  }

  stpTime = time(0);  //Initializes a stopping time
  totTime = stpTime - strTime; //Calculates the total time used to create the random grid

  cout << "It took a total of " << totTime << " to create a random 9 X 9 grid.";
  cout << "\n\nIf you would like to create another grid type \"W\" otherwise type \"M\" to go back to the main menu: ";
  cin >> choice;

return 0;
}

any help would be appreciated thanks :-)

Recommended Answers

All 12 Replies

You are trying to create a Sudoku puzzle for a player to solve, or do you already have a puzzle and you are creating a function to see whether it is "legal" (no repeats)? Checking the puzzle for no repeats is a lot easier than creating a puzzle.

Your description of the problem suggests you are checking a puzzle that is already there, but your cout statements suggests you are creating the puzzle, as does your use of rand () .

Regardless, even if you are creating a puzzle, you may do well to develop a function that checks for repeats and have that be a separate function:

bool CheckLegality (char grid[][9])
// returns true if legal/no repeats
// returns false if there are repeats in a row, column, or box
{
    // code here
}

Is this what you are trying to do (the above function)? No random number generation would occur in the above function. It could be called numerous times from your other function where you are creating the puzzle. Sudoku puzzle generation can be a complex task.

This is supposed to be the function that checks only the rows for repetition. We are trying to create a function that will generate and check at the same time however, so to answer your question "we" are creating the puzzle. There is a menu that the user is taken to that asks them 4 options

1) Random 9x9 grid
2) Random 9x9 with no reps in the rows (this is where we are stuck)
3) Rand 9x9 with no reps in rows or colms
4) Sudoku

so as for calling the function to check, is in fact the function we are trying to create. If that makes more sense.....

This is supposed to be the function that checks only the rows for repetition. We are trying to create a function that will generate and check at the same time however, so to answer your question "we" are creating the puzzle. There is a menu that the user is taken to that asks them 4 options

1) Random 9x9 grid
2) Random 9x9 with no reps in the rows (this is where we are stuck)
3) Rand 9x9 with no reps in rows or colms
4) Sudoku

so as for calling the function to check, is in fact the function we are trying to create. If that makes more sense.....

O.K., why not set up a boolean array of size 10 (must hold indexes 1 through 9), initial it all to false, then go through each cell you need to check and flag that index as true when you hit the number the cell contains. If it's already true, you have a duplicate, so return false. Otherwise if you go through all the cells with no duplicates, return true.

bool used[10];
// initialize array to false
for (int i = 0; i < 9; i++)
{
    // check cell i's contents against used array.  If already true,
    // return false.  If false, flag as true.
}

return true;

I remeber doing a similar program a few months ago as a joke with my friend. Our teacher asked us to create a soduku solver so we created an algorithm to test every possible combination of ansewers in a number until it was correct. What you are trying to do(or atleast what I think you are) is create a row of unique numbers while checking the column is unique. However, we used a structure with checksums and arrays for each row/column which might be a little more than you want to get into. But anyways, for your purposes, you are not checking the entire row/column; only the previous element, which makes your problem very simple. Just make two for loops to check the current column and row of the element. In addition, you will want to set the whole array to 0 if you use this method:

for(x = 0; x < 9; x++) {
if(i != x) {
if(grid[i][j] == grid[x][j])
j--;
x = 9;
}
}

just repeat this loop twice for 'j' and it will check the corresponding rows and columns. However, you will also need to make a flag to ignore the second loop if the first one fails so j is not subtracted twice. I hope this helps!

I understand what you are saying but I am not 100% on how exactly I execute it here are the additions I have made

char rows(int grid[][9], int rows, int cols, char& choice)
{
  //Variables
  int i, j, k, strTime, stpTime, totTime;
  grid[0][0] = 0;
  bool repChecker = false;
  srand (time (0));

  strTime = time(0); //Initializes a starting time

  //Creates the 2D array with out repititons in the rows
  for(i=0; i<9; i++)
  {
     for(j=0; j<9; j++)
     {
       grid[i][j] = rand( )%9 + 1;

        for(k = 0; k < 9; k++)
        {
          if(i != k)
           {
             if(grid[i][j] == grid[k][j])
               j--;

             k = 9;
           }
        }

     }                         // inner for loop
  }

I'm trying to leave some of the code for you to do, but to clarify; you need to check both rows and columns. In this case, you are only checking i. What you need to do is create a second for loop to check j. However here is the problem I am talking about(and was probally vague on) Say j = 5 and you go through your first loop, which checks rows, and find a repetition, j is now 4. After this loop you have a second loop to check columns, and if this also fails, j is now = to 3. So what you need to do is make a flag that prevents the program from entering the second loop if the first check failed.

if(grid[i][j] == grid[k][j])

Looks like you are comparing column cells here, not row cells. The first index is the row number, the second index is the column number, correct? The column number is the same above and the row number is different, so you're comparing above to make sure the column has no duplicates. That's not what you are intending, is it? You are intending to check for duplicates in the row here, correct?

For the purposes of two dimensional arrays, the "rows" and "columns" are declared, in a sense, by the user; depending on which one he or she calls first. For instance, you can do

for(i = 0; i <  9; i++)
   for(j = 0; j < 9; j++) {
       grid[i][j]=x;
       x++;
}

//or

for(j = 0; j <  9; j++)
   for(i = 0; i < 9; i++) {
       grid[i][j]=0;
       x++;
}

both loops will give the same output if called in the same way as they are declared(i first or j first). That being said, he needs to check for both rows and columns for his program

Understand ;-) you don't want to write the code for us and I don't expect you too, thank you for clarifying that though. We will have to play around with this for a while, thanks for the help :-)

so we managed to get the rows to work and even tried it for the columns and it worked as well....now we have in interesting problem. When we tried setting it up so it does both of them together we get stuck in an infinite loop and we are not sure as to why...here is the new code:

#include <iostream>
#include <ctime>
using namespace std;

char print(int grid[][9], int, int);

char latinsquare(int grid[][9], int rows, int cols, char& choice)
{
  //Variables
  int i, j, k, h, count, strTime, stpTime, totTime;
  grid[9][9] = 0;
  bool repCheck;
  srand (time (0));

  strTime = time(0); //Initializes a starting time

  //Creates the 2D array without repititons in the rows
  for(i=0; i<9; i++)
  {
     for(j=0; j<9; j++)
     {
      do{
        grid[i][j] = rand( )%9 + 1;
        repCheck = false;
        count =  0;

         for(k = 0; k < j; k++)            // K Loop for Row Checking
         {
           if(grid[i][j] == grid[i][k])    // Checks for repetitions
            {
             j--;                             // Moves the index back one spot and replaces the number
             repCheck = true;        
             count ++;
            }

           if(count == 100)
           {
             j=0;
             break;
           }
         } //End the row check for loop

         if(repCheck == false)             // Checks if conditions were met in the above check
         for(k = 0; k < i; k++)             // K Loop for Column Checking
         {
           if(grid[i][j] == grid[k][j])        // Checks for repetitions
            {
             j--;                                  // Moves the index back one spot and replaces the number
             repCheck = true;
             count ++;
            }

            if(count == 100)                 //Resets J to 0 so it doesn't get stuck in an infinite loop
            {  
              j=0;
              break;
            }
         } //End the column check for loop
      }while(repCheck == false);    //End While Loop
     } // End j for loop
  } // End i for loop

  stpTime = time(0);  //Initializes a stopping time
  totTime = stpTime - strTime; //Calculates the total time used to create the random grid

  cout << print(grid, 9, 9);

  cout << "It took a total of " << totTime << " seconds to create a random 9 X 9 grid.";
  cout << "\n\nIf you would like to create another grid type \"W\" otherwise type \"M\" to go back to the main menu: ";
  cin >> choice;

return 0;
}

Hmmm, you two are looking far too deeply, there is really no need for a do while at all. You only need three if statements at most(check x, check y, check flag) and four for loops for the array creation portion. But if you are really interested in programming, I suggest looking into a recursive function, rather than resetting count each time. An example would be like

void inc(int x, int y) {
            x ++;
            if(x < y)
            inc(x,y);
}

This example, although crude, gives the basic gist of a recrusive function; it repeatedly calls itself until the parameters are met. If you two are ambitions; try using a recursive function to create your unique grid. Other than that, you two seem to be on the right rack, but remeber to tag && k != j and && j != i to your two if statments respectively. In each of the two cases grid[j] is the exact same thing as grid[k][j] because i is equal to k. I hope this helps, don't give up!

If you simply want the numbers 1 to 9 uniquely randomized in a row, you could load the row with the numbers 1 to 9 and then shuffle it. No need to pick random numbers and check if they've already been picked. That's always something to avoid, if possible.
However, shuffled rows would still have column repetitions. Getting rid of those is the interesting part.
And to time the routine, you might consider the clock() function, as it has better resolution than time().

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.