Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Судоку проверка (https://javascript.ru/forum/misc/71884-sudoku-proverka.html)

shoopik 20.12.2017 07:09

Судоку проверка
 
Здравствуйте, есть задача про судоку, поле 9на9, нужно проверить, чтобы цифры в строках, столбцах и в боксах 3на3 не было повторений цифр.

Нагородил вот тут, сам запутался там: https://jsfiddle.net/bb3o2ohr/

Нужно в итоге вернуть "try again" или "finished".

Допустим есть поле:
[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
  [ 2, 3, 4, 5, 6, 7, 8, 9, 1 ],
  [ 3, 4, 5, 6, 7, 8, 9, 1, 2 ],
  [ 4, 5, 6, 7, 8, 9, 1, 2, 3 ],
  [ 5, 6, 7, 8, 9, 1, 2, 3, 4 ],
  [ 6, 7, 8, 9, 1, 2, 3, 4, 5 ],
  [ 7, 8, 9, 1, 2, 3, 4, 5, 6 ],
  [ 8, 9, 1, 2, 3, 4, 5, 6, 7 ],
  [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ] ]



//Создаю переменные:
  var i; //Для первого цикла
  var j; // Для второго
  var z; // Для цикла в массиве цифр
  var uniq1Arr = []; //Здесь массивы, для строк
  var uniq2Arr = []; // Для колонок
  var uniq3Arr =[]; // Для полей 3 на 3

//Иду циклами, например:

// Здесь проверяю строчки, и пушу каждую цифру строки в массив, если длина массива больше 9, очищаю его.
for(i=0; i<9; i++) {
      for(j=0; j<9; j++) {
          for(z=0; z<uniq1Arr.length; z++) {
              if(uniq1Arr.length >9) uniq1Arr = [];
              if(board[i][j] == uniq1Arr[z]) {
              return "Try again!";   
              }
              uniq1Arr.push(board[i][j]);
          }

// Здесь проверяю колонки, и пушу каждую цифру колонки в массив, если длина массива больше 9, очищаю его.
for(i=0; i<9; i++) {
      for(j=0; j<9; j++) {
          for(z=0; z<uniq2Arr.length; z++) {
              if(uniq1Arr.length >9) uniq2Arr = [];
              if(board[j][i] == uniq2Arr[z]) {
              return "Try again!";   
              }
              uniq1Arr.push(board[j][i]);
          }

//Поля 3на3 проверяю так... 
for(i=0; i<3; i++){
      for(j=0; j<3; j++) {
       for(z=0; z<uniq3Arr.length; z++) {
              if(board[i][j] == uniq1Arr[z])   return "Try again!";       
          }
          if(board[i][j] == uniq3) return "Try again!" ;
          uniq3 = board[i][j];
      }
  }
  
  
  uniq3 = 0;
  uniq3Arr = [];
  for(i=3; i<6; i++){
      for(j=0; j<3; j++) {
       for(z=0; z<uniq3Arr.length; z++) {
              if(board[i][j] == uniq3Arr[z])   return "Try again!";       
          }
          if(board[i][j] == uniq3) return "Try again!" 
          uniq3 = board[i][j]
      }
  }
   uniq3 = 0;
   uniq3Arr = [];
  for(i=6; i<9; i++){
      for(j=0; j<3; j++) {
       for(z=0; z<uniq3Arr.length; z++) {
              if(board[i][j] == uniq3Arr[z])   return "Try again!";       
          }
          if(board[i][j] == uniq3) return "Try again!" 
          uniq3 = board[i][j]
      }
  }
//Если всё прошло, победа
 return "Finished!";

ksa 20.12.2017 08:29

Цитата:

Сообщение от shoopik
нужно проверить, чтобы цифры в строках, столбцах и в боксах 3на3 не было повторений цифр.

Чтобы в каждой строке/столбце не было повторений? Или вообще одна цифра могла встретиться только раз в строках или столбцах "бокса"?

Пройдись по тем 9 боксам (циклом)... Пусть некая функция проверит текущий бокс, удовлетворяет он условиям или нет. В ней два цикла:
- по строкам
- по столбцам
Для проверки можно использовать "пустой" объект...

Вроде все просто. А ты там циклов наворотил - капец! :blink:

shoopik 20.12.2017 09:43

Цитата:

Сообщение от ksa (Сообщение 473271)
Чтобы в каждой строке/столбце не было повторений? Или вообще одна цифра могла встретиться только раз в строках или столбцах "бокса"?

Пройдись по тем 9 боксам (циклом)... Пусть некая функция проверит текущий бокс, удовлетворяет он условиям или нет. В ней два цикла:
- по строкам
- по столбцам
Для проверки можно использовать "пустой" объект...

Вроде все просто. А ты там циклов наворотил - капец! :blink:

Чтобы в каждой строке/столбце не было повторений, и внутри боксов 3на3.

По строкам/строкам прохожусь, как для проверки использовать пустой объект ?
И как лучше проверить циклами сами боксы 3 на 3 ?

void() 20.12.2017 10:19

Можно попробовать каждую строку бить на три части. Если остаток от деления на 3 == 0, то передать в функцию индекс строки и текущий индекс элемента.

for(var j = 0; j <= 9; j++){
			arr[j].forEach(function(item, i) {
				if(i % 3 == 0 && i != 0){
					myFunc([arr[j], i]); 
				}
			});
		}


И в функции на основе принятых параметров сформировать массив, в котором проверить на совпадения. Тем самым уже проверены строки, осталось дело за столбцами.

function myFunc(arr){
			var arr2 = [arr[0][arr[1]], arr[0][arr[1]-1], arr[0][arr[1]-2]];
			var uni = arr2.filter(function(elem, pos) {
				return arr2.indexOf(elem) == pos;
			});

			if(uni.length < 3){
				alert('Найдено совпадение');
			}
		}


Чуть криво сделал, это просто идея, мож пригодится или натолкнет на мысль)

Dilettante_Pro 20.12.2017 10:47

shoopik,
Поскольку при игре ставится при каждом ходе одна цифра, то и проверять нужно только те строки/столбцы и блок, в которых находится эта цифра.

shoopik 20.12.2017 11:03

Цитата:

Сообщение от Dilettante_Pro (Сообщение 473282)
shoopik,
Поскольку при игре ставится при каждом ходе одна цифра, то и проверять нужно только те строки/столбцы и блок, в которых находится эта цифра.

Там сразу всё поле даётся, заполненное :)

ksa 20.12.2017 11:32

Цитата:

Сообщение от shoopik
как для проверки использовать пустой объект ?

Перед проверкой создаешь пустой объект...
var o={};

А когда берешь очередного "подопечного" можно быстро проверить, был такой или нет
if (o[a[i][j]]) {
   return false;
} else {
   o[a[i][j]]=true;
};

ksa 20.12.2017 11:35

Цитата:

Сообщение от shoopik
как лучше проверить циклами сами боксы 3 на 3 ?

Передавай в проверяющую функцию "верхнюю точку" бокса, а там обычные циклы от 0 до 2... По строкам и столбцам.

ksa 20.12.2017 11:57

Цитата:

Сообщение от shoopik
Чтобы в каждой строке/столбце не было повторений, и внутри боксов 3на3.

Оно?

var arr=[ 
	[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
	[ 2, 2, 4, 5, 6, 7, 8, 9, 1 ],
	[ 3, 4, 5, 6, 7, 8, 9, 1, 2 ],
	[ 4, 5, 6, 7, 8, 9, 1, 2, 3 ],
	[ 5, 6, 7, 8, 9, 1, 2, 3, 4 ],
	[ 6, 7, 8, 9, 1, 2, 3, 4, 5 ],
	[ 7, 8, 9, 1, 2, 3, 4, 5, 6 ],
	[ 8, 9, 1, 2, 3, 4, 5, 6, 7 ],
	[ 9, 1, 2, 3, 4, 5, 6, 7, 8 ] 
];
for (var i=0; i<arr.length; i++) {
	var y=Math.floor(i/3)*3;
	var x=(i%3)*3;
	var ok=box(y,x);
	if (!ok) {
		alert('Ошибка!');
		break;
	};
};
if (ok) {
	alert('Все отлично.');
};
function box(Y,X) {
	for (var i=0; i<3; i++) {
		var o={};
		for (var j=0; j<3; j++) {
			var val=arr[Y+i][X+j];
			if (o[val]) {
				alert(Y+' - '+X);
				return false;
			} else {
				o[val]=true;
			};
		};
	};
	for (var i=0; i<3; i++) {
		var o={};
		for (var j=0; j<3; j++) {
			var val=arr[Y+j][X+i];
			if (o[val]) {
				alert(Y+' - '+X);
				return false;
			} else {
				o[val]=true;
			};
		};
	};
	return true;
};

рони 20.12.2017 12:14

судоку проверка
 
шифровка из центра ... :)

<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>

  <script>
  var chec = function() {
  for (var g = [], b = [], c = [], d = [], e = [], h = [], f = [], a = 0; 81 > a; a++) {
    a % 9 || (b = [], h.push(b)), b.push(a), 9 > a ? f.push([a]) : f[a % 9].push(a), a % 3 || a % 27 || (c = [], d = [], e = [], g.push(c, d, e)), [c, d, e][a % 9 / 3 | 0].push(a);
  }
  var k = [].concat(g, h, f);
  return function(a) {
    a = [].concat.apply([], a);
    return k.every(function(b) {
      var c = {};
      return b.every(function(b) {
        b = a[b];
        c[b] = (c[b] || 0) + 1;
        return 2 > c[b];
      });
    });
  };
}();

var board =  [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
  [ 2, 3, 4, 5, 6, 7, 8, 9, 1 ],
  [ 3, 4, 5, 6, 7, 8, 9, 1, 2 ],
  [ 4, 5, 6, 7, 8, 9, 1, 2, 3 ],
  [ 5, 6, 7, 8, 9, 1, 2, 3, 4 ],
  [ 6, 7, 8, 9, 1, 2, 3, 4, 5 ],
  [ 7, 8, 9, 1, 2, 3, 4, 5, 6 ],
  [ 8, 9, 1, 2, 3, 4, 5, 6, 7 ],
  [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ] ];

alert(chec(board)); //false
board =  [
    [8, 4, 5, 6, 1, 9, 3, 2, 7],
    [1, 3, 2, 4, 5, 7, 6, 9, 8],
    [7, 6, 9, 8, 3, 2, 5, 4, 1],
    [5, 9, 6, 2, 8, 1, 7, 3, 4],
    [4, 8, 3, 5, 7, 6, 2, 1, 9],
    [2, 7, 1, 3, 9, 4, 8, 5, 6],
    [3, 5, 7, 9, 4, 8, 1, 6, 2],
    [6, 1, 4, 7, 2, 5, 9, 8, 3],
    [9, 2, 8, 1, 6, 3, 4, 7, 5]
]
alert(chec(board));//true
  </script>
</head>

<body>
<div id="slider"></div>

</body>
</html>

рони 20.12.2017 12:15

ksa,
твой вариант только для
Цитата:

Сообщение от ksa
внутри боксов 3на3

?
а строки и столбцы?

ksa 20.12.2017 13:32

рони, я не особо знаком с Судоку... :cray: Т.ч. "как надо" я не знаю...
ТС сказал про "боксы" - я сделал тестовый примерчик. Вот собственно и все. :)

рони 20.12.2017 13:39

ksa,
да вроде просто каждая строка arr[i] - не должна содержать повторений и каждый столбец [arr[0] [0], arr[1] [0],..., arr[8] [0]]

ksa 20.12.2017 13:43

рони, а боксы 3х3 тогда тут при чем? :blink:

рони 20.12.2017 14:36

Цитата:

Сообщение от ksa
боксы 3х3 тогда тут при чем?

нужны тоже!!!
9 строк, 9 столбцов, 9 блоков 3 х 3 - каждый из этих 27 массивов должен содержать только уникальные элементы - вот и все правила Судоку.

рони 20.12.2017 15:43

судоку проверка
 
:write: вопрос как проще сформровать массив k в 12 строке, последовательность строк не имеет значения, вариант формирования смотреть пост №10 (строки 12-15)

<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>

  <script>
  var chec = function() {
  var k = [
  /* строки */
    [0, 1, 2, 3, 4, 5, 6, 7, 8],
    [9, 10, 11, 12, 13, 14, 15, 16, 17],
    [18, 19, 20, 21, 22, 23, 24, 25, 26],
    [27, 28, 29, 30, 31, 32, 33, 34, 35],
    [36, 37, 38, 39, 40, 41, 42, 43, 44],
    [45, 46, 47, 48, 49, 50, 51, 52, 53],
    [54, 55, 56, 57, 58, 59, 60, 61, 62],
    [63, 64, 65, 66, 67, 68, 69, 70, 71],
    [72, 73, 74, 75, 76, 77, 78, 79, 80],
 /* блоки 3 х 3 */
    [0, 1, 2, 9, 10, 11, 18, 19, 20],
    [3, 4, 5, 12, 13, 14, 21, 22, 23],
    [6, 7, 8, 15, 16, 17, 24, 25, 26],
    [27, 28, 29, 36, 37, 38, 45, 46, 47],
    [30, 31, 32, 39, 40, 41, 48, 49, 50],
    [33, 34, 35, 42, 43, 44, 51, 52, 53],
    [54, 55, 56, 63, 64, 65, 72, 73, 74],
    [57, 58, 59, 66, 67, 68, 75, 76, 77],
    [60, 61, 62, 69, 70, 71, 78, 79, 80],
/* столбцы */
    [0, 9, 18, 27, 36, 45, 54, 63, 72],
    [1, 10, 19, 28, 37, 46, 55, 64, 73],
    [2, 11, 20, 29, 38, 47, 56, 65, 74],
    [3, 12, 21, 30, 39, 48, 57, 66, 75],
    [4, 13, 22, 31, 40, 49, 58, 67, 76],
    [5, 14, 23, 32, 41, 50, 59, 68, 77],
    [6, 15, 24, 33, 42, 51, 60, 69, 78],
    [7, 16, 25, 34, 43, 52, 61, 70, 79],
    [8, 17, 26, 35, 44, 53, 62, 71, 80]
];
  return function(a) {
    a = [].concat.apply([], a);
    return k.every(function(b) {
      var c = {};
      return b.every(function(b) {
        b = a[b];
        c[b] = (c[b] || 0) + 1;
        return 2 > c[b];
      });
    });
  };
}();

var board =  [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
  [ 2, 3, 4, 5, 6, 7, 8, 9, 1 ],
  [ 3, 4, 5, 6, 7, 8, 9, 1, 2 ],
  [ 4, 5, 6, 7, 8, 9, 1, 2, 3 ],
  [ 5, 6, 7, 8, 9, 1, 2, 3, 4 ],
  [ 6, 7, 8, 9, 1, 2, 3, 4, 5 ],
  [ 7, 8, 9, 1, 2, 3, 4, 5, 6 ],
  [ 8, 9, 1, 2, 3, 4, 5, 6, 7 ],
  [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ] ];

alert(chec(board)); //false
board =  [
    [8, 4, 5, 6, 1, 9, 3, 2, 7],
    [1, 3, 2, 4, 5, 7, 6, 9, 8],
    [7, 6, 9, 8, 3, 2, 5, 4, 1],
    [5, 9, 6, 2, 8, 1, 7, 3, 4],
    [4, 8, 3, 5, 7, 6, 2, 1, 9],
    [2, 7, 1, 3, 9, 4, 8, 5, 6],
    [3, 5, 7, 9, 4, 8, 1, 6, 2],
    [6, 1, 4, 7, 2, 5, 9, 8, 3],
    [9, 2, 8, 1, 6, 3, 4, 7, 5]
]
alert(chec(board));//true
  </script>
</head>

<body>
<div id="slider"></div>

</body>
</html>


Часовой пояс GMT +3, время: 14:17.