メタチックタックトーをプレイしましょう!


38

メタ三目並べのゲームをプレイしましょう!

これはですメタ三目並べのオブザトーナメントです。Meta tic-tac-toeのルールは次のとおりです。

  1. 三目並べの規則はすべて適用されます。

  2. 1つのマスターボードを作成するために9つのボードが配置されています。そのようです:

    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. 小さいボードの1つでしか移動できません。

  4. 小さいボードの1つに勝った場合、そのボード全体がタイルとしてカウントされます。

  5. いずれかのボットが勝つ前にボードの1つがいっぱいになると、nobodyタイルとしてカウントされます。

  6. マスターボードに勝った人が勝ちます!

ただし、重要なねじれがあります。ボード7、タイル2に行くとしましょう。つまり、あなたのターンでは、ボード2にしか行くことができません。次に、ボード2、タイル5に行くとしましょう。のみボード5に進みます。ボード1がいっぱいだとしましょう。(もうスポットが残っていないか、私たちの1人がすでにボード1を獲得しています)今、ボード5、タイル1に行くと、好きなボードに行くことができます。

これらのルールは次のように見なされます。

  1. 前のプレイヤーがプレイしたポジションに対応するボードでプレイする必要があります。
    • Xがボード2でプレーする場合、タイル5。Oはボード5でプレイする必要があります
  2. ターゲットボードがいっぱい(同点)の場合、または既に勝者がいる場合、次の動きは制約を受けません。
  3. 勝者のいるボードは、制約のない動きであってもプレーすることはできません

これが少しわかりにくい場合は、こちらからオンライン試すことができます。(「最初のタイルの勝ち」から「3タイルの連続」に切り替えるようにしてください)

これがチャレンジのルールです。

  1. このゲームをプレイするボットを作成する必要があります。

  2. Bot 1はXsであり、最初に行くことができます。これらのコマンドライン引数を使用して呼び出されます(かっこで囲まず)。

    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までの2つの数字を印刷する必要があります。数字1はボットが移動するボードで、数字2はそのボードのタイルです。コントローラーはこの動きを追跡します。ボット1が38を印刷するとします。ボードは次のようになります。

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

    bot2は次の引数で呼び出されます:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    --------- 
    ---------
    38
    
  3. ここで、ボット2はボード8で移動する必要があります(ボット1がタイル3にxを配置したため)。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で、最初に行く2番目の対戦があります。

  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、ボットが必要なものを読み書きできるテキストファイルが1つ含まれます。

技術仕様とルールの説明

  • フォルダー内以外の場所から何かを読み書きしようとするボットは、ゲームから追い出されます。

  • プログラムは、Yosemiteを実行しているMacbookで実行できる必要があります。現在サポートされている言語は、python(2.7.9および3.4​​.2)、C / C ++、objective-C、perl、ruby、bash、PHP、Java、C#、javascript、およびHaskellです。もっとたくさんありますが、これらは私が今考えることができるものです。時間が経つにつれて、さらに追加していきます。特定の言語で競争したい場合は、私にメッセージを送るかコメントしてください。可能な場合はリストに追加します。

  • ボードが勝ったが、まだスペースがある場合、あなたはまだオープンスポットのいずれかに移動することはできません。

  • 提出の作業ディレクトリは、ボットを含むディレクトリではなく、コントローラーと他のすべてのボットを含むディレクトリになります。

  • コントローラーボットコードと一緒に、適切なコマンドをコンパイルして(該当する場合)実行し、ボットを実行してください。これのほとんどは、Linux端末にかなり似ているOS X端末から行われます。

  • ボットは1秒以内に完了する必要があります。残念ながら、コントローラーボットにタイマーを追加するのに十分な能力はありません。ただし、ボットの時間を手動で調整します。


結果!

まあ、私は正しかった。masterBoardがいっぱいかどうかを確認するためにコントローラーボットをチェックするのを忘れました。masterBoardがいっぱいの場合、すべての移動は無効になりますが、ボットを呼び出し続けます。これが、おそらく非常に多くの無効な移動があった理由です。今すぐ修正しました。以下は、すべてのボットの最新バージョンでの公式結果です。

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は現チャンピオンです!少なくとも、今のところ。


さておき、あなたが今まで見てきたように火と氷(のPBEM版 gamerz.net) -これはかかわらず、いくつかの三目並べの要素が...そこにあるのを思い出しましたスクライブ

いいね9件、ビュー40件。私が感銘を受けた!
-Loovjo

5
ボットの応答時間に制限を設けたい場合があります。または、ボットがすべての可能な将来の動きを検索している間、動きごとに3分かかる場合があります。
ロジックナイト

1
次の動きについて少しルールの説明を追加しました。データ形式とルールの1つに懸念があります。最初のセクションのルール5:「ボードの1つがいっぱいになると、nobodyタイルとしてカウントされます。」これは勝者なしで満たされますか?すなわち、誰かが以前にタイルに勝ち、それが満たされた場合、それはnobodyタイルですか?さらに、状態が渡されたボットがステートレス(そうであるように見える)の場合、ボードの勝者はどのようXXX000---に送信されますか?または、「Oが最初に勝ったにもかかわらず、誰もそれを手に入れない」ということですか?

ボードの勝者である@MichaelTは11行目に渡されます。この部分を編集してもう少し明確にしますが、編集内容は正しくありません。「ボードが勝ったが、まだスペースがある場合は、オープンスポットの1つに移動することはできません。」
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ですが、1秒近くまたはそれ以上のケースがいくつかあったため、安全のために6に設定しました)。


python's sys.argvは改行で区切られた文字列を返しません。この形式の文字列のリストが表示されます。['Depth.py', 'X', '---------', '---------', ...]最後の2行を編集して修正しました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がtrueの場合、プレーヤーがすでに獲得しているボードを使用しようとするため、提出は失敗します。
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>それは私のために1秒未満で喜んで実行されるようですので、うまくいけばあなたのためにも


すべてうまくいきますが、参考までに、最後の動きが「xx」である場合にクラッシュします。これは、最初とボットが無効な動きをするたびに発生します。
DJMcMayhem

おっとっと!今すぐ修正する必要があります。その繰り返しで「xx」のケースをテストするのを忘れてしまった、ごめんなさい!
LogicianWithAHat

また、編集を行いました-勝者なしでボードがいっぱいになり、そこでプレイするように求められた場合、クラッシュします
-LogicianWithAHat

0

自分のボットをミックスに投入することもできます。

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)

このボットは、有効な移動である限り、どこに移動してもかまいません。すべての有効な動きからランダムに選択し、0無効な動きの平均を作成します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.