Игра в крестики-нолики — Регулярному выражению требуется больше символов, чем на доске 3х3?

#javascript #arrays #regex

#javascript #массивы #регулярное выражение

Вопрос:

Ниже приведен код для игры в крестики-нолики 3х3. Это работает отлично, но есть вещи, которые я не понимаю.

Цель функции — вернуть:

  • -1 если доска еще не закончена (есть пустые места),
  • 1 если «X» выиграл,
  • 2 если «О» выиграл,
  • 0, если это игра в кошки-мышки (т.е. Ничья).

 function isSolved(board) {
   board = board.join('-').replace(/,/g,'');
   if(/222|2...2...2|2....2....2|2..2..2/.test(board)) return 2;
   if(/111|1...1...1|1....1....1|1..1..1/.test(board)) return 1;
   if(/0/.test(board)) return -1;
   return 0;

}

var result = isSolved([[0, 0, 1],[0, 1, 2],[2, 1, 0]]); //board is 3 dimensional array.

console.log(result); // -1  

Я не понимаю часть регулярного выражения в if инструкции, т. е. 1....1....1 , поскольку максимальный ввод, который может принять доска, равен 9; но здесь, похоже, это 11. Почему это?

Код абсолютно в порядке, но я не понимаю, что происходит. Не могли бы вы объяснить?

Комментарии:

1. что такое .test(board) ?

2. @SaadAnees это: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /… . Синтаксис regexObj.test(str) .

Ответ №1:

Регулярное выражение содержит 11 символов, потому что board к нему добавлено два дополнительных - символа:

 board = board.join('-')
  

Предположительно, оригинал board представляет собой 2D-массив, и запятые, введенные этим объединением (поскольку вложенные массивы в процессе упорядочиваются), удаляются с помощью:

 .replace(/,/g,'');
  

Итак, оригинальная доска, подобная этой:

 [
    [1, 0, 1],
    [2, 2, 0],
    [0, 0, 0]
]
  

…превращается в строку с .join("-") :

 "1,0,1-2,2,0-0,0,0"
  

… и, наконец, очищен от запятых:

 "101-220-000".
  

Дополнительный разделитель упрощает поиск некоторых шаблонов, не вызывая ложных срабатываний. Например, когда есть совпадение с 222 , можно быть уверенным, что они будут в одном ряду, и совпадение с 1..1..1 аналогичным образом обнаружит три возможных вертикальных символа 3 в ряд без ложных срабатываний, поскольку совпадение может быть только с позиции 0, 1 или 2. 1....1....1 Имеет длину 11 символов и может совпадать только в позиции 0 для одной из диагоналей. Наконец, 1..1..1 также может совпадать только в одной позиции, то есть в позиции 2, поскольку в противном случае один из дефисов конфликтовал бы с 1 в шаблоне. Совпадение представляет противоположную диагональ.

Дальнейшее улучшение

Можно объединить два регулярных выражения в одно (экономя некоторое время выполнения), используя обратную ссылку, и использовать некоторую логику для объединения всех возможностей в одном выражении:

 function isSolved(board) {
   board = board.join('-').replace(/,/g,'');
   var match = board.search(/([12])(1|...1...|....1....|..1..)1/);
   return  (board[match] || board.includes("0") amp;amp; -1);
}
  

Комментарии:

1. @trincol большое спасибо. Ваше объяснение сделало мой день лучше. Obrigado.

Ответ №2:

. сопоставьте с любым символом, чтобы

222 сопоставьте с

 -------------
| 2 | 2 | 2 |
-------------
|   |   |   |
-------------
|   |   |   |
-------------

OR

-------------
|   |   |   |
-------------
| 2 | 2 | 2 |
-------------
|   |   |   |
-------------

OR

-------------
|   |   |   |
-------------
|   |   |   |
-------------
| 2 | 2 | 2 |
-------------
  

и 2...2...2 сопоставьте с

 -------------
| 2 | . | . | . 
-------------
| 2 | . | . | . 
-------------
| 2 |   |   | 
-------------

OR

-------------
|   | 2 | . | . 
-------------
| . | 2 | . | . 
-------------
| . | 2 |   | 
-------------

OR

-------------
|   |   | 2 | . 
-------------
| . | . | 2 | . 
-------------
| . | . | 2 |
-------------
  

. за пределами доски совпадают с разделителем - .

А два других более или менее одинаковые.

Ответ №3:

После операций join и replace , board будет строка, подобная этой:

 001-012-210
  

Каждая строка разделяется - .

111 Случай тестируется на строку, полную крестиков.

1...1...1 Случай тестируется на наличие столбца, полного крестиков. Есть 3 точки, потому что там также есть - символ.

1..1..1 Случай тестируется на диагональ, полную крестиков.

Ответ №4:

В регулярных выражениях альтернативные шаблоны разделяются | и . совпадают в точности с любым символом.

Доска преобразуется в строку, которая выглядит следующим образом:

 001-012-210
  

Это означает, что игрок 1 выигрывает, когда

  • они заполнили строку, что означает, что строка содержит подстроку 111
  • они заполнили столбец, что означает, что строка либо 1xx-1xx-1xx , x1x-x1x-x1x либо xx1-xx1-xx1 . В этих случаях между каждым из них ровно три символа 1 , которым соответствует 1...1...1 в регулярном выражении.
  • они заполнили диагональ, что означает, что строка либо xx1-x1x-1xx , либо 1xx-x1x-xx1 . В этих случаях между каждым из них есть либо ровно два, либо четыре символа 1 , которым соответствует либо 1..1..1 , либо 1....1...1 .