quine-ish tic-tac-toe


19

Viết một chương trình bằng ngôn ngữ bạn chọn, chơi một trò chơi hoàn hảo về tic-tac-toe trên bảng 3 * 3 với người chơi. Tuy nhiên, mỗi di chuyển phải là một chương trình khác nhau , được tạo từ lần lặp trước.

Làm thế nào và ở dạng nào bạn đánh giá đầu vào của con người, tùy thuộc vào bạn, nhưng nó phải được đọc từ đầu vào tiêu chuẩn. Tương tự, bạn có thể tự do chọn phương thức bạn sẽ xác định người chơi nào bắt đầu (ví dụ: bạn hỏi trước hoặc bạn cho phép con người nhập di chuyển không hợp lệ để báo hiệu rằng máy tính khởi động hoặc các ý tưởng khác).

Xác nhận di chuyển là không cần thiết, bạn có thể giả sử một đối thủ khá chơi người.

Về cơ bản, bạn có chương trình tương ứng với trạng thái của hội đồng quản trị. Trạng thái được in theo bất kỳ cách nào có thể nhận ra, nhưng ít nhất mức độ chi tiết sau đây được mong đợi:

X..
00X
x..

Sau khi trình phát của con người nhập các bước di chuyển của mình, chương trình của bạn phải tạo ra lần lặp tiếp theo của chính nó dưới dạng tệp nguồn trong cùng một ngôn ngữ (theo đầu ra tiêu chuẩn hoặc thành một tệp) và chấm dứt. Bạn không được phép lưu trữ thông tin ở bất kỳ nơi nào khác ngoài tệp nguồn đó. (không cần thiết cho chương trình của bạn để xây dựng và chạy chương trình đã tạo, nó có thể được thực hiện bởi người dùng - tuy nhiên, nó không bị cấm). Khi chương trình được tạo được xây dựng và chạy, nó sẽ hoạt động tương tự, hiển thị trạng thái, chờ người dùng nhập liệu, v.v.

Vào cuối trò chơi, bạn phải in kết quả (cho dù bạn thắng hay là hòa) theo bất kỳ cách nhận dạng rõ ràng nào.

Bằng cách chơi hoàn hảo, ý tôi là chương trình không được thua, và nếu có khả năng buộc phải thắng, thì nên thắng.

Chiến thắng mã ngắn nhất , người chiến thắng được chọn ít nhất 10 ngày sau lần nhập hợp lệ đầu tiên.

Bạn được giảm 10% số điểm nếu chương trình của bạn có thể xử lý việc xây dựng và khởi chạy lần lặp tiếp theo. (Tôi biết, có lẽ nó không có giá trị) Tất nhiên, bản thân chương trình phải được chấm dứt vào thời điểm lần lặp tiếp theo chấp nhận các động thái từ người dùng.

Nếu bạn sử dụng một số thủ thuật không phổ biến lạ, xin vui lòng gửi một lời giải thích ngắn với mã của bạn.


2
Thử thách thú vị, nhưng tôi nghĩ mình sẽ từ chối.
John Dvorak

"Mỗi động thái phải là một chương trình khác nhau". Ý bạn là, "mỗi trò chơi phải được bắt đầu và quản lý bởi một phiên bản mới, riêng biệt của chương trình gốc"?
DavidC

1
@DavidCarraher: Không. Mọi di chuyển, không chỉ mỗi trò chơi. Kiểm tra mô tả dưới đây ví dụ bảng. Khi máy tính phải di chuyển (vì vậy trạng thái của bảng thay đổi), chương trình của bạn phải tạo một tệp nguồn, khi được xây dựng và chạy, sẽ trở thành trạng thái tiếp theo. Chương trình ban đầu sau đó thoát ra. Chương trình mới được tạo, khi thực hiện di chuyển, sẽ hoạt động tương tự: nó tạo ra một tệp nguồn, khi được xây dựng và chạy, sẽ trở thành trạng thái tiếp theo, v.v. Vì không cho phép lưu trữ thông tin ngoại trừ trong tệp nguồn được tạo, nó giống như một câu hỏi với sự khác biệt giữa các lần lặp.
vsz

Câu trả lời:


13

Perl, 933 ký tự

$m=<<'';$_='         ';
sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}

sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}

Xin lưu ý rằng dòng trống ở giữa tập lệnh thực sự cần phải có. (Không cần ngắt dòng ở cuối dòng dài, ngoại trừ mức độ dễ đọc và không được bao gồm trong số ký tự.)

Cách sử dụng: Khi chương trình được chạy mà không có đối số, nó sẽ hiển thị trạng thái trò chơi hiện tại. Vì khi bắt đầu, bảng trống, đầu ra sẽ là:

...
...
...

Chạy chương trình với một đối số từ 1 đến 9 để xác nhận hình vuông đó là bước di chuyển của bạn. Chương trình sẽ tự di chuyển và sau đó xuất ra một kịch bản thay thế với trạng thái mới. Vì vậy, ví dụ:

$ perl ./qttt 5 > ./qttt-2
$ perl ./qttt-2
O..
.X.
...

Ở lượt đầu tiên, bạn có thể di chuyển 0 để chỉ ra rằng máy tính sẽ thực hiện bước đầu tiên. Lưu ý rằng người chơi đầu tiên sẽ luôn luôn là X.

Khi trò chơi kết thúc, đầu ra màn hình sẽ bao gồm một ghi chú cho hiệu ứng đó:

$ perl ./qttt-4 6 > ./qttt-5
$ perl ./qttt-5
O wins
OXX
OOX
X.O

Chương trình hoạt động bằng cách thực hiện tìm kiếm minimax tiêu chuẩn của cây trò chơi. (Tic-tac-toe là một trò chơi đủ nhỏ để có thể tạo ra một cây trò chơi đầy đủ trong mỗi lần chạy.) Ngoại lệ cho điều này là khi máy tính di chuyển trước - trong trường hợp này, việc di chuyển ban đầu sang góc trên bên trái là khó khăn- mã hóa

Lưu ý rằng chương trình này hoạt động theo cách thức phù hợp - không có lúc nào tập lệnh truy cập vào tệp nguồn của chính nó để tạo đầu ra của nó.


1
Nó thật đẹp! Tôi đã không nhận ra mình đã nhìn chằm chằm vào một tài liệu khổng lồ ở đây trong thời gian dài nhất, sau đó thực hiện một cú đúp.
Jesse Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.