Я знаю, что людям не нравятся домашние задания, однако я работаю над этим слишком долго, уже более 6 часов, и у меня нет идей, и по какой-то причине мой валидатор судоку продолжает возвращать неправильное логическое значение, это должна быть часть sudokuisvalid, но я понятия не имею, почему сейчас он не возвращает правильное логическое значение
переписал код, но, к сожалению, я не знаю другого способа сделать эту часть, по-прежнему ничего, я перепроверил все остальные части, проверил getRow, работает отлично, проверил getColumn, работает отлично, проверил getSection, работает отлично, проверил include1To9, тоже работает отлично это что-то в части sudokuIsValid, но я не могу понять, что с этим не так, кажется, что он обращается к getRow, getColumn, getSection и incudes1To9 нормально, и он отображает логическое значение, но говорит только правду...
пытался сделать что-то на основе того, что кто-то сказал здесь, он все равно делает это верно, хотя предполагалось, что это ложь.
Ошибка: sudokuIsValid возвращает true для допустимого образца головоломки (переменная головоломка). Ошибка 2: sudokuIsValid возвращает true для других допустимых головоломок, не предусмотренных в задаче.
Я очень надеюсь, что это что-то очевидное, но я слишком устал, и я новичок в программировании, поэтому я вставлю свой код и посмотрим, что вы думаете!
Я попытался выделить то, что, по моему мнению, является проблемной областью, жирным шрифтом, просто обведя ее звездочкой.
function getRow(puzzle, row) {
// WRITE YOUR CODE HERE
return puzzle[row]
}
function getColumn(puzzle, col) {
// WRITE YOUR CODE HERE
return puzzle.map(row=>row[col])
}
function getSection(puzzle, x, y) {
// WRITE YOUR CODE HERE
let section = []
for(i = 3 * y; i < 3 * y + 3; i++){
for(j = 3 * x; j < 3*x+3 ; j++){
section.push(puzzle[i][j])
}
}
return section
}
function includes1To9(arr) {
// WRITE YOUR CODE HERE
for (i = 0; i < arr.length; i++){
for (j = 0; j < arr.length; j++){
if (j != i){
if (arr[i] === arr[j]){
return false
}
}
}
}
return true
}
function sudokuIsValid(puzzle) {
for (let i = 0; i < 9; i++){
if (includes1To9(getRow) === false){
return false
}
}
for (let i= 0; i < 9; i++){
if (includes1To9(getColumn) === false){
return false
}
}
for(let i = 0; i < 3; i++){
for(let j =0; j < 3; j++){
if (includes1To9(getSection) === false){
return false
}
}
}
return true
}
// example of the puzzle that is being input and returning true, should return false
let puzzleTwo = [[ 8,9,5, 7,4,2, 1,3,6 ],
[ 8,7,1, 9,6,3, 4,8,5 ],
[ 4,6,3, 5,8,1, 7,9,2 ],
[ 9,3,4, 6,1,7, 2,5,8 ],
[ 5,1,7, 2,3,8, 9,6,4 ],
[ 6,8,2, 4,5,9, 3,7,1 ],
[ 1,5,9, 8,7,4, 6,2,3 ],
[ 7,4,6, 3,2,5, 8,1,9 ],
[ 3,2,8, 1,9,6, 5,4,7 ]];
console.info(sudokuIsValid(puzzleTwo)) // returns true should be false
console.info(includes1To9([8,8,4,9,5,6,1,7,3])) // returns false like it should
У вас есть код функции, написанный неправильно в valid.push(getrow(puzzle,i)), это должен быть getRow()
Не могли бы вы добавить пример головоломки, в которой возникает ошибка?
только что исправлена проблема, когда там, где я должен был быть, была цифра 1, и проблема с получением, но все еще не работало правильно
Добавьте ведение журнала и посмотрите Как мне задавать вопросы по домашнему заданию и отвечать на них?.
У вас также есть ошибка в if (includes1To9(valid[i] === false)){return false}"
, потому что valid[i] === false
возвращает логическое значение, а функция include1To9 ожидает массив.
Я также рекомендую использовать циклы for-of или forEach вместо циклов for, чтобы код стал более читабельным.
Если хотите, вы всегда можете поискать это на каких-нибудь ИТ-сайтах (рекомендую W3Schools). Работает ли это после исправления проблемы, о которой я упоминал ранее? :)
Чтобы добавить к тому, что говорил @RedApple, для этого конкретного случая, похоже, вам следует иметь if (include1to9(valid) === false)
, если ваша цель — проверить возвращаемое значение include1to9
с массивом valid
в качестве входных данных. P.S. также вам не нужен цикл for для циклического прохождения valid
, поскольку вы уже делаете это в функции include1to9()
Можете ли вы опубликовать полную информацию об ошибке, которую вы получаете, если таковая имеется, и, возможно, некоторые тесты, которые вы пытаетесь выполнить? Кроме того, совет по коду: поскольку вы пытаетесь вернуть false, если include1to9(valid)
является ложным, а в противном случае — true, вы можете вообще опустить оператор if-else, просто выполнив return include1to9(valid);
Приведите пример значения, которое вы регистрируете.
Домашние задания допустимы, если вы задаете конкретный вопрос и демонстрируете свои усилия по исследованию и отладке. Как отлаживать небольшие программы StackOverflow — это сайт вопросов и ответов для конкретных вопросов о реальном коде; «Я написал какой-то глючный код, который не могу исправить» — это не вопрос, это история, и даже не интересная история.
«Я пытался создать еще что-нибудь, чтобы посмотреть, решит ли это проблему, но все, что я сделал, это провалил проблему». Менее интересно то, что вы случайно пытались решить проблему. Гораздо интереснее то, что вы узнали, пройдя построчно код с помощью отладчика. Какая именно строка имела неожиданное поведение (и я не имею в виду возвращаемое значение функции)?
Установите точку останова return includes1To9(valid)
в отладчике и проанализируйте valid
. Я думаю, это одно неожиданное значение. Вам вообще не нужен let valid = []
. Вы можете сразу вернуть false, если одно из условий не выполнено.
Существует фундаментальная проблема в getSection()
и в том, как вы обрабатываете valid
в sudokuIsValid()
: getSection()
возвращает массив, и вы помещаете его в valid
, который уже содержит значения внутри puzzle
, поскольку вы помещаете перед вызовом getSection()
функции getRow()
и getColumn()
. Я предлагаю вам переосмыслить то, что вы пытаетесь сделать, и, возможно, добавить новую функцию, чтобы лучше разделить проверку раздела и столбца.
Теперь это работает, не так ли?
@CcmU Возможно, я неправильно понял, что вы сказали, я пытался установить значения строки в новую переменную, то же самое со столбцом и разделом, затем поместил это в действительную переменную, но это тоже не сработало, я собираюсь обновить свою код, чтобы вы могли увидеть изменения, я, наверное, тоже сделал это ужасно
@RedApple, к сожалению, нет
Первое, чему вам следует научиться, — это пользоваться отладчиком. Я преподаю это на первой или второй неделе. Если вы не знаете, что такое отладчик, изучите его, прежде чем продолжить курс. Программистам не нужно догадываться, в чем заключаются проблемы. Им не придется находить их методом проб и ошибок или с помощью отладочных результатов. Они могут просматривать каждую строку, каждое выражение, анализировать и манипулировать значениями. Что такое отладчик и как он может помочь мне диагностировать проблемы?
ИМХО, если в курсе вас попросят использовать валидатор судоку до того, как он научит вас использовать отладчик, это ужасный вводный курс. Я бы поискал другой.
Как улучшить ваш код и решить вашу проблему:
Вам не обязательно иметь список valid
. Вы можете проверить каждую возможность, и если функция вернет false
, вы можете немедленно return false
. В конце функции вы можете сделать return true
. это решит вашу проблему, поскольку в вашем includes1to9
вы проверяете все строки, столбцы и подсетки. это означает, что вы проверяете, есть ли во всей головоломке числа от 1 до 9, и если вы найдете два одинаковых элемента, вы выходите. например, если у вас есть такая головоломка-судоку:
900 000 000
000 000 000
000 000 000
000 000 000
000 000 000
000 000 000
000 000 000
000 000 000
000 000 009
он вернет истину, потому что (если мы не проверяем нули) в головоломке две девятки. 2 девятки в двух рядах, 2 девятки в двух столбцах, 2 девятки в двух подсетках = 6 девяток...
Примечание: - используйте Наборы (если вы их выучили). Они не могут содержать повторяющиеся элементы, например. если у вас есть массив 0, 1, 2, 2, 2, 5, 6, 7, 8, 9
(дубликаты 2
), то он даст вам 0, 1, 2, 5, 6, 7, 8, 9
. Затем вы можете сравнить массив с набором и посмотреть, имеют ли они одинаковый размер. Вы можете использовать цикл double-for. хотя это нормально, Sets упростит ваш код. если вы не узнали о наборах или не понимаете их, не используйте их.
Итак, ваш код должен выглядеть так:
function SudokuIsValid(sudoku){
for row {
if (row is not valid){
return false
// return false exits/stops the function.
// No code after this will be run in this function.
}
}
// if code has gotten here, that means that all rows are valid.
for column {
if (column is not valid){
return false
}
}
// if code has gotten here, that means all columns are valid
for subgrid {
if (subgrid is not valid){
return false
}
}
// if code has gotten here, that means all rows, columns and subgrids are valid.
// we can return true then
return true
}
@RipperReborn, можешь показать мне, как ты пытался это сделать? (код)
я обновил код в сообщении, где находится старая функция sudokuisvalid
@RipperReborn вы передаете функцию includes1to9
. Вам нужно вызвать туда. Что вы делаете: includes1to9( getRow )
. Вам стоит сделать includes1to9( getRow(puzzle, row) )
. и т. д. для строки, столбца, подсетки.
омг, спасибо огромное, я занимался этим около 10 часов и наконец-то получилось!!,
Как объяснено в комментариях, есть некоторая проблема в том, как вы подошли к проблеме: как вы написали, getSection()
возвращает массив, и вы помещаете его в действительный, который сам по себе является массивом, уже содержащим значения внутри puzzle
, поскольку getRow()
и getColumn()
помещаются в него, прежде чем нажать getSection()
.
Вот мой подход, основанный на вашем коде, я настоятельно рекомендую вам взять и посмотреть, каковы различия между указанным подходом и вашим. Вы можете почерпнуть вдохновение из этого кода и попытаться воссоздать свой собственный в качестве упражнения.
function getRow(puzzle, row) {return puzzle[row]};
function getColumn(puzzle, col) {return puzzle.map(row => row[col])};
function getSection(puzzle, x, y) {
// Initializing the section matrix
let section = [[],[],[]];
for(i = 3 * x; i < 3 * x + 3; i++){
for(j = 3 * y; j < 3*y+3 ; j++){
// Pushing into the matrix 3x3 each element (0 % 3 == 0, 3 % 0 == 0, etc...)
section[i%3].push(puzzle[i][j]);
}
}
return section;
};
function arrayIncludes1To9(arr) {
for (let i = 1; i < 10; i++) {
// If i is not in the array return false
if (!arr.includes(i)) {
return false;
}
}
// True otherwise
return true;
}
function sectionIncludes1To9(matr) {
let arr = [];
// Getting each matrix as an array to reutilize arrayIncludes1To9()
matr.forEach(element => {
element.map(x => arr.push(x));
});
return arrayIncludes1To9(arr);
}
function sudokuIsValid(puzzle) {
let columns = [];
let rows = [];
// Assuming all the sections are correct
let sections = true;
for (let i = 0; i < 10; i++) {
columns.push(getColumn(puzzle, i));
rows.push(getRow(puzzle, i));
}
// Cycling through each section until one is not valid
for (let i = 0; i < 3 && sections; i++) {
for (let j = 0; j < 3 && sections; j++) {
if (!sectionIncludes1To9(getSection(puzzle, i, j))) {
sections = false;
}
}
}
// Returning true if columns, rows and sections are valid; false otherwise
return arrayIncludes1To9(columns) && arrayIncludes1To9(rows) && sections;
}
let puzzleTwo = [[ 8,9,5, 7,4,2, 1,3,6 ],
[ 8,7,1, 9,6,3, 4,8,5 ],
[ 4,6,3, 5,8,1, 7,9,2 ],
[ 9,3,4, 6,1,7, 2,5,8 ],
[ 5,1,7, 2,3,8, 9,6,4 ],
[ 6,8,2, 4,5,9, 3,7,1 ],
[ 1,5,9, 8,7,4, 6,2,3 ],
[ 7,4,6, 3,2,5, 8,1,9 ],
[ 3,2,8, 1,9,6, 5,4,7 ]];
console.info(sudokuIsValid(puzzleTwo)); // false
я не думал о добавлении других функций для хранения значений раздела, но извините за вопрос, что такое часть element.map? я нигде не вижу элемента, если только не просматриваю его
@RipperReborn Я добавил комментарии, чтобы лучше объяснить код, но, чтобы ответить, имейте в виду, что matr
— это массив массивов, поэтому я циклически просматриваю каждый массив внутри matr
и для каждого элемента помещаю их в простой массив, объявленный ранее. Это просто для повторного использования arrayIncludes1To9()
и без повторной проверки, поскольку и эта достаточно хороша.
Если вы проверите консоль, вы увидите ошибку, объясняющую, что
getrow
не существует. Имена функций JS чувствительны к регистру.