Ruby, Rev B 121 byte
Trình là chức năng ẩn danh, trừ đi f=
. Hiển thị trong chương trình thử nghiệm để minh họa việc sử dụng.
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 byte được lưu bằng cách làm cho hình vuông trung tâm trở thành bit đáng kể nhất thay vì bit đáng kể nhất (loại bỏ /2
thay vì %256
.) Tiết kiệm còn lại bằng cách sắp xếp lại bảng di chuyển chấp nhận được. Tổ chức dưới dạng ô vuông trung tâm miễn phí / chiếm thay vì tổng số X cho phép thử nghiệm đơn giản hơn. Ngoài ra, bây giờ chỉ có 2 chuỗi trong mảng nên %w{string1 string2}
cú pháp bị bỏ qua có lợi cho ["string1","string2"]
cú pháp. Điều này cho phép \7
bao gồm một ký tự không thể in được, từ đó cho phép sử dụng mã hóa đơn giản hơn: 126-t
thay vì (36-t)%120
.
Ruby, Rev A 143 byte
->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}
Đây là một chức năng ẩn danh. Định dạng đầu vào / đầu ra bị bỏ ngỏ, vì vậy tôi đã sử dụng số nhị phân 9 bit. bit 512 đại diện cho trung tâm, với các bit còn lại xoắn quanh nó (bit 1 được coi là một góc.)
Có nhiều đầu vào khả dĩ hơn đầu ra chấp nhận được, vì vậy thuật toán là thử tất cả các bước di chuyển và tìm một đầu vào phù hợp với mẫu đầu ra chấp nhận được. Các mẫu đầu ra chấp nhận được cho mỗi số X là mã hóa cứng.
Thông tin về hình vuông trung tâm bị loại bỏ và 8 bit còn lại được nhân với 257 để nhân đôi chúng. Mẫu này sau đó được xoay qua các mẫu có thể chấp nhận được bằng cách chuyển quyền.
Vòng lặp không được thoát khi tìm thấy một mẫu, do đó mẫu được trả về sẽ là mẫu được chấp nhận LAST được tìm thấy. Vì lý do này, các mẫu thích hợp hơn (nơi có ưu tiên) đến sau trong danh sách.
Với chiến lược 'Hiệp sĩ di chuyển', việc một mô hình được xoay 45 độ hay không là rất quan trọng. Phiên bản không có người theo chiến lược di chuyển của các hiệp sĩ và do đó không cần phân biệt giữa hình vuông góc và hình vuông cạnh: dù sao thì ba cái liên tiếp cũng phải tránh.
Tuy nhiên, tôi thấy rằng đây không phải lúc nào cũng là chiến lược tốt nhất, vì có mẹo sau đây. Nếu đối thủ của bạn đi trước và chiếm trung tâm, anh ta sẽ giành chiến thắng. Nhưng trong lần di chuyển thứ hai, anh ta mắc lỗi khi cho phép bạn tạo một hình vuông 2x2, bạn nên lấy nó, vì điều này cho phép bạn buộc anh ta thực hiện ba lần liên tiếp. Điều này được thực hiện trong phiên bản golf. Trong trường hợp này cần thêm một ít mã để phân biệt giữa ba chữ X trong một góc (buộc đối thủ thua cuộc) và 3 chữ X dọc theo một cạnh (tự sát ngay lập tức.)
Ungolfed trong chương trình thử nghiệm
Phiên bản không được tuân theo logic được thể hiện trong câu hỏi.
Trong phiên bản golf, bảng được sửa đổi một chút [[0],[1,17],[9],[37,7,51,85],[45],[47,119]]
để thực hiện hành vi hơi khác nhau cho trường hợp r=3
. Sau đó, nó được nén thành ASCII có thể in (yêu cầu giải mã (t-36)%120
). Cần thêm một chút logic để phân biệt giữa ba chữ X trong một góc và ba chữ X dọc theo một cạnh trong trường hợp của bảng 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}
Đầu ra của chương trình thử nghiệm
Điều này xảy ra khi máy tính tự chơi.
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
PHÂN TÍCH CHƠI TRÒ CHƠI ĐẦU TIÊN
Điều này thực sự rất đơn giản và tuyến tính.
Khi chơi đầu tiên, hình vuông ở giữa sẽ luôn là hình vuông đầu tiên bị chiếm đóng.
r = 0
... binary representation 0
.X.
...
r = 2
X.. binary representation 1001=9
.XX
...
r = 4
X.. binary representation 101101=45
.XX
XX.
Chỉ có một cách (tối đa đối xứng) để có năm chữ X bao gồm hình vuông ở giữa trên bảng mà không có trò chơi kết thúc. Có một chữ X ở ô vuông ở giữa, một trên mỗi đường chéo (ở góc 90 độ với nhau) và một chữ trên mỗi đường trung tâm ngang / dọc (ở 90 độ với nhau.) Vì toàn bộ cạnh không thể bị chiếm ở trên sắp xếp có thể. Người chơi khác phải thua trong lần di chuyển tiếp theo.
PHÂN TÍCH CHƠI TRÒ CHƠI THỨ HAI
Chơi là khá khác nhau tùy thuộc nếu người chơi khác chọn hình vuông ở giữa.
r = 1
chiếm vuông giữa
.X. X.. binary representation 1
.X. .X.
... ...
giữa vuông miễn phí
X.. .X. binary representation 10001=17
... ...
..X .X.
r = 3
Hình vuông ở giữa bị chiếm đóng, nếu người chơi khác chơi liền kề với X cuối cùng của bạn Chơi một hiệp sĩ di chuyển đi như bên dưới được hỗ trợ trong phiên bản không có người nhận
XX. .XX binary representation 1011=11
.X. XX. or mirror image 1101=13
X.. ...
Tuy nhiên, ở trên KHÔNG phải là nước đi tốt nhất và không được hỗ trợ trong phiên bản chơi gôn. Động thái tốt nhất là như sau, buộc một chiến thắng ở lượt tiếp theo:
XX. binary representation 111=7. XXX
XX. Only to be used where j is odd. .X.
... Even j would look like image to right. ...
Hình vuông ở giữa bị chiếm đóng, nếu người chơi khác chơi ở 90 hoặc 135 độ so với chữ X cuối cùng của bạn (chơi di chuyển hiệp sĩ đi.)
X.X .X. binary representation 100101=37
.X. .XX
.X. X..
Trung vuông miễn phí
X.X .X. XX. binary representations:
... X.X ... 1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)
r = 5
quảng trường trung chiếm. Vì những lý do đã nêu ở trên trong r = 4, có bốn động thái có thể xảy ra, tất cả đều mất. chỉ có một được hỗ trợ: 101111 = 47.
giữa vuông miễn phí. Chỉ có một bảng có thể lên đến đối xứng, như sau. Người chơi khác phải thua trong lần di chuyển tiếp theo, vì vậy không cần phải hỗ trợ r> 5.
XX. binary representation 1110111=119
X.X
.XX