r.Parrot1
r.Parrot1

Reputation: 67

Check values against contents of 2D array

I am trying to loop through my 2D array which is of type Cell Cell m_grid[9][9] - when the current value in the array is not equal to the value that is in the row, column or 3x3 block of the array, I need to add this to my int m_candidateList[9] array. The 2D array itself contains an unsolved sudoku puzzle in a 9x9 format.

How do I access the rows, columns of the 2D array so I can check them against the current value that the array is at in the loop?

This is in my SudokuPuzzle.cpp file where I am wanting to get the current puzzle value and check it against all the values in that row, column and 3x3 block of the sudoku puzzle.

for (int i = 0; i < 9; i++)
{
    for (int j = 0; j < 9; j++)
    {
            
        //if number doesn't appear in row
        //if number doesn't appear in col
        //if number doesn't appear in 3x3
        //add number to candidate list
        
    }
}

My Cell.cpp which holds data member for each individual value in the puzzle

Cell::Cell(void) {}
Cell::~Cell(void) {}

void Cell::SetValue(int value)
{
    m_value = value;

    if (m_value = 0)
    {
        m_given = true;
    }
}

And Cell.h

#pragma once
class Cell
{
public:
    Cell(void);
    ~Cell(void);

    void SetValue(int n);

private:

    int m_candidateList[9];
    int m_value;
    bool m_given;

};

Upvotes: 1

Views: 75

Answers (2)

Muhamad Gafar
Muhamad Gafar

Reputation: 409

Most of this answer is just taken from the user that commented.

I can see that you have have a setter function SetValue(int n) but to be able to access what you already have stored then you will also need a setter function so that you can make a call to your Cell object and have access to this value. Let's call this setter function getValue().

Notice that getValue returns a boolean but could assign a value to the int passed by reference. This allows us to use the getValue function to do 2 things, firstly it checks that a value has been assigned to this Cell, and secondly if the value has been assigned then you pass it back via the variable that you passed a reference.

Cell.cpp

Cell::Cell(void) {}
Cell::~Cell(void) {}

void Cell::SetValue(int value)
{
    m_value = value;

    if (m_value = 0)
    {
        m_given = true;
    }
}

bool Cell::getValue(int& n)
{
    if(m_given)
        n = m_value;

    return m_given;
}

void Cell::insertCandidate(int n)
{
    m_candidateList[m_candidate_counter++] = n;
}

Cell.h

#pragma once
class Cell
{
public:
    Cell(void);
    ~Cell(void);

    void SetValue(int n);
    bool getValue(int& n);

    void insertCandidate(int n);

private:

    int m_candidate_counter = 0;
    int m_candidateList[9];
    int m_value;
    bool m_given;

};

Now using the getter you are able to loop through the 2d array of cells as you now have a getter function.

SudokuPuzzle.cpp

for (int i = 0; i < 9; i++)
{
    for (int j = 0; j < 9; j++)
    {
        for (int number = 1; number <= 9; number++)
        {
            if(!exists_in_row(number, i) && 
               !exists_in_column(number, j) && 
               !exists_in_square(number, i, j))
            {
                m_grid[i][j].insertCandidate(number);
                return;
            }
        }
    }
}

You will also need to create the helper functions. E.g. in SudokuPuzzle.cpp

bool SudokuPuzzle::exists_in_row(int number, int row)
{
    int number_from_cell = 0;

    for (int col = 0; col < 9; ++col)
    {        
        if(m_grid[row][col].GetValue(number_from_cell) && number_from_cell == number)
             return true;
    }
    return false;
}

bool SudokuPuzzle::exists_in_column(int number, int col)
{
    int number_from_cell = 0;
    
    for (int row = 0; row < 9; ++row)
    {       
        if(m_grid[row][col].GetValue(number_from_cell) && number_from_cell == number)
             return true;
    }
    return false;
}

bool SudokuPuzzle::exists_in_square(int number, int row, int col)
{
    int row_start = 3*(row/3);
    int col_start = 3*(col/3);
    int number_from_cell = 0;

    for (int r = 0; r < 3; ++r)
    {
        for (int c = 0; c < 3; ++c)
        {
            if (m_grid[row][col].GetValue(number_from_cell) && number_from_cell == number)
              return true;
        }
    }
    return false;
}

Also you are making your life a bit difficult by creating the Cell object and having a 2D array of Cells. The answer would have probably been a lot more straight forward if you just used a type int m_grip[9][9]. Also for m_candiateList I didn't make any change to this data type but please look into std::set to avoid storing duplicates and also avoiding memory problems. E.g. Imagine you don't add protection code and you try to access m_candidateList[10], this will give you a segmentation fault.

Upvotes: 1

john
john

Reputation: 87944

So I'll just try to outline the logic. I'll ignore the Cell class because I don't have full details of it and I'll just assume your grid is an array of integers.

The thing that is really important is to break up what is quite a complex piece of code into separate functions. That will make the code easier to write, easier to debug and easier to understand.

Here's my take, only suggestions

for (int row = 0; row < 9; row++)
{
    for (int col = 0; col < 9; col++)
    {
        for (int number = 1; number <= 9; number++)
        {
            if (!number_in_row(number, row) &&
                !number_in_column(number, col) &&
                !number_in_square(number, row, col))
            {
                 add_number_to_candidates(number, row, col);
            }
        }
    }
}

bool number_in_row(int number, int row)
{
     for (int col = 0; col < 9; ++col)
          if (m_grid[row][col] == number)
              return true;
     return false;
}

Function number_in_column is very similar. Number_in_square is the most complex one.

bool number_in_square(int number, int row, int col)
{
    // calculate start of 3x3 square
    int row_start = 3*(row/3);
    int col_start = 3*(col/3);
    for (int r = 0; r < 3; ++r)
        for (int c = 0; c < 3; ++c)
          if (m_grid[row_start + r][col_start + c] == number)
              return true;
    return false;
}

I've left out the add_number_to_candidates function as I'm not sure how to write that with the information given. Hopefully it will be clear to you.

I hope that gives you some ideas. All code completely untested.

Upvotes: 2

Related Questions