มาเล่น Meta tic-tac-toe กันเถอะ!


38

ให้เล่นเกม Meta tic-tac-toe!

นี่คือการแข่งขันของ Meta tic-tac-toe กฎของ Meta tic-tac-toe มีดังนี้:

  1. ใช้กฎปกติทั้งหมดของโอเอกซ์

  2. มีเก้ากระดานที่จัดทำขึ้นเพื่อเป็นหนึ่งในคณะกรรมการหลัก ชอบมาก

    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 
    

    บอร์ด 0 หมายถึงกระดานซ้ายบน, กระดาน 1 หมายถึงกระดานกลางด้านบน ... เช่นนี้

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

    ถ้าผมบอกว่าบอร์ด 3, ไทล์ 4, นั่นหมายถึงไทล์ของบอร์ดตรงกลางซ้าย

  3. คุณได้รับอนุญาตเท่านั้นที่จะย้ายในหนึ่งในบอร์ดขนาดเล็ก

  4. หากคุณชนะกระดานใดกระดานหนึ่งที่มีขนาดเล็กลงกระดานทั้งหมดนั้นจะนับว่าเป็นไทล์ของคุณ

  5. หากบอร์ดใดบอร์ดหนึ่งเต็มก่อนที่บอทจะชนะก็จะนับว่าเป็นไพ่โนบิทอล

  6. ใครก็ตามที่ชนะบอร์ดมาสเตอร์จะเป็นผู้ชนะ!

อย่างไรก็ตามมีการบิดที่สำคัญ สมมติว่าผมไปในกระดานที่ 7 กระเบื้อง 2. นั่นหมายความว่าในทางกลับกันคุณสามารถเพียงไปในกระดาน 2. จากนั้นสมมติว่าคุณไปในกระดานที่ 2, กระเบื้อง 5. ตอนนี้เกี่ยวกับการเปิดของฉันฉันสามารถเท่านั้นไปในกระดาน 5 สมมติว่าบอร์ด 1 เต็มแล้ว (ไม่มีสปอตเหลืออีกหรือเราหนึ่งคนชนะบอร์ด 1) ตอนนี้ถ้าฉันไปที่บอร์ด 5, ไทล์ 1 คุณสามารถไปที่บอร์ดใดก็ได้ที่คุณต้องการ

กฎเหล่านี้ถือได้ว่า:

  1. คุณต้องเล่นในกระดานที่สอดคล้องกับตำแหน่งที่เล่นโดยผู้เล่นก่อนหน้า
    • ถ้า X เล่นในบอร์ด 2 ให้ไทล์ 5; O ต้องเล่นในบอร์ด 5
  2. หากบอร์ดเป้าหมายเต็ม (เสมอ) หรือมีผู้ชนะอยู่แล้วการเคลื่อนไหวครั้งต่อไปจะไม่มีข้อ จำกัด
  3. บอร์ดที่มีผู้ชนะอาจไม่สามารถเล่นได้แม้ว่าจะอยู่ในสภาพที่ไม่มีข้อ จำกัด

หากนี่สับสนเล็กน้อยคุณสามารถลองออนไลน์ได้ที่นี่(ตรวจสอบให้แน่ใจว่าได้เปลี่ยนจาก "ไทล์แรกชนะ" เป็น "3 ไทล์ในแถว")

