Ruby, Rev B 121 байт
Представление является анонимной функцией, минус f=. Показано в тестовой программе для иллюстрации использования.
f=->n{["~mK)\7","}uYwQO"][l=n%2].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m/2*257>>j&255==126-t&&t+j%2!=119&&l=m}}}
l}
puts g=f[gets.to_i]
puts
[7,6,5,
8,0,4,
1,2,3].each{|i|print g>>i&1; puts if i/3==1}
2 байта сохраняются, делая центральный квадрат наименьшим значащим битом вместо самого старшего бита (удаляем /2вместо вместо %256.) Оставшиеся сбережения путем реорганизации таблицы допустимых ходов. Организация в виде центрального квадрата свободного / занятого вместо общего числа X позволяет провести более простой тест. Кроме того, теперь в массиве только 2 строки, поэтому %w{string1 string2}синтаксис отброшен в пользу ["string1","string2"]синтаксиса. Это позволяет \7включать непечатаемый символ , что, в свою очередь, позволяет использовать более простую кодировку: 126-tвместо (36-t)%120.
Ruby, Rev A 143 байта
->n{l=r=("%b"%n).sum%8
%w{$ %5 - I+Wy Q S#}[r].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m%256*257>>j&255==(t-36)%120&&t+j%2!=43&&l=m}}}
l}
Это анонимная функция. Формат ввода / вывода был оставлен открытым, поэтому я выбрал 9-битное двоичное число. бит 512 представляет центр, а остальные биты закручиваются вокруг него (бит 1 считается углом).
Возможных входных данных намного больше, чем допустимых выходных, поэтому алгоритм должен попробовать все ходы и найти тот, который соответствует приемлемому выходному шаблону. Приемлемые шаблоны вывода для каждого числа X жестко закодированы.
Информация о центральном квадрате удаляется, а оставшиеся 8 бит умножаются на 257 для их дублирования. Этот шаблон затем поворачивается мимо приемлемых шаблонов путем смещения прав.
Цикл не завершается при обнаружении шаблона, поэтому возвращенный шаблон будет последним приемлемым шаблоном. По этой причине предпочтительные шаблоны (там, где есть предпочтения) появляются позже в списке.
Учитывая стратегию «движения рыцарей», не имеет значения, повернута ли модель на 45 градусов или нет. Версия без гольфа следует стратегии перемещения коней и, следовательно, не нуждается в различении угловых квадратов и краевых граней: в любом случае следует избегать трех подряд.
Тем не менее, я обнаружил, что это не всегда лучшая стратегия, поскольку есть следующий трюк. Если ваш противник идет первым и занимает центр, он должен победить. Но на своем втором ходу он делает ошибку, позволяя вам сделать квадрат 2х2, вы должны взять его, так как это заставит его сделать три подряд. Это реализовано в версии для гольфа. В этом случае требуется немного дополнительного кода, чтобы различить три X в углу (заставить противника проиграть) и 3 X вдоль одного края (немедленное самоубийство).
Неуправляемый в тестовой программе
Версия без присмотра следует логике, выраженной в вопросе.
В версии для игры в гольф стол слегка модифицирован, [[0],[1,17],[9],[37,7,51,85],[45],[47,119]]чтобы реализовать немного другое поведение для случая r=3. Затем он сжимается в печатный ASCII (требующий декодирования (t-36)%120). В случае записи 7 таблицы требуется дополнительный бит логики, чтобы различать три X в углу и три X вдоль края:&&t+j%2!=43
f=->n{l=r=("%b"%n).sum%8 #convert input to text, take character checksum to count 1's(ASCII 49.)
#0 is ASCII 48, so %8 removes unwanted checksum bloat of 48 per char.
#l must be initialised here for scoping reasons.
[[0],[1,17],[9],[11,13,37,51,85],[45],[47,119]][r].each{|t| #according to r, find the list of acceptable perimeter bitmaps, and search for a solution.
9.times{|i|(m=n|1<<i)==n|| #OR 1<<i with input. if result == n, existing X overwritten, no good.
#ELSE new X is in vacant square, good. So..
8.times{|j|m%256*257>>j&255==t&&l=m}} #%256 to strip off middle square. *257 to duplicate bitmap.
#rightshift, see if pattern matches t. If so, write to l
}
l} #return l (the last acceptable solution found) as the answer.
#call function and pretty print output (not part of submission)
puts g=f[gets.to_i]
puts
[6,7,0,
5,8,1,
4,3,2].each{|i|print g>>i&1; puts if i<3}
Вывод тестовой программы
Это то, что происходит, когда компьютер играет сам.
C: \ Users \ steve> ruby tictac.rb
0
256
000
010
000
C: \ Users \ steve> ruby tictac.rb
256
384
010
010
000
C: \ Users \ steve> ruby tictac.rb
384
400
010
010
100
C: \ Users \ steve> ruby tictac.rb
400
404
010
010
101
C: \ Users \ steve> ruby tictac.rb
404
436
010
110
101
C: \ Users \ steve> ruby tictac.rb
436
444
010
110
111
ИГРА АНАЛИЗ ИГРАЕТ ПЕРВЫЙ
Это на самом деле очень просто и линейно.
При первой игре средний квадрат всегда будет занятым первым.
г = 0
... binary representation 0
.X.
...
г = 2
X.. binary representation 1001=9
.XX
...
г = 4
X.. binary representation 101101=45
.XX
XX.
Есть только один способ (с точностью до симметрии), чтобы пять X, включая средний квадрат на доске, не были закончены. В среднем квадрате есть X, по одному на каждой диагонали (под углом 90 градусов друг к другу) и по одному на каждой горизонтальной / вертикальной центральной линии (под углом 90 градусов друг к другу). Поскольку весь край не может быть занят, вышеуказанное является единственным договоренность возможна. Другой игрок должен проиграть на следующем ходу.
ИГРОВОЙ АНАЛИЗ ИГРАЕТ ВТОРОЙ
Игра совсем другая, если другой игрок выберет средний квадрат.
г = 1
средняя площадь занята
.X. X.. binary representation 1
.X. .X.
... ...
средняя площадь свободна
X.. .X. binary representation 10001=17
... ...
..X .X.
г = 3
Средняя клетка занята, если другой игрок играет рядом с вашим последним Икс. Игра в ход коня, как показано ниже, поддерживается в версии без гольфа.
XX. .XX binary representation 1011=11
.X. XX. or mirror image 1101=13
X.. ...
Однако вышесказанное НЕ является лучшим ходом и не поддерживается в версии для гольфа. Лучший ход выглядит следующим образом, принуждая выиграть на следующем ходу:
XX. binary representation 111=7. XXX
XX. Only to be used where j is odd. .X.
... Even j would look like image to right. ...
Средняя клетка занята, если другой игрок играет на 90 или 135 градусов к вашему последнему Х (играйте с ходом рыцаря).
X.X .X. binary representation 100101=37
.X. .XX
.X. X..
Средняя площадь бесплатно
X.X .X. XX. binary representations:
... X.X ... 1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)
г = 5
средняя площадь занята. По причинам, указанным выше в r = 4, есть четыре возможных хода, каждый из которых проигрывает. поддерживается только один: 101111 = 47.
средняя площадь свободна. Существует только одна возможная плата с точностью до симметрии, как изложено ниже. Другой игрок должен проиграть на следующем ходу, поэтому нет необходимости поддерживать r> 5.
XX. binary representation 1110111=119
X.X
.XX