Hãy chơi Meta tic-tac-toe!


38

Hãy chơi một trò chơi Meta tic-tac-toe!

Đây là một giải đấu của Meta tic-tac-toe. Các quy tắc của Meta tic-tac-toe như sau:

  1. Tất cả các quy tắc thông thường của tic-tac-toe áp dụng.

  2. Có chín bảng được sắp xếp để làm một bảng tổng thể. Thích như vậy:

    0|1|2 || 0|1|2 || 0|1|2 
    ----- || ----- || ----- 
    3|4|5 || 3|4|5 || 3|4|5 
    ----- || ----- || ----- 
    6|7|8 || 6|7|8 || 6|7|8 
    ========================
    0|1|2 || 0|1|2 || 0|1|2 
    ----- || ----- || ----- 
    3|4|5 || 3|4|5 || 3|4|5 
    ----- || ----- || ----- 
    6|7|8 || 6|7|8 || 6|7|8 
    ========================
    0|1|2 || 0|1|2 || 0|1|2 
    ----- || ----- || ----- 
    3|4|5 || 3|4|5 || 3|4|5 
    ----- || ----- || ----- 
    6|7|8 || 6|7|8 || 6|7|8 
    

    bảng 0 đề cập đến bảng trên cùng bên trái, bảng 1 đề cập đến bảng giữa trên cùng ... như thế này

    0|1|2
    -----
    3|4|5
    -----
    6|7|8
    

    Nếu tôi nói bảng 3, gạch 4, có nghĩa là gạch trung tâm của bảng ở giữa bên trái.

  3. Bạn chỉ được phép di chuyển trong một trong những bảng nhỏ hơn.

  4. Nếu bạn giành được một trong những bảng nhỏ hơn, toàn bộ bảng đó được tính là ô của bạn.

  5. Nếu một trong các bảng trở nên đầy trước khi một trong hai bot giành được nó, nó sẽ được tính là gạch quý tộc.

  6. Ai thắng bảng chủ sẽ thắng!

Tuy nhiên, có một bước ngoặt quan trọng. Giả sử tôi đi ở ván 7, ô 2. Điều đó có nghĩa là đến lượt của bạn, bạn chỉ có thể đi ở ván 2. Sau đó, giả sử bạn đi ở ván 2, ô 5. Bây giờ đến lượt tôi, tôi chỉ có thể đi ở ván 5. Hãy nói rằng bảng 1 đã đầy. (Không còn vị trí nào nữa, hoặc một trong số chúng tôi đã giành được bảng 1) Bây giờ nếu tôi vào bảng 5, ô 1, bạn có thể vào bất kỳ bảng nào bạn muốn.

Những quy tắc này có thể được coi là:

  1. Bạn phải chơi trong bảng tương ứng với vị trí mà người chơi trước đó đã chơi.
    • Nếu X chơi ở bảng 2, ô 5; O phải chơi ở ván 5
  2. Nếu bảng mục tiêu đã đầy (hòa) hoặc đã có người chiến thắng, bước tiếp theo sẽ không bị ràng buộc.
  3. Một bảng với một người chiến thắng có thể không được chơi, ngay cả khi di chuyển không bị ràng buộc.

Nếu điều này hơi khó hiểu, bạn có thể thử trực tuyến tại đây. (đảm bảo chuyển từ "gạch đầu tiên thắng" sang "3 gạch liên tiếp")