ตอนนี้นี่คือกฎของการท้าทาย

  1. คุณต้องเขียนบอทที่เล่นเกมนี้

  2. บอท 1 คือ X และมันจะไปก่อน มันจะถูกเรียกด้วยอาร์กิวเมนต์บรรทัดคำสั่งเหล่านี้ (โดยไม่มีเนื้อหาในวงเล็บ):

    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)
    

    อักขระตัวแรกแสดงว่าบอทคือใคร ในกรณีนี้บ็อต 1 เล่นเป็น X 9 บรรทัดถัดไปหมายถึง 9 บอร์ด บรรทัดที่ 11 หมายถึงบอร์ดหลัก "xx" คือการเคลื่อนไหวครั้งสุดท้าย ตอนนี้ bot1 ต้องพิมพ์ตัวเลขสองตัวระหว่าง 0 ถึง 8 หมายเลข 1 คือกระดานที่บอทของคุณกำลังเคลื่อนที่และหมายเลข 2 คือไพ่ในบอร์ดดังกล่าว ผู้ควบคุมจะติดตามการเคลื่อนไหวนี้ สมมุติว่า bot 1 พิมพ์ 38 ตอนนี้บอร์ดก็จะเป็นแบบนี้:

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

    และ bot2 จะถูกเรียกด้วยอาร์กิวเมนต์เหล่านี้:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    --------- 
    ---------
    38
    
  3. ตอนนี้บอท 2 ต้องย้ายไปอยู่ในบอร์ด 8 (เพราะบอท 1 วาง x ลงในไทล์ 3) สมมุติว่า bot2 พิมพ์ 84 ทีนี้บอร์ดก็เป็นแบบนี้

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

    ตอนนี้ bot1 จะถูกเรียกด้วยอาร์กิวเมนต์เหล่านี้:

    X
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    ----0---- 
    ---------
    84
    
  4. ตอนนี้ bot1 ต้องย้ายไปอยู่ในบอร์ด 4 อย่างไรก็ตาม bot1 เป็นบอตตัวน้อยซุกซนและตัดสินใจที่จะย้ายเข้ามาในบอร์ด 3 มันพิมพ์ '30' คณะกรรมการจะไม่เปลี่ยนแปลงเลย บอทต้นแบบคอยติดตามสิ่งนี้ ตอนนี้ bot2 จะถูกเรียกด้วยอาร์กิวเมนต์เหล่านี้:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    ----0---- 
    ---------
    xx
    
  5. ตอนนี้บอท 2 สามารถไปได้ทุกที่ที่ต้องการ (ยกเว้นสำหรับ 38 และ 84 แน่นอน) สิ่งนี้จะดำเนินต่อไปจนกว่าจะมีใครชนะ 3 ของบอร์ดหลักในแถว จากนั้นมีคู่ที่สองที่ bot2 คือ X และเริ่มต้นก่อน

  6. การทำซ้ำนี้จนกว่าบอทเดียวจะเล่นบอทอื่น ๆ

เกณฑ์การให้คะแนน

การให้คะแนนทำงานเช่นนี้:

ผู้ชนะการแข่งขันแต่ละคนจะได้รับ100 + number of open spotsคะแนน ด้วยวิธีนี้จะมีค่ามากกว่าหากบอตของคุณชนะอย่างรวดเร็ว ทุกครั้งที่บอทของคุณเคลื่อนที่ไม่ถูกต้องจะเสีย 1 คะแนน ถ้าหลังจาก 250 รอบบอทไม่ชนะแต่ละบอทจะแพ้ 10 คะแนนและเราจะไปรอบต่อไป


ทุกอย่างจะถูกใส่ไว้ในไดเรกทอรีที่มี

  1. บอควบคุม นี่คือโปรแกรม C ++ ที่ฉันเขียน คุณสามารถดูรหัสแหล่งบอควบคุมได้ที่นี่ โปรดแจ้งให้เราทราบหากคุณเห็นสิ่งที่ไม่ถูกต้องกับคอนโทรลเลอร์

  2. ไฟล์ข้อความชื่อไฟล์instructions.txtนี้จะมีลักษณะดังนี้:

    [Total number of bots that are competing]
    
    [bot1Name] [bot1 command to run]
    [bot2Name] [bot2 command to run]
    ...
    
  3. โฟลเดอร์สำหรับแต่ละบอท โฟลเดอร์นี้จะเก็บโปรแกรมของคุณ (ไม่ว่าจะเป็นสคริปต์หรือไบนารี) และไฟล์ข้อความหนึ่งชื่อdata.txtที่บอตของคุณสามารถอ่านและเขียนสิ่งที่ต้องการ

ข้อกำหนดทางเทคนิคและการชี้แจงกฎ

  • บอทใด ๆ ที่พยายามอ่าน / เขียนบางสิ่งจากที่ใดก็ตามที่ไม่อยู่ในโฟลเดอร์จะถูกเตะออกจากเกม

  • โปรแกรมของคุณจะต้องสามารถทำงานบน macbook ที่ใช้โยเซมิตีได้ ภาษาที่รองรับในปัจจุบัน ได้แก่ python (2.7.9 และ 3.4.2), C / C ++, Object-C, perl, ruby, bash, PHP, Java, C #, javascript และ Haskell มีอีกมากมาย แต่สิ่งเหล่านี้เป็นเพียงสิ่งที่ฉันนึกได้ตอนนี้ ฉันจะเพิ่มมากขึ้นเมื่อเวลาผ่านไป หากคุณต้องการแข่งขันในภาษาใดข้อความหนึ่งให้ฉันหรือแสดงความคิดเห็นและฉันจะเพิ่มลงในรายการถ้าเป็นไปได้

  • หากบอร์ดชนะ แต่มีพื้นที่ว่างคุณจะไม่สามารถย้ายไปยังจุดที่เปิดโล่งแห่งใดแห่งหนึ่งได้

  • โปรดทราบว่าไดเรกทอรีทำงานของการส่งของคุณจะเป็นไดเรกทอรีที่มีตัวควบคุมและบอตอื่น ๆ ทั้งหมดไม่ใช่ไดเรกทอรีที่มีบอทของคุณ

  • กรุณาโพสต์พร้อมกับรหัสบอควบคุมของคุณคำสั่งที่ถูกต้องในการรวบรวม (ถ้ามี) และเรียกใช้บอทของคุณ ส่วนใหญ่จะทำจากเทอร์มินัล OS X ซึ่งค่อนข้างคล้ายกับเทอร์มินัลลินุกซ์

  • บอตจะต้องเสร็จสิ้นภายในไม่กี่วินาที น่าเสียดายที่ฉันไม่ค่อยเก่งพอที่จะเพิ่มตัวจับเวลาลงในบ็อตคอนโทรลเลอร์ อย่างไรก็ตามฉันจะตั้งเวลาบอทด้วยตนเอง


