Trò chơi tối ưu của Tic Tac Torus


31

Thử thách này là về trò chơi Tic Tac Toe, nhưng nó được chơi trên một hình xuyến.

Cách chơi

Để tạo bảng trò chơi cần thiết, bạn bắt đầu với bảng trò chơi Tic Tac Toe thông thường. Đầu tiên gấp nó thành một hình trụ bằng cách nối cạnh trái và cạnh phải. Sau đó gấp nó thành hình xuyến bằng cách nối cạnh trên và cạnh dưới. Đây là một hình ảnh đơn giản của một bảng trò chơi như vậy với một vài động tác được chơi (kỹ năng Sick Paint!).

Tor Tac Torus

Các quy tắc của Tic Tac Toe trên hình xuyến cũng giống như Tic Tac Toe thông thường. Mỗi người chơi đặt xen kẽ Xs và Os. Cái đầu tiên có 3 ký hiệu giống nhau trong một hàng, một cột hoặc một trong một đường chéo thắng.

Vì một hình xuyến khá khó để hình dung, chúng tôi chỉ cần chiếu tấm bảng lên một tờ giấy. Bây giờ chúng ta có thể chơi trò chơi như Tic Tac Toe thông thường. Sự khác biệt duy nhất là, bạn cũng có thể giành chiến thắng với 3 biểu tượng giống nhau trong một đường chéo bị hỏng. Ví dụ Người chơi 1 (X) thắng bảng sau. Bạn có thể thấy điều này một cách dễ dàng bằng cách thay đổi góc nhìn trên hình xuyến một chút.

Người chơi 1 (X) thắng vì 3 X trong một đường chéo bị hỏng

Nếu bạn quan tâm, bạn có thể chơi Tic Tac Toe trên Torus tại Torus Games . Có phiên bản Windows, Mac và Android.

Trò chơi tối ưu

Trong thử thách này đã quan tâm đến các trò chơi tối ưu. Một trò chơi tối ưu là một trò chơi, trong đó cả hai người chơi đều chơi một chiến lược tối ưu. Trên bảng Tic Tac Toe thông thường, các trò chơi tối ưu luôn kết thúc với tỷ số hòa. Hấp dẫn trên bảng hình xuyến luôn là người chơi đầu tiên giành chiến thắng. Trong thực tế, một trò chơi trên bảng hình xuyến không bao giờ có thể kết thúc với tỷ số hòa (cũng có thể nếu người chơi chơi không tối ưu).

Chiến lược tối ưu thực sự dễ dàng:

  • Nếu bạn có thể giành chiến thắng bằng cách đặt biểu tượng của bạn, hãy làm điều đó.
  • Mặt khác, nếu đối thủ của bạn có hai biểu tượng trong một hàng / cột / đia chéo, hãy thử chặn anh ta. Nếu không, hãy làm những gì bạn muốn.
  • Nếu không hãy làm những gì bạn muốn.

Mỗi trò chơi tối ưu bao gồm chính xác 7 động tác và những động tác này có thể được mô tả theo cách sau:

  1. Người chơi 1 đặt X ở bất cứ đâu trên bảng (9 lựa chọn)
  2. Người chơi 2 đặt một chữ O ở bất cứ đâu trên bảng (8 lựa chọn)
  3. Người chơi 1 đặt X ở bất cứ đâu trên bảng (7 lựa chọn)
  4. Di chuyển của người chơi 2 có thể bị ép buộc (1 lựa chọn), nếu không, anh ta đặt O ở bất cứ đâu (6 lựa chọn)
  5. Di chuyển của người chơi 1 là bắt buộc (1 lựa chọn)
  6. Người chơi 2 bị bắt trong một ngã ba (Người chơi 1 có thể thắng theo hai cách khác nhau), vì vậy Người chơi 2 phải chặn Người chơi 1 theo một cách (2 lựa chọn)
  7. Người chơi 1 đặt chiêu cuối của mình và thắng (1 lựa chọn)

Có 9 * 8 * 1 * 6 * 1 * 2 * 1 + 9 * 8 * 6 * 1 * 1 * 2 * 1 = 1728 trò chơi tối ưu khác nhau trên bảng dự kiến ​​của chúng tôi. Ở đây bạn có thể thấy một trò chơi tối ưu điển hình:

Ví dụ về một trò chơi tối ưu

Nếu chúng ta dán nhãn cho mỗi ô của bảng bằng các chữ số 0-8, chúng ta có thể mô tả trò chơi này bằng các chữ số 3518207. Đầu tiên a X là các vị trí trong ô 3 (hàng giữa, cột bên trái), hơn một O trong ô 5 (hàng giữa, cột bên phải), hơn một X trong ô 1 (hàng trên, cột giữa), ...