Bây giờ đây là các quy tắc của thách thức.

  1. Bạn phải viết một bot chơi trò chơi này.

  2. Bot 1 là Xs, và nó phải đi trước. Nó sẽ được gọi với các đối số dòng lệnh này (không có nội dung trong ngoặc đơn):

    X         (whose turn)
    --------- (board 0)
    --------- (board 1)
    --------- (board 2)
    --------- (board 3)
    --------- (board 4)
    --------- (board 5)
    --------- (board 6)
    --------- (board 7)
    --------- (board 8)
    --------- (master board)
    xx        (last move)
    

    Nhân vật đầu tiên đại diện cho bot là ai. Trong trường hợp này, bot 1 đóng vai trò X. 9 dòng tiếp theo đề cập đến 9 bảng. Dòng thứ 11 đề cập đến bảng tổng thể. "Xx" là bước cuối cùng. Bây giờ, bot1 phải in hai số từ 0 đến 8. Số 1 là bảng mà bot của bạn đang di chuyển và số 2 là ô trong bảng đã nói. Bộ điều khiển sẽ theo dõi di chuyển này. Giả sử bot 1 in 38. Bây giờ bảng sẽ trông như thế này:

     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ==========================
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |X ||  | |  ||  | |  
    ==========================
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    

    và bot2 sẽ được gọi với các đối số sau:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    --------- 
    ---------
    38
    
  3. Bây giờ bot 2 phải di chuyển trong bảng 8 (vì bot1 đã đặt x trong ô 3). Giả sử bot2 in 84. Bây giờ bảng trông như thế này.

     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ==========================
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |X ||  | |  ||  | |  
    ==========================
     | |  ||  | |  ||  | |  
    ----- || ----- || ----- 
     | |  ||  | |  ||  |O|  
    ----- || ----- || ----- 
     | |  ||  | |  ||  | |  
    

    bây giờ bot1 sẽ được gọi với các đối số sau:

    X
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    ----0---- 
    ---------
    84
    
  4. Bây giờ bot1 phải di chuyển trong bảng 4. Tuy nhiên, bot1 là một bot nhỏ nghịch ngợm và quyết định chuyển sang bảng 3. Nó in '30'. Hội đồng quản trị không thay đổi gì cả. Các bot chủ theo dõi điều này. Bây giờ bot2 sẽ được gọi với các đối số sau:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    ----0---- 
    ---------
    xx
    
  5. Bây giờ bot 2 có thể đi bất cứ nơi nào nó muốn (tất nhiên trừ 38 và 84). Điều này tiếp tục cho đến khi ai đó giành được 3 trong số các bảng tổng thể liên tiếp. Sau đó, có một trận đấu thứ hai trong đó bot2 là X và được đi trước.

  6. Điều này lặp lại cho đến khi mọi bot duy nhất đã chơi mọi bot khác.

Chấm điểm

Việc tính điểm như thế này:

Người chiến thắng trong mỗi trận đấu được 100 + number of open spotsđiểm. Bằng cách đó, nó có giá trị hơn nếu bot của bạn thắng nhanh chóng. Mỗi khi bot của bạn thực hiện một động thái không hợp lệ, nó sẽ mất 1 điểm. Nếu sau 250 vòng, không bot nào thắng, mỗi bot mất 10 điểm và chúng ta tiếp tục vào vòng tiếp theo.


Mọi thứ sẽ được đưa vào một thư mục chứa

  1. Bộ điều khiển bot. Đây là một chương trình C ++ mà tôi đã viết. Bạn có thể xem mã nguồn bot điều khiển ở đây. Vui lòng cho tôi biết nếu bạn thấy điều gì đó không đúng với bộ điều khiển.

  2. Một tệp văn bản có tên instructions.txtTệp này sẽ trông giống như thế này:

    [Total number of bots that are competing]
    
    [bot1Name] [bot1 command to run]
    [bot2Name] [bot2 command to run]
    ...
    
  3. Một thư mục cho mỗi bot. Thư mục này sẽ giữ chương trình của bạn (Cho dù đó là tập lệnh hay tệp nhị phân) và MỘT tệp văn bản có tên data.txtlà bot của bạn có thể đọc và viết bất cứ điều gì nó muốn.