ผล!

ฉันพูดถูก ฉันลืมที่จะทำการบอตตัวควบคุมเพื่อตรวจสอบว่ามาสเตอร์เต็มหรือไม่ หากมาสเตอร์บอร์ดเต็มแล้วการเคลื่อนไหวทุกครั้งจะไม่ถูกต้อง แต่มันจะเรียกบอตต่อไปซึ่งอาจเป็นสาเหตุที่ทำให้มีการเคลื่อนไหวที่ไม่ถูกต้องมากมาย ฉันได้รับการแก้ไขแล้ว นี่คือผลการแข่งขันอย่างเป็นทางการกับเวอร์ชั่นล่าสุดของบอททั้งหมด

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.

บอทลึกเป็นแชมป์ที่ครองราชย์! อย่างน้อยตอนนี้


เช่นกันคุณเคยมองที่ไฟและน้ำแข็ง (รุ่น pbem ที่ gamerz.net ) - มีองค์ประกอบบางอย่างโอเอกซ์กับมัน ... แต่มันยังทำให้ผมนึกถึงอาลักษณ์

9 ไลค์และ 40 วิว ฉันประทับใจ!
Loovjo

5
คุณอาจต้องการ จำกัด เวลาตอบสนองของบอทหรือบอทอาจใช้เวลา 3 นาทีต่อการเคลื่อนไหวในขณะที่ค้นหาการเคลื่อนไหวในอนาคตที่เป็นไปได้ทั้งหมด
Logic Knight

1
ฉันได้เพิ่มการชี้แจงกฎบางอย่างเพื่อบิตเกี่ยวกับการย้ายครั้งต่อไป ฉันมีความกังวลเกี่ยวกับรูปแบบข้อมูลและกฎข้อใดข้อหนึ่ง กฎข้อที่ 5 จากส่วนแรก: "หากหนึ่งในกระดานเต็มไปแล้วจะนับว่าเป็นไพ่โนบิทอล" สิ่งนี้เต็มไปโดยไม่มีผู้ชนะหรือไม่? เช่นถ้ามีคนชนะกระเบื้องก่อนหน้านี้และมันจะกลายเป็นเต็มไปด้วยกระเบื้องโนเบิล? นอกจากนี้หากบอตไร้สัญชาติ (ปรากฏว่าเป็น) เมื่อรัฐผ่านไปแล้วผู้ชนะของบอร์ดที่XXX000---ได้รับการถ่ายทอดอย่างไร หรือว่า 'ไม่มีใครได้รับแม้ O จะได้รับมันก่อน'?

@MichaelT ผู้ชนะบอร์ดจะถูกส่งต่อในบรรทัดที่ 11 ฉันจะแก้ไขส่วนนี้เพื่อให้ชัดเจนขึ้นเล็กน้อย แต่การแก้ไขของคุณไม่ถูกต้อง “ หากบอร์ดชนะ แต่ยังมีพื้นที่ว่างคุณจะไม่สามารถย้ายไปยังจุดที่เปิดโล่งแห่งใดแห่งหนึ่งได้”
DJMcMayhem

คำตอบ:


5

Python 2.7 ความลึก

การตัดแต่งกิ่งด้วยอัลฟาเบต้าโดยไม่มีสิ่งใดแฟนซีเกินไป มันพยายามที่จะสั่งการเคลื่อนไหวด้วยวิธีที่ไร้เดียงสาน้อยที่สุดเพื่อเพิ่มการกำจัดอัลฟาเบต้า ฉันอาจจะพยายามทำให้มันเร็วขึ้น แต่จริงๆแล้วฉันไม่รู้ว่าการแข่งขันของ Python นั้นจะเกิดขึ้นได้อย่างไรหากมันมีคำถามเกี่ยวกับความเร็ว

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)

หากต้องการเรียกใช้คุณสามารถทำได้ python Depth.py <input>แม้ว่าฉันจะแนะนำให้ใช้pypyเพราะมันเพิ่มความเร็วอย่างเห็นได้ชัด

