Ruby, оберт 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
.
Рубі, об. 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 вздовж одного краю (негайне самогубство.)
Ungolfed в тестовій програмі
Негольована версія слідує логіці, висловленій у питанні.
У версії для гольфу стіл трохи змінений, [[0],[1,17],[9],[37,7,51,85],[45],[47,119]]
щоб реалізувати дещо іншу поведінку для цього випадку r=3
. Потім він стискається для друку ASCII (вимагає розшифровки (t-36)%120
). Необхідний додатковий біт логіки для розмежування трьох X у куті та трьох X по краю у випадку запису таблиці 7:&&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: \ Користувачі \ steve> ruby tictac.rb
0
256
000
010
000
C: \ Користувачі \ steve> ruby tictac.rb
256
384
010
010
000
C: \ Користувачі \ steve> ruby tictac.rb
384
400
010
010
100
C: \ Користувачі \ steve> ruby tictac.rb
400
404
010
010
101
C: \ Користувачі \ steve> ruby tictac.rb
404
436
010
110
101
C: \ Користувачі \ steve> ruby tictac.rb
436
444
010
110
111
ІГРАЛЬНИЙ АНАЛІЗ ІГРАЙ ПЕРШИЙ
Це насправді дуже просто і лінійно.
Під час першої гри середній квадрат завжди буде зайнятим першим квадратом.
r = 0
... binary representation 0
.X.
...
r = 2
X.. binary representation 1001=9
.XX
...
r = 4
X.. binary representation 101101=45
.XX
XX.
Є лише один спосіб (аж до симетрії) мати п'ять X, включаючи середній квадрат на дошці, без того, щоб гра закінчилася. У середньому квадраті є X, по одній діагоналі (90 градусів один до одного) і по одній на кожній горизонтальній / вертикальній центральній лінії (на 90 градусів один до одного.) Оскільки ціле ребро не може бути зайняте, вище є єдиним можлива домовленість. Інший гравець повинен програти при наступному кроці.
ІГРАЛЬНИЙ АНАЛІЗ, ІГРЕННЯ ВТОРОМ
Гра зовсім інша, залежно від того, якщо інший гравець вибере середній квадрат.
r = 1
середня площа зайнята
.X. X.. binary representation 1
.X. .X.
... ...
середня площа вільна
X.. .X. binary representation 10001=17
... ...
..X .X.
r = 3
Середня площа зайнята, якщо інший гравець грає поруч з вашою останньою X Відігравання рицарського руху, як показано нижче, підтримується у версії без вольфів
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)
r = 5
середня площа зайнята З причин, зазначених вище в r = 4, є чотири можливі ходи, які всі програють. підтримується лише один: 101111 = 47.
середня площа вільна. Існує лише одна можлива дошка до симетрії, як описано нижче. Інший гравець повинен програти при наступному кроці, тому немає необхідності підтримувати r> 5.
XX. binary representation 1110111=119
X.X
.XX