Thông số kỹ thuật và làm rõ quy tắc

  • Bất kỳ bot nào cố gắng đọc / ghi một cái gì đó từ bất cứ nơi nào không có trong thư mục của nó sẽ bị đá khỏi trò chơi.

  • Chương trình của bạn phải có khả năng chạy trên macbook chạy Yosemite. Các ngôn ngữ hiện được hỗ trợ là python (2.7.9 và 3.4.2), C / C ++, object-C, perl, ruby, bash, PHP, Java, C #, javascript và Haskell. Còn nhiều điều nữa, nhưng đây chỉ là những thứ tôi có thể nghĩ ra ngay bây giờ. Tôi sẽ thêm nhiều hơn khi thời gian trôi qua. Nếu bạn muốn cạnh tranh bằng một ngôn ngữ cụ thể, hãy nhắn tin cho tôi hoặc nhận xét và tôi sẽ thêm nó vào danh sách nếu có thể.

  • Nếu một bảng được giành chiến thắng, nhưng vẫn còn không gian, bạn vẫn không thể di chuyển vào một trong những điểm mở.

  • Lưu ý rằng thư mục làm việc của trình của bạn sẽ là thư mục chứa bộ điều khiển và tất cả các bot khác, KHÔNG phải là thư mục chứa bot của bạn.

  • Vui lòng gửi cùng với mã bot điều khiển của bạn lệnh chính xác để biên dịch (nếu có) và để chạy bot của bạn. Hầu hết điều này sẽ được thực hiện từ thiết bị đầu cuối OS X, khá giống với thiết bị đầu cuối linux.

  • Bots phải hoàn thành trong một giây. Thật không may, tôi không đủ năng lực để thêm bộ đếm thời gian vào bot điều khiển. Tuy nhiên, tôi sẽ tự tay thời gian các bot.


Các kết quả!

Vâng, tôi đã đúng. Tôi quên làm cho bộ điều khiển bot kiểm tra xem masterBoard đã đầy chưa. Nếu masterBoard đã đầy, thì MỌI di chuyển không hợp lệ, nhưng nó vẫn tiếp tục gọi các bot, đó có thể là lý do tại sao có quá nhiều di chuyển không hợp lệ. Tôi đã sửa nó ngay bây giờ. Dưới đây là kết quả chính thức với phiên bản mới nhất của tất cả các bot.

Bot 1, goodRandBot, has 1 wins and made 0 illegal moves, for a total of 133 points.
Bot 2, naiveBot, has 3 wins and made 48 illegal moves, for a total of 361 points.
Bot 3, depthBot, has 5 wins and made 0 illegal moves, for a total of 664 points.
Bot 4, middleBot, has 1 wins and made 20 illegal moves, for a total of 114 points.

With 4 bots, This program took 477.471 seconds to finish.

Depth Bot là nhà vô địch trị vì! Ít nhất, cho ngay bây giờ.


Ở một khía cạnh khác, bạn đã bao giờ nhìn vào Fire and Ice (phiên bản pbem tại gamerz.net ) - có một số yếu tố tic-tac-toe với nó ... mặc dù điều này cũng khiến tôi nhớ đến scribe .

9 lượt thích và 40 lượt xem. Tôi rất ấn tượng!
Loovjo

5
Bạn có thể muốn đặt giới hạn về thời gian phản hồi của bot hoặc bot có thể mất 3 phút mỗi lần di chuyển trong khi tìm kiếm tất cả các chuyển động có thể trong tương lai.
Logic Knight

1
Tôi đã thêm một số làm rõ quy tắc cho bit về di chuyển tiếp theo. Tôi có một mối quan tâm về định dạng dữ liệu và một trong các quy tắc. Quy tắc 5 từ phần đầu tiên: "Nếu một trong các bảng trở nên đầy, nó được tính là gạch quý tộc." Đây có phải là đầy mà không có người chiến thắng? tức là nếu ai đó giành được gạch trước đó và nó trở nên đầy thì đó có phải là gạch cao quý không? Hơn nữa, nếu các bot không trạng thái (chúng có vẻ như vậy) với trạng thái được thông qua, làm thế nào để người chiến thắng của một bảng XXX000---được truyền đi? hoặc là "không ai có được nó mặc dù O đã giành được nó trước"?