Sử dụng ký hiệu chữ số này, chúng tôi tự động tạo ra một đơn đặt hàng. Bây giờ chúng tôi có thể sắp xếp tất cả 1728 trò chơi tối ưu và chúng tôi nhận được danh sách:

Game 0000: 0123845
Game 0001: 0123854
Game 0002: 0124735
Game 0003: 0124753
Game 0004: 0125634
   ...
Game 0674: 3518207
   ...
Game 1000: 5167423
Game 1001: 5167432
Game 1002: 5168304
   ...
Game 1726: 8765034
Game 1727: 8765043

Thử thách

Danh sách này là một phần công việc của bạn. Bạn sẽ nhận được một số ktrong khoảng từ 0 đến 1727 và bạn phải trả lại ktrò chơi thứ năm theo ký hiệu số của danh sách được sắp xếp đó.

Viết hàm hoặc chương trình, nhận số k(số nguyên) tính toán trò chơi tương ứng. Bạn có thể đọc đầu vào thông qua STDIN, đối số dòng lệnh, đối số nhắc hoặc hàm và in kết quả (7 chữ số) ở định dạng có thể đọc được (ví dụ 0123845hoặc [0, 1, 2, 3, 8, 4, 5]) hoặc trả về bằng chuỗi (định dạng có thể đọc được của con người) hoặc số nguyên (chứa tất cả các chữ số trong cơ sở 10), hoặc trong bất kỳ định dạng mảng / danh sách.

Loại thử thách là golf-code. Do đó mã ngắn nhất sẽ thắng.


Tại sao bước di chuyển đầu tiên của người chơi 2 phải ở cùng một hàng hoặc cột như bước di chuyển đầu tiên của người chơi 1? Tôi đã chơi một vài trò chơi trong đầu, nơi di chuyển đầu tiên của người chơi 2 là ở một trong những đường chéo tương tự và chúng theo cùng một mô hình trò chơi tối ưu. Dường như với tôi, một trong những khía cạnh của bảng hình xuyến là các hàng, cột và đường chéo có hiệu ứng đối xứng trong trò chơi.
Runer112

@ Runer112 Đơn giản hóa chiến lược tối ưu rất nhiều. Quy tắc duy nhất bây giờ là chặn đối thủ của bạn nếu bạn có thể, nếu không hãy làm những gì bạn muốn.
Jakube

7
Chỉ cần một nhận xét phụ: thực sự có rất ít trò chơi độc đáo có thể có ở đây. Đối xứng tịnh tiến làm cho vị trí của bước di chuyển đầu tiên không liên quan (vì bạn luôn có thể căn giữa chế độ xem của mình), do đó, chia cho 9 ... và xoay bảng chỉ tạo ra 2 bước di chuyển khác nhau (đường chéo hoặc hình vuông liền kề) ... hầu hết 48 trò chơi khác nhau. Nếu bạn tính đến sự đối xứng phản chiếu, nó sẽ còn đi xa hơn nữa. Phiên bản hình xuyến này nhàm chán hơn nhiều so với phiên bản thông thường. Chơi gôn đi.
orion

@orion Trên thực tế, thực tế là hình xuyến kết thúc, không cấm chúng ta nghĩ về '0' là 'đầu tiên' trên bảng hình xuyến và phân biệt tất cả chín lĩnh vực nói chung ... Tuy nhiên, chúng tôi đồng ý rằng "kinh tuyến 0" đang ở Greenwich , trong khi ở phía đối diện Trái đất, chúng ta có thể là một chân tại nơi thứ năm, một chân thay thế vào thứ tư (chênh lệch 24h theo giờ địa phương!) - và tất cả mặc dù Trái đất tròn và không có một "điểm khởi đầu" ...
pawel.boczarski

@Rodney Không, đó là một, không phải bảy. Hãy thử tính toán nó.
Jakube

Câu trả lời:


6

JavaScript (ES6), 266 308 317 334 341

Một hàm trả về một chuỗi. Chỉnh sửa Tìm thấy một giải pháp số học cho hàm M (cuối cùng!)

F=(n,x=[],M=(a,b,t=-a-b)=>(a-b)%3?a<3&b<3?3+t:a>5&b>5?21+t:12+t:9+t+a%3*3)=>
[for(a of z='012345678')for(b of z)for(c of z)for(d of z) 
a-b&&c-a&&c-b&&(b-(y=M(a,c))?d==y:d-a&&d-b&&d-c)&&(
f=M(c,e=M(b,d)),g=M(a,e),g<f?[f,g]=[g,f]:0,r=a+b+c+d+e,x.push(r+f+g,r+g+f))]
&&x[n]

