2016-01-29 7 views
1

Я пишу программу, которая позволяет пользователю играть в головоломки судоку. Каждая головоломка представляет собой 2d массив структур, но я не могу инициализировать массив за один раз. Есть ли способ сделать это без необходимости инициализации каждой части структуры для каждого элемента массива? Вот некоторые из моего кода.C++ Инициализация 2D-массива структур

class Sudoku { 
    protected: 
    struct Puzz { 
     int Ans; 
     // IsClue is used further in the program so the user cannot change the clues given. 
     bool IsClue; 
    }; 
    Puzz Puzzle[9][9]; // I chose a 2D array so represent the 9 rows and columns of a sudoku puzzle 
}; 

Я пробовал некоторые из следующих действий:

Puzzle[][9] = {{0, false, 8, true, 0, false, 6, true, 7, true, 0, false, 0, false, 0, false, 0, false}, //...etc, going on for each row 
Puzzle[9][9] = // etc, etc, but I get an error saying "Expected an expression 

Это единственный способ, чтобы инициализировать каждый элемент сделать

Puzzle[x][y].Ans = x; Puzzle[x][y].IsClue = true/false;? 
+0

Сторона примечания: Некоторые головоломки судоку имеют более одного решения - не говорите игроку, что они ошибаются, если их решение не соответствует ожидаемому. – immibis

+0

Может быть проще иметь массив с размером 9x9 с начальной конфигурацией и отдельный массив 9x9 с тем, что пользователь имеет до сих пор. –

ответ

0

Ниже приведен пример, показывающий, как массив 2 х 2 может быть инициализирован. Я оставлю это вам, чтобы распространить это на массив 9 x 9.

class Sudoku { 
    Sudoku(); 
    protected: 
    struct Puzz { 
     int Ans; 
     bool IsClue; 
    }; 
    Puzz Puzzle[2][2]; 
}; 

Sudoku::Sudoku() : Puzzle{{{0, false}, {1, true}}, {{2, false}, {3, true}}} 
{ 
} 

Сказав, что, возможно, было бы проще создать конструктор по умолчанию Puzz, который делает разумную вещь для большинства объектов, а затем изменить только избранные элементы Puzzle в конструкторе Sudoku «s.

class Sudoku { 
    Sudoku(); 
    protected: 
    struct Puzz { 
     int Ans; 
     bool IsClue; 
     Puzz() : Ans(0), IsClue(false) {} 
    }; 
    Puzz Puzzle[2][2]; 
}; 

Sudoku::Sudoku() 
{ 
    // Change specific elements of Puzzle 
} 
0

Для инициализации двумерного массива, используйте для цикла. Как и в:

for (int i = 0; i < row_count; i++) { 
    for (int j = 0; j < col_count; j++) { 
     item[i][j] = initial_value; 
    } 
} 

Если вы хотите использовать список инициализации, как в приведенном выше, вы можете сделать это, просто обернув каждый экземпляр структуры в скобках. Однако инициализация вашей платы sodoku буквами не является особенно масштабируемым подходом к созданию платы sodoku для игрока. То есть, вместо того, чтобы:

Puzzle puzz[9][9] = {{0, false, 8, true, 0, false, 6, true, 7, true, 0, false, 0, false, 0, false, 0, false, ...}}; 

Вы могли бы использовать:

Puzzle puzz[9][9] = { 
    { // First row 
    {0, false}, // first column 
    {8, true}, // second column 
    ... 
    }, 
    { // Second row 
    ... 
    }, 
    ... 
}; 

Поскольку это C++, хотя, возможно, пожелает рассмотреть отображающий плат с помощью вложенных векторов (то есть vector<vector<Cell>>). Хотя это может быть излишним, особенно для платы Sodoku (особенно если это всегда 9x9), это позволит вам более легко представлять нестандартные размеры досок, а структура векторных данных имеет возможность по умолчанию инициализировать/заполнять всех участников с заранее заданным значением. Однако, как замечают примечания @paddy в комментариях, есть и другие функции (например, std::fill, которые могут использоваться с обычными массивами для обработки распространенных случаев использования.

+1

Или используйте 'std :: fill'. Если значения должны следовать некоторому инкрементному шаблону, возможно, можно использовать 'std :: iota' с пользовательским' operator ++ ', но это, вероятно, слишком велико, а не отличная идея. – paddy

0

Вы можете инициализировать список инициализаторов в C++ 11 или выше :

Puzz Puzzle[2][2] = { 
    { {8, true}, {9, false} }, 
    { {10, true}, {11, false} } 
}; 

Если в классе вы можете по умолчанию построить его таким же образом:

class PuzzHolder { 
    PuzzHolder() : Puzzle{ 
     { {8, true}, {9, false} }, 
     { {10, true}, {11, false} } 
    } { } 

    Puzz Puzzle[2][2]; 
}; 

Хотя, если он очень большой, это может стать довольно запутанна Таким образом, окончательный подход может быть для инициализации. это в петле.

Live example.

1

Проблема заключается в том, что вы пытаетесь присвоить в массив, и это просто не представляется возможным. Вам нужно на самом деле инициализировать это, что-то совершенно другое.

Если вы не возражаете писать много строк, которые почти одинаковы, то вы можете использовать constructor member initializer list. Как, например,

Sudoku::Sudoku() 
    : Puzzle{{...}, {... }, ... } 
{} 

Если только несколько структур в массивах отличаются от значений по умолчанию, которые затем можно установить все записи в массивах с тем же значением по умолчанию, используя, например, std::fill, а затем измените те немногие записи, которые имеют специальные значения.

Смежные вопросы