@MichaelT người chiến thắng của hội đồng quản trị được thông qua trên dòng thứ 11. Tôi sẽ chỉnh sửa phần này để làm rõ hơn một chút, tuy nhiên chỉnh sửa của bạn không chính xác. "Nếu một bảng chiến thắng, nhưng vẫn còn không gian, bạn vẫn không thể di chuyển đến một trong những điểm mở."
DJMcMayhem

Câu trả lời:


5

Python 2.7, độ sâu

Việc thực hiện cắt tỉa alpha-beta mà không có gì quá lạ mắt. Nó cố gắng ra lệnh di chuyển theo cách ít ngây thơ hơn để tối đa hóa việc loại bỏ alpha-beta. Tôi có thể sẽ cố gắng tăng tốc nó, nhưng thực lòng tôi không biết Python có thể cạnh tranh như thế nào nếu gặp vấn đề về tốc độ.

class DepthPlayer:
    def __init__(self,depth):
        self.depth = depth

    def score(self,master,subs,last_move):
        total = 0
        for x in range(3):
            for y in range(3):
                c = master[3*y+x]
                if c == 0:
                    total += sum(subs[3*y+x])
                else:
                    total += c*10
                    for (dx,dy) in [(1,-1),(1,0),(0,1),(1,1)]:
                        if x+dx<=2 and 0<=y+dy<=2 and master[3*(y+dy)+(x+dx)] == c:
                            total += c*10
        if last_move is None or master[last_move[1]] != 0 or 0 not in subs[last_move[1]]:
            total += 5
        return total

    def winner(self,board):
        for y in range(3):
            row = board[3*y:3*y+3]
            if 0!=row[0]==row[1]==row[2]:
                return row[0]
        for x in range(3):
            col = board[x:9:3]
            if 0!=col[0]==col[1]==col[2]:
                return col[0]
        if 0!=board[0]==board[4]==board[8]:
            return board[0]
        if 0!=board[2]==board[4]==board[6]:
            return board[2]

        return 0

    def parse(self,input):
        lines = input.split('\n')
        team = lines[0]
        subs_str = lines[1:10]
        master_str = lines[10]
        last_move_str = lines[11]

        master = [1 if c==team else 0 if c=='-' else -1 for c in master_str]
        subs = [[1 if c==team else 0 if c=='-' else -1 for c in sub_str] for sub_str in subs_str]
        if last_move_str == 'xx':
            last_move = None

        else:
            last_move = [int(c) for c in last_move_str]
        return master,subs,last_move

    def alphabeta(self, master,subs,last_move, depth, alpha, beta, player):
        if depth == 0:
            return self.score(master,subs,last_move),None
        w = self.winner(master)
        if w != 0:
            return w*1000,None

        if player:
            v = -10000
            best = None
            for n_master,n_subs,n_last_move in self.all_moves(master,subs,last_move,1):
                nv,_ = self.alphabeta(n_master,n_subs,n_last_move, depth-1, alpha, beta, False)
                if nv>v:
                    v = nv
                    best = n_last_move
                alpha = max(alpha, v)
                if beta <= alpha:
                    break
            return v,best
        else:
            v = 10000
            best = None
            for n_master,n_subs,n_last_move in self.all_moves(master,subs,last_move,-1):
                nv,nb = self.alphabeta(n_master,n_subs,n_last_move, depth-1, alpha, beta, True)
                if nv<v:
                    v = nv
                    best = n_last_move
                beta = min(beta, v)
                if beta <= alpha:
                    break
            return v,best

    def make_move(self,master,subs,move,player):
        n_subs = [sub[:] for sub in subs]
        n_master = master[:]
        n_subs[move[0]][move[1]] = player
        if n_master[move[0]] == 0:
            n_master[move[0]] = self.winner(n_subs[move[0]])
        return n_master,n_subs,move

    def sub_moves(self,board):
        first = []
        second = []
        third = []
        for i in range(9):
            if board[i] != 0:
                continue
            y,x = divmod(i,3)
            c=-2
            if   x==0 and 0!=board[i+1]==board[i+2]>c: c=board[i+1]
            elif x==1 and 0!=board[i-1]==board[i+1]>c: c=board[i-1]
            elif x==2 and 0!=board[i-2]==board[i-1]>c: c=board[i-2]
            if   y==0 and 0!=board[i+3]==board[i+6]>c: c=board[i+3]
            elif y==1 and 0!=board[i-3]==board[i+3]>c: c=board[i-3]
            elif y==2 and 0!=board[i-6]==board[i-3]>c: c=board[i-6]
            if i in [0,4,8] and 0!=board[(i+4)%12]==board[(i+4)%12]>c: c=board[i-6]
            if i in [2,4,6] and 0!=board[6 if i==2 else i-2]==board[2 if i==6 else i+2]>c: c=board[i-6]

            if c==-2:   third.append(i)
            elif c==-1: second.append(i)
            else:       third.append(i)
        return first+second+third

    def all_moves(self,master,subs,last_move,player):
        if last_move is not None and master[last_move[1]]==0 and 0 in subs[last_move[1]]:
            for i in self.sub_moves(subs[last_move[1]]):
                yield self.make_move(master,subs,[last_move[1],i],player)

        else:
            for j in range(9):
                if master[j]==0 and 0 in subs[j]:
                    for i in self.sub_moves(subs[j]):
                        yield self.make_move(master,subs,[j,i],player)

    def move(self,master,subs,last_move):
        return self.alphabeta(master,subs,last_move, self.depth, -10000, 10000, True)[1]

    def run(self,input):
        result = self.move(*self.parse(input))
        if result:
            return str(result[0])+str(result[1])

