Jouons au Meta tic-tac-toe!

38

Permet de jouer à un jeu de Meta tic-tac-toe!

C'est un tournoi de Meta-tic-tac-toe. Les règles de Meta-tic-tac-toe sont les suivantes:

  1. Toutes les règles habituelles du tic-tac-toe s'appliquent.

  2. Il y a neuf tableaux conçus pour en faire un seul. Ainsi:

    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 
    

    le tableau 0 correspond au tableau en haut à gauche, le tableau 1 au tableau du milieu en haut ... comme celui-ci

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

    Si je dis conseil 3, tuile 4, cela signifie la tuile centrale du conseil sur le centre gauche.

  3. Vous ne pouvez vous déplacer que dans l'un des plus petits conseils.

  4. Si vous gagnez un des plus petits tableaux, ce tableau entier compte pour votre tuile.

  5. Si l'une des cartes est remplie avant que l'un des deux robots l'ait gagnée, elle compte comme tuile nul.

  6. Celui qui gagne le tableau principal gagne!

Cependant, il y a une torsion importante. Disons que je vais à bord 7, la tuile 2. Cela signifie que votre tour, vous pouvez seulement aller à bord 2. Ensuite , nous allons vous dire allez à bord 2, la tuile 5. Maintenant sur mon tour, je peux seulement aller à bord 5. Disons que le tableau 1 est plein. (Il ne reste plus de places, ou l'un d'entre nous a déjà gagné le tableau 1) Maintenant, si je vais au tableau 5, tuile 1, vous pouvez aller dans n'importe quel tableau que vous voulez.

Ces règles peuvent être considérées comme:

  1. Vous devez jouer dans le tableau correspondant à la position jouée par le joueur précédent.
    • Si X joue au tableau 2, la tuile 5; O doit jouer au tableau 5
  2. Si le tableau cible est plein (égalité) ou a déjà un vainqueur, le prochain coup n'est pas contraint.
  3. Un tableau avec un gagnant ne peut pas être joué, même sur un mouvement sans contrainte.

Si cela vous semble un peu déroutant, vous pouvez l’essayer en ligne ici. (assurez-vous de passer de "première tuile gagne" à "3 tuiles dans une rangée")

Maintenant, voici les règles du défi.

  1. Vous devez écrire un bot qui joue à ce jeu.

  2. Le bot 1 est un X, et il peut commencer en premier. Il sera appelé avec ces arguments de ligne de commande (sans les éléments entre parenthèses):

    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)
    

    Le premier caractère représente le bot. Dans ce cas, le bot 1 joue en tant que X. Les 9 lignes suivantes font référence aux 9 planches. La 11ème ligne se réfère au tableau principal. Le "xx" est le dernier coup. Maintenant, bot1 doit imprimer deux nombres compris entre 0 et 8. Le numéro 1 est le tableau dans lequel votre bot se déplace, et le numéro 2 est la tuile du tableau. Le contrôleur suivra ce mouvement. Supposons que le bot 1 en imprime 38. Le tableau ressemblera à ceci:

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

    et bot2 sera appelé avec ces arguments:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    --------- 
    ---------
    38
    
  3. Maintenant, le bot 2 doit se déplacer dans le tableau 8 (car le bot1 a placé un x dans la tuile 3). Supposons que bot2 en affiche 84. Le tableau ressemble à ceci.

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

    maintenant bot1 va être appelé avec ces arguments:

    X
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    ----0---- 
    ---------
    84
    
  4. Maintenant, bot1 doit être déplacé dans le tableau 4. Cependant, bot1 est un petit robot méchant et décide de passer au conseil 3. Il affiche '30'. Le conseil ne change pas du tout. Le maître bot garde une trace de cela. Maintenant bot2 sera appelé avec ces arguments:

    O
    ---------
    --------- 
    --------- 
    --------X 
    --------- 
    --------- 
    --------- 
    --------- 
    ----0---- 
    ---------
    xx
    
  5. Maintenant, bot 2 peut aller où il veut (sauf pour 38 et 84, bien sûr). Cela continue jusqu'à ce que quelqu'un gagne 3 cartes mères d'affilée. Ensuite, il y a un deuxième match où bot2 est X et commence en premier.

  6. Cela se répète jusqu'à ce que chaque bot ait joué contre tous les autres.

Notation

