Игра Tic-Tac-Toe - Regex хочет больше персонажей, чем на доске 3х3? - PullRequest
4 голосов
/ 03 апреля 2019

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

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

  • -1, если доска еще не закончена (есть пустые места),
  • 1, если "Х" выиграл,
  • 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. Почему это?

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

Ответы [ 4 ]

5 голосов
/ 03 апреля 2019

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

board = board.join('-')

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

.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") && -1);
}
2 голосов
/ 03 апреля 2019

. соответствует любому символу, так что

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 |
-------------

. вне поля совпадения с разделителем -.

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

2 голосов
/ 03 апреля 2019

После операций join и replace строка board будет выглядеть следующим образом:

001-012-210

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

The *Кейс 1010 * проверяет строку, полную X.

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

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

1 голос
/ 03 апреля 2019

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

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

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...