def print_board(subs,player):
    string = ""
    for row in range(9):
        for sub in subs[row/3*3:row/3*3+3]:
            for c in sub[row%3*3:row%3*3+3]:
                string += "-XO"[c*(1 if player=='X' else -1)]
            string += ' '
        if row%3 == 2:
            string += '\n'
        string += '\n'
    print string

def to_string(master,subs,last_move,player):
    string = player+'\n'
    for sub in subs:
        for c in sub:
            string += "-XO"[c*(1 if player=='O' else -1)]
        string += '\n'
    for c in master:
        string += "-XO"[c*(1 if player=='O' else -1)]
    string += '\n'+str(last_move[0])+str(last_move[1])
    return string


import sys
command = '\n'.join(sys.argv[1:])
print DepthPlayer(8).run(command)

Để chạy nó, bạn có thể chỉ cần làm python Depth.py <input>, mặc dù tôi sẽ đề nghị sử dụng pypyvì nó tăng tốc đáng kể.

Ngoài ra tôi không biết hệ thống của bạn nhanh đến mức nào nhưng bạn có thể sửa đổi đối số đầu tiên thành DepthPlayercuối cùng để cao hơn nếu nó vẫn có thể chạy trong thời gian được chỉ định (trên hệ thống của tôi, nó đã hoàn thành hầu hết mọi thứ rất nhanh với độ sâu 7 hoặc 8, nhưng có một vài trường hợp gần hoặc trên một giây nên tôi đặt nó thành 6 để an toàn).


python's sys.argvkhông trả về một chuỗi phân tách dòng mới. Nó đưa ra một danh sách các chuỗi ở định dạng này: ['Depth.py', 'X', '---------', '---------', ...]Tôi đã sửa nó bằng cách chỉnh sửa hai dòng cuối cùng này, command = '\n'.join(sys.argv[1:]) print DepthPlayer(6).run(command)tôi hy vọng bạn không phiền.
DJMcMayhem