La notation fonctionne comme ceci:

Le gagnant d'un match est marqué par des 100 + number of open spotspoints. De cette façon, il est plus utile que votre bot gagne rapidement. Chaque fois que votre bot effectue un coup invalide, il perd 1 point. Si, après 250 tours, aucun des deux robots n'a gagné, chacun d'eux perd 10 points et nous passons au tour suivant.


Tout sera mis dans un répertoire qui contient

  1. Le bot de contrôleur. C’est un programme C ++ que j’ai écrit. Vous pouvez consulter le code source du bot du contrôleur ici. S'il vous plaît laissez-moi savoir si vous voyez quelque chose qui ne va pas avec le contrôleur.

  2. Un fichier texte nommé instructions.txtCe fichier ressemblera à ceci:

    [Total number of bots that are competing]
    
    [bot1Name] [bot1 command to run]
    [bot2Name] [bot2 command to run]
    ...
    
  3. Un dossier pour chaque bot. Ce dossier contiendra votre programme (qu'il s'agisse d'un script ou d'un binaire) et UN fichier texte nommé data.txtpermettant à votre bot de lire et d'écrire tout ce qu'il veut.

Spécifications techniques et clarifications de règles

  • Tout bot qui tente de lire / écrire quelque chose de n’importe où ailleurs que dans son dossier sera expulsé du jeu.

  • Votre programme doit pouvoir fonctionner sur un macbook exécutant Yosemite. Les langages actuellement supportés sont python (2.7.9 et 3.4.2), C / C ++, Objective-C, Perl, Ruby, Bash, PHP, Java, C #, javascript et Haskell. Il y en a beaucoup plus, mais ce ne sont que ceux auxquels je peux penser maintenant. J'ajouterai plus avec le temps. Si vous souhaitez concourir dans une langue spécifique, envoyez-moi un message ou un commentaire, et je l'ajouterai à la liste si possible.

  • Si un tableau est gagné, mais qu'il reste encore de la place, vous ne pouvez toujours pas vous rendre dans l'un des espaces libres.

  • Notez que le répertoire de travail de votre soumission sera le répertoire contenant le contrôleur et tous les autres robots, PAS le répertoire contenant votre bot.

  • S'il vous plaît postez avec votre code de bot de contrôleur la commande correcte pour compiler (le cas échéant) et pour exécuter votre bot. La plupart de ces opérations seront effectuées à partir du terminal OS X, qui est assez similaire à un terminal linux.

  • Les robots doivent compléter en moins d'une seconde. Malheureusement, je ne suis pas assez compétent pour ajouter une minuterie au bot du contrôleur. Cependant, je vais chronométrer les robots manuellement.


Résultats!

Eh bien, j'avais raison. J'ai oublié de faire vérifier par le bot du contrôleur si le masterBoard est plein. Si le masterBoard est plein, alors CHAQUE mouvement est invalide, mais il continue d'appeler les robots, ce qui explique probablement pourquoi il y a eu tant de mouvements invalides. Je l'ai corrigé maintenant. Voici les résultats officiels avec la version la plus récente de tous les robots.

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 est le champion en titre! Au moins pour le moment.

DJMcMayhem
la source
Soit dit en passant , avez-vous déjà examiné Fire and Ice (une version de pbem sur gamerz.net ) - il comporte quelques éléments de tic-tac-toe ... même si cela me faisait également penser à scribe .
9 goûts et 40 vues. Je suis impressionné!
Loovjo
5
Vous voudrez peut-être limiter le temps de réponse des robots, ou prendre trois minutes par mouvement pour rechercher tous les mouvements futurs possibles.
Logic Knight
1
J'ai ajouté quelques précisions sur les règles au sujet du prochain mouvement. Je m'inquiète du format des données et de l'une des règles. Règle 5 de la première section: "Si l’un des panneaux est rempli, cela compte comme un carreau nul." Est-ce rempli sans gagnant? C'est-à-dire que si quelqu'un gagne la tuile précédemment, et qu'elle devient remplie, s'agit-il de tuile? De plus, si les bots sont apatrides (ils semblent être) avec l'état transféré, comment le gagnant d'un tableau qui est XXX000---transmis est- il transmis? ou est-ce un "personne ne l'obtient malgré O ayant gagné le premier"?
@MichaelT le ​​gagnant du tableau est passé à la 11ème ligne. Je modifierai cette partie pour la rendre un peu plus claire, mais votre modification est incorrecte. "Si un tableau est gagné, mais qu'il y a toujours de la place, vous ne pouvez toujours pas vous rendre dans l'un des espaces libres."
DJMcMayhem