Rất ngây thơ , nó có thể được rút ngắn bằng nhiều cách . Nó chỉ đơn giản là liệt kê tất cả các giá trị pháp lý có thể và trả về những gì tìm thấy tại vị trí n. Hàm M trả về vị trí ở giữa hai ô, đó là động tác bắt buộc để chặn người chơi đối diện.

Dễ đọc hơn

F=(n,x=[],
  M=(a,b,t=-a-b)=>(a-b)%3? 
     a<3&b<3?
       3+t // first row
       :a>5&b>5?
          21+t // last row
          :12+t // middle row and diags
     :9+t+a%3*3 // columns
  )=>
  [for(a of z='012345678') // enumerate the first 4 moves
     for(b of z)
       for(c of z)
         for(d of z) 
           a-b&&c-a&&c-b // avoid duplicates
           &&(b-(y=M(a,c))?d==y:d-a&&d-b&&d-c) // and check if d must block a-c or it's free
           &&(
             e=M(b,d), // forced to block b-d
             f=M(c,e),g=M(a,e),g<f?[f,g]=[g,f]:0, // f and g could be in the wrong order
             r=a+b+c+d+e, // start building a return string
             x.push(r+f+g,r+g+f) // store all values in x
  )]&&x[n] // return value at requested position

3

Octave, 467 369 363 309 297 ký tự

297:

global t=0*(1:9)m=dec2bin([15;113;897;1170;1316;1608;2370;2216;2580])-48 a;
function g(s,p)global a t m;
if nnz(s)<8&&any((t==1)*m>2)a=[a;s];return;end;q=t==3-p;
(r=sort(~q.*(1:9)*m(:,find([3 1]*([q;t==p]*m)==6)')))||(r=find(~t));
for i=r t(i)=p;g([s i+47],3-p);t(i)=0;end;end;g('',1);f=@(n)a(n+1,:);

Thay đổi duy nhất có liên quan là chúng tôi không bao giờ kiểm tra xem người chơi hiện tại có thể giành chiến thắng hay không, chỉ kiểm tra khả năng của đối thủ để giành chiến thắng trong lượt tiếp theo . Vì lượt chơi duy nhất mà người chơi 1 có thể thắng là lượt 7 , đây là nơi duy nhất khi thuật toán tạo ra trò chơi không tối ưu, nhưng rất dễ dàng để loại bỏ tình huống như vậy. Chúng tôi chỉ đơn giản xác minh từng trò chơi được tạo nếu nó thắng bởi người chơi 1 - nếu không, việc di chuyển trong lượt 7 là không chính xác, vì vậy chúng tôi không thêm trò chơi này vào bảng trò chơi tối ưu.

(Chính xác một nửa số trò chơi được tạo bởi quy tắc này là sai, tức là trong lượt thứ 7, người chơi 1 luôn có hai khả năng chặn người chơi hai, nhưng chỉ có một trò chơi sẽ khiến anh ta thắng ngay lập tức).

Sử dụng:

$ octave
octave:1>> source script.m
octave:2>> f(634)
ans = 3270148

Mã không mã hóa trông giống như:

 global t=0*(1:9);
 global m=dec2bin([15;113;897;1170;1316;1608;2370;2216;2580])-48;
 global allgames;
 allgames=[];

 function r=canbewon(by)
  global t m
  q=[t==by;t==(3-by)]*m;
  g=(find([3 1]*q==6))';
  r=sort((~(t==by).*(1:9)) * m(:,g));
 end

 function games_starting_with(s)
 global allgames t;
 if 7==numel(s) && any((t==1)*m==3) # it's 7th move and first player won
  allgames=[allgames;s];
  return;
 end;
 poss=(find(~t));                  # for now all free slots are possible
 player=1+mod(numel(s),2);
 moves = canbewon(3-player);
 if numel(moves) poss=moves; end;  # ... no, we must block the other player
 for i=poss
  t(i)=player;
  games_starting_with([s char(i+47)]);
  t(i)=0;
 end
end

games_starting_with('');
f=@(n)(allgames(n+1,:));

1
gợi ý nhỏ: bạn có thể cắt bỏ các phiên bản cũ nếu chúng sử dụng cùng logic vì chúng được lưu trữ trong lịch sử chỉnh sửa để chúng vẫn có sẵn
masterX244
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.