@DJMcMayhem Oh cảm ơn tôi đã không kiểm tra dòng cuối cùng.
KSab

2

Java, ngây thơ

Nếu có thể, nó thắng. Nếu không, nó ngăn cản đối thủ chiến thắng.

import java.util.Arrays;

public class Naive {

    public static void main(String[] args) {

        char[][] board = new char[9][9];
        for (int i = 0; i < 9; i++) {
            board[i] = args[i + 1].toCharArray();
        }
        char[] metaBox = args[10].toCharArray();

        char a = args[0].charAt(0),
                b = (char) ('X' + 'O' - a);

        int legalBox = args[11].charAt(1) - '0';
        boolean legalAnywhere = legalBox == 'x' - '0';
        if (!legalAnywhere) {
            if (wins(board[legalBox], 'X') || wins(board[legalBox], 'O')) {
                legalAnywhere = true;
            }
        }
        a:
        if (!legalAnywhere) {
            for (int i = 0; i < 9; i++) {
                if (board[legalBox][i] == '-') {
                    break a;
                }
            }
            legalAnywhere = true;
        }

        if (legalAnywhere) {
            chooseMove(board, metaBox, a, b);
        } else {
            chooseMove(board, metaBox, a, b, legalBox);
        }
    }

    static boolean canWinWith(char[] box, char c) {
        for (int i = 0; i < 9; i++) {
            if (wins(box, i, c)) {
                return true;
            }
        }
        return false;
    }

    static boolean wins(char[] box, int move, char c) {
        char[] copy = Arrays.copyOf(box, 9);
        copy[move] = c;
        return wins(copy, c);
    }

    static boolean wins(char[] box, char c) {
        return (box[0] == c && box[1] == c && box[2] == c)
               || (box[3] == c && box[4] == c && box[5] == c)
               || (box[6] == c && box[7] == c && box[8] == c)
               || (box[0] == c && box[3] == c && box[6] == c)
               || (box[1] == c && box[4] == c && box[7] == c)
               || (box[2] == c && box[5] == c && box[8] == c)
               || (box[0] == c && box[4] == c && box[8] == c)
               || (box[2] == c && box[4] == c && box[6] == c);
    }

    static void endWith(int box, int i) {
        System.out.println("" + box + i);
        System.exit(0);
    }

    private static void chooseMove(char[][] board, char[] metaBox, char a, char b, int legalBox) {
        for (int i = 0; i < 9; i++) {
            if (wins(board[legalBox], i, a) && board[legalBox][i] == '-') {
                endWith(legalBox, i);
            }
        }
        for (int i = 0; i < 9; i++) {
            if (wins(board[legalBox], i, b) && board[legalBox][i] == '-') {
                endWith(legalBox, i);
            }
        }
        for (int i = 0; i < 9; i++) {
            if (board[legalBox][i] == '-') {
                if (!canWinWith(board[i], b)) {
                    endWith(legalBox, i);
                }
            }
        }
        for (int i = 0; i < 9; i++) {
            if (board[legalBox][i] == '-') {
                endWith(legalBox, i);
            }
        }
        throw new RuntimeException("No move chosen!");
    }

    private static void chooseMove(char[][] board, char[] metaBox, char a, char b) {
        for (int box = 0; box < 9; box++) {
            for (int i = 0; i < 9; i++) {
                if (wins(board[box], i, a) && board[box][i] == '-') {
                    endWith(box, i);
                }
            }
        }
        for (int box = 0; box < 9; box++) {
            for (int i = 0; i < 9; i++) {
                if (wins(board[box], i, b) && board[box][i] == '-') {
                    endWith(box, i);
                }
            }
        }
        for (int box = 0; box < 9; box++) {
            for (int i = 0; i < 9; i++) {
                if (board[box][i] == '-') {
                    if (!canWinWith(board[i], b)) {
                        endWith(box, i);
                    }
                }
            }
        }
        for (int box = 0; box < 9; box++) {
            for (int i = 0; i < 9; i++) {
                if (board[box][i] == '-') {
                    endWith(box, i);
                }
            }
        }
        throw new RuntimeException("No move chosen!");
    }
}

Bạn sẽ phải tha thứ cho tôi vì là một java noob, nhưng làm thế nào để tôi chạy nó từ thư mục mẹ? Tôi có Naive.classtrong một thư mục có tên naiveBottrong thư mục chính.
DJMcMayhem

@DJMcMayhem Tôi không có quyền truy cập vào máy Mac, nhưng trên Windows, bạn chỉ có thể chạy java Naive <args>lệnh, giả sử các biến môi trường bao gồm con trỏ tới C:\Program Files\Java\jdk1.8.0\bin. Tôi hi vọng cái này giúp được.
Ypnypn

Được rồi, tôi sẽ tìm ra nó.
DJMcMayhem

@DJMcMayhem Nếu bạn chưa tìm ra nó, thì đó là java -classpath naiveBot Naive;)
CommonGuy

@Ypnypn Nếu legalAnywheređúng, việc gửi của bạn thất bại vì bạn cố gắng sử dụng các bảng đã được người chơi giành được.
CommonGuy

2

Python 2, MiddleBot

MiddleBot thích giữa. Trước khi trò chơi trung tâm (4) giành chiến thắng, nó sẽ cố gắng giành lấy ô vuông trung tâm của càng nhiều trò chơi càng tốt, buộc đối thủ quay lại trò chơi giữa chừng hết lần này đến lần khác.
Một khi điều này được thực hiện, nó cố gắng giành chiến thắng bất kỳ trò chơi nào có thể, hoặc chỉ lấp đầy không gian có sẵn đầu tiên nếu không (cần phải làm việc trên trò chơi muộn của nó, tôi nghĩ vậy)

from random import randint
import sys
command_in = '\n'.join(sys.argv[1:])
class MiddleBot:

    def scan_in(self,the_game):

        lines = the_game.split('\n')
        self.us = lines[0]
        if self.us == 'X':
            self.them = 'O'
        else:
            self.them = 'X'
        self.games = lines[1:10]
        self.metagame = lines[10]
        self.last_move = lines[11]

        try:
            self.sub_board = int(self.last_move[1])
        except ValueError:
            self.sub_board = self.last_move[1]

    def empty(self,game,target):
        if self.games[int(game)][int(target)] == '-':
            self.emptycell = 1
        else: self.emptycell = 0

    def empty_fill(self,game):
        #checks for next empty space, fills it
        for k in xrange(0,8):
            self.empty(game,k)
            if self.emptycell == 1:
                self.first_empty_space = k
                break
            if self.emptycell == 0:
                game = randint(0,8)
                self.first_empty_space = 4


    def aim_for_target(self,game,target):
        if self.games[int(game)][int(target)] == '-':
            self.move = `game` + `target`
        else:
            self.empty_fill(game)
            self.move = `game` + `self.first_empty_space`


    #define all win conditions        
    win = [0]*8            
    win[0] = [0,1,2]
    win[1] = [3,4,5]
    win[2] = [6,7,8]
    win[3] = [0,3,6]
    win[4] = [1,4,7]
    win[5] = [2,5,8]
    win[6] = [0,4,8]
    win[7] = [2,4,6]

    #check if current board state is one move away from 'us' winning
    def aim_for_win(self,game):
            for k in xrange(0,len(self.win)):
                if self.games[self.sub_board][self.win[k][0]] == self.games[self.sub_board][self.win[k][1]] == self.us:
                    self.empty(self.sub_board,self.win[k][2])
                    if self.emptycell == 1:
                        self.move = `self.sub_board`+`self.win[k][2]`
                    else:
                        self.empty_fill(self.sub_board)
                        self.move = `self.sub_board`,`self.first_empty_space`
                elif self.games[self.sub_board][self.win[k][0]] == self.games[self.sub_board][self.win[k][2]] == self.us:
                    self.empty(self.sub_board,self.win[k][1])
                    if self.emptycell == 1:
                        self.move = `self.sub_board`+`self.win[k][1]`
                    else:
                        self.empty_fill(self.sub_board)
                        self.move = `self.sub_board`+`self.first_empty_space`
                elif self.games[self.sub_board][self.win[k][1]] == self.games[self.sub_board][self.win[k][2]] == self.us:
                    self.empty(self.sub_board,self.win[k][0])
                    if self.emptycell == 1:
                        self.move = `self.sub_board`+`self.win[k][0]`
                    else:
                        self.empty_fill(self.sub_board)
                        self.move = `self.sub_board`+`self.first_empty_space`
                else:
                    self.empty_fill(self.sub_board)
                    self.move = `self.sub_board`+`self.first_empty_space`


    def play(self):
        #If the middle board is not won, aim for the middle square of each board
        if self.metagame[4] == '-':
            if self.sub_board == 4 or self.sub_board == 'x':
                self.aim_for_target(4,4)
            else:
                self.aim_for_target(self.sub_board,4)
        else:
            #once the middle board is won, pretty much plays randomly, aiming to win if it can, otherwise just filling the first empty space in each subgame
            played = 0
            if self.sub_board == 'x':
                self.sub_board = randint(0,8)
            while played == 0:
                if self.metagame[int(self.sub_board)] == '-':
                    self.aim_for_win(self.sub_board)
                    played = 1
                else:
                    self.sub_board = randint(0,8)
        return self.move

    def run(self,game_board):
        self.scan_in(game_board)
        self.play()
        return self.move