นอกจากนี้ฉันยังไม่ทราบว่าระบบของคุณเร็วแค่ไหน แต่คุณสามารถแก้ไขอาร์กิวเมนต์แรกให้DepthPlayerอยู่ในระดับที่สูงที่สุดได้ถ้ามันยังสามารถทำงานได้ตามเวลาที่กำหนด 7 หรือ 8 แต่มีบางกรณีที่อยู่ใกล้หรือสูงกว่าหนึ่งวินาทีดังนั้นฉันจึงตั้งค่าเป็น 6 เพื่อความปลอดภัย)


python sys.argvไม่ส่งคืนสายอักขระที่คั่นด้วยบรรทัดใหม่ มันให้รายการของสตริงในรูปแบบนี้: ['Depth.py', 'X', '---------', '---------', ...]ฉันแก้ไขโดยแก้ไขสองบรรทัดสุดท้ายนี้command = '\n'.join(sys.argv[1:]) print DepthPlayer(6).run(command)ฉันหวังว่าคุณจะไม่สนใจ
DJMcMayhem

@DJMcMayhem โอ้ขอบคุณฉันไม่ได้ทดสอบบรรทัดสุดท้าย
KSab

2

Java, ไร้เดียงสา

ถ้าเป็นไปได้มันจะชนะ มิฉะนั้นจะป้องกันคู่ต่อสู้จากการชนะ

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!");
    }
}

คุณจะต้องยกโทษให้ฉันสำหรับการเป็น java noob แต่ฉันจะเรียกใช้จากไดเรกทอรีหลักได้อย่างไร ฉันมีNaive.classชื่อnaiveBotอยู่ในไดเรกทอรีหลัก
DJMcMayhem

@DJMcMayhem ฉันไม่มีสิทธิ์เข้าถึง Mac แต่ใน Windows คุณสามารถเรียกใช้java Naive <args>คำสั่งโดยสมมติว่าตัวแปรสภาพแวดล้อมมีตัวชี้ไปC:\Program Files\Java\jdk1.8.0\binด้วย ฉันหวังว่านี่จะช่วยได้.
Ypnypn

เอาล่ะฉันจะคิดออก
DJMcMayhem

@DJMcMayhem หากคุณไม่ได้คิดออกแล้วก็java -classpath naiveBot Naive;)
CommonGuy

@Ypnypn หากlegalAnywhereเป็นจริงการส่งของคุณล้มเหลวเนื่องจากคุณพยายามใช้กระดานที่ผู้เล่นชนะแล้ว
CommonGuy

2

Python 2 MiddleBot

MiddleBot ชอบตรงกลาง ก่อนที่จะชนะเกมกลาง (4) มันจะพยายามคว้าสแควร์กลางของเกมให้ได้มากที่สุดบังคับให้คู่ต่อสู้กลับไปที่เกมกลางซ้ำแล้วซ้ำอีก
เมื่อทำสิ่งนี้เสร็จแล้วก็พยายามที่จะชนะเกมใด ๆ ที่ทำได้หรือเพียงแค่เติมพื้นที่ว่างก่อนถ้าไม่ (ต้องทำงานในเกมท้ายของมันฉันคิดว่า)

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)      

เมื่อต้องการเรียกใช้python MiddleBot.py <input>ดูเหมือนว่าจะวิ่งอย่างมีความสุขภายในไม่กี่วินาทีสำหรับฉันดังนั้นหวังว่าจะเป็นเช่นนั้นสำหรับคุณเช่นกัน


ทุกอย่างทำงานได้ดี แต่ FYI จะเกิดปัญหาเมื่อการย้ายครั้งล่าสุดคือ 'xx' ซึ่งเกิดขึ้นที่จุดเริ่มต้นและทุกครั้งที่บอททำการย้ายที่ไม่ถูกต้อง
DJMcMayhem

อ๊ะ! ควรได้รับการแก้ไขแล้ว ลืมทดสอบกรณี 'xx' ในการทำซ้ำนั้นขออภัย!
LogicianWithAHat

ทำการแก้ไขด้วยเช่นกัน - มันจะพังถ้าบอร์ดถูกเติมโดยไม่มีผู้ชนะและถูกขอให้เล่นที่นั่น
LogicianWithAHat

0

อาจจะโยนบอทของฉันเองลงไปในส่วนผสม

หลาม 2 ดีแบบสุ่มบอท

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)

บอทนี้ไม่สนใจว่ามันเคลื่อนที่ไปไหนตราบใดที่มันเป็นการเคลื่อนไหวที่ถูกต้อง เลือกโดยการสุ่มจากการเคลื่อนไหวที่ถูกต้องทั้งหมดและทำการ0ย้ายที่ไม่ถูกต้องโดยเฉลี่ย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.