Réponses:

5

Python 2.7, Profondeur

Une mise en œuvre de la taille alpha-bêta sans rien d'extraordinaire. Il essaie d’ordonner les déménagements de manière moins naïve afin de maximiser les éliminations alpha-bêta. J'essaierai probablement d'accélérer les choses, mais honnêtement, je ne sais pas à quel point Python peut être compétitif s'il s'agit d'une question de vitesse.

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)

Pour l'exécuter, vous pouvez simplement le faire python Depth.py <input>, bien que je suggère d'utiliser pypycomme il accélère considérablement.

De plus, je ne sais pas à quelle vitesse votre système est rapide mais vous pouvez modifier le premier argument DepthPlayerà la fin pour qu'il soit plus élevé s'il peut encore s'exécuter dans le temps spécifié (sur mon système, il a presque tout terminé très rapidement avec une profondeur 7 ou 8, mais il y avait quelques cas qui étaient proches ou au-dessus d'une seconde alors je l'ai réglé à 6 pour être sûr).

KSab
la source
Python's sys.argvne renvoie pas de chaîne séparée par une nouvelle ligne. Il donne une liste de chaînes dans ce format: ['Depth.py', 'X', '---------', '---------', ...]je l'ai corrigé en éditant les deux dernières lignes, command = '\n'.join(sys.argv[1:]) print DepthPlayer(6).run(command)j'espère que cela ne vous dérange pas.
DJMcMayhem
@DJMcMayhem Oh merci, je n'ai pas testé cette dernière ligne.
KSab
2

Java, naïf

Si possible, ça gagne. Sinon, cela empêche un adversaire de gagner.

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!");
    }
}
Ypnypn
la source
Vous devrez me pardonner d'être un noob java, mais comment puis-je l'exécuter à partir du répertoire parent? J'ai Naive.classdans un répertoire nommé naiveBotdans le répertoire principal.
DJMcMayhem
@DJMcMayhem Je n'ai pas accès à un Mac, mais sous Windows, vous pouvez simplement exécuter la java Naive <args>commande, en supposant que les variables d'environnement incluent le pointeur sur C:\Program Files\Java\jdk1.8.0\bin. J'espère que ça aide.
Ypnypn
D'accord, je vais comprendre.
DJMcMayhem
@DJMcMayhem Si vous ne l'avez pas déjà java -classpath naiveBot Naive
compris
@Ypnypn Si la valeur legalAnywhereest true, votre soumission échoue parce que vous essayez d'utiliser des planches déjà gagnées par un joueur.
CommonGuy
2

Python 2, MiddleBot

MiddleBot aime le milieu. Avant que la partie centrale (4) ne soit gagnée, il tentera de saisir le centre du plus grand nombre de parties possible, forçant l'adversaire à revenir encore et encore à la partie centrale.
Une fois que cela est fait, il essaie de gagner tous les jeux possibles, ou remplit simplement le premier espace disponible sinon (il faut travailler sur son jeu en retard, je pense)

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)      

Pour le lancer, il python MiddleBot.py <input>me semble que ça me fait plaisir de passer moins d'une seconde, alors j'espère que ça le sera aussi pour vous

Logicien avec un chapeau
la source
Tout se passe bien, mais pour votre information, il se bloque lorsque le dernier mouvement est 'xx', ce qui se produit au début et à chaque fois qu'un bot effectue un déplacement invalide.
DJMcMayhem
Oops! Devrait être corrigé maintenant. J'ai oublié de tester le cas 'xx' dans cette itération, désolé!
LogicianWithAHat
Également effectué une édition - il tomberait en panne si un tableau avait été rempli sans vainqueur et il lui était demandé de jouer
LogicianWithAHat
0

Pourrait aussi bien jeter mon propre bot dans le mélange.

Python 2, bon RandomBot

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)

Ce bot ne se soucie pas de l'endroit où il se déplace, tant qu'il s'agit d'un mouvement valide. Choisit au hasard parmi tous les coups valides et effectue une moyenne des 0coups invalides.

DJMcMayhem
la source