print MiddleBot().run(command_in)      

Để chạy nó, python MiddleBot.py <input>nó dường như hạnh phúc chạy dưới một giây cho tôi, vì vậy hy vọng nó cũng sẽ cho bạn


Mọi thứ đều chạy tốt, nhưng FYI, nó gặp sự cố khi di chuyển cuối cùng là 'xx' xảy ra lúc đầu và mỗi khi bot thực hiện một động thái không hợp lệ.
DJMcMayhem

Rất tiếc! Nên sửa ngay. Quên kiểm tra trường hợp 'xx' trong lần lặp đó, xin lỗi!
LogicianWithAHat

Cũng thực hiện một chỉnh sửa - nó sẽ sụp đổ nếu một bảng đã được điền mà không có người chiến thắng và nó được yêu cầu chơi ở đó
LogicianWithAHat

0

Cũng có thể ném bot của riêng tôi vào hỗn hợp.

python 2, goodRandomBot

import sys
from random import choice

args = sys.argv
if len(args) < 13:
    print ("I can't work with this!\n")
    sys.exit()

whoAmI = args[1];
masterBoard = list(args[11])
board = []
for i in range(2, 11):
    board.append(list(args[i]))

oppMove = args[12]

def findAllValidMoves(board, masterBoard):
    validMoves = []
    for row in range(9):
        if masterBoard[row] != '-':
            continue
        for col in range(len(board[row])):
            if board[row][col] == '-':
                validMoves.append(str(row) + str(col))
    return validMoves

validMoves = []
if oppMove == "xx" or masterBoard[int(oppMove[1])] != "-":
    validMoves = findAllValidMoves(board, masterBoard)    

else:
    row = int(oppMove[1])
    for col in range(len(board[row])):
        if board[row][col] == '-' and masterBoard[row] == "-":
            validMoves.append(str(row) + str(col))

if (validMoves == []):
    validMoves = findAllValidMoves(board, masterBoard)

print choice(validMoves)

Bot này không quan tâm nó di chuyển ở đâu, miễn là nó là một nước đi hợp lệ. Chọn ngẫu nhiên từ tất cả các di chuyển hợp lệ và tạo trung bình các 0di chuyển không hợp lệ.

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.