Todo mundo percebe que Tic Tac Toe é um jogo resolvido. No entanto, a versão Misère do only-Xs fornece uma alternativa interessante.
Nesta versão do jogo, os dois jogadores jogam Xs no tabuleiro e tentam evitar fazer três seguidas. Se você quiser saber mais sobre isso, o Numberphile tem um bom vídeo sobre esse conceito.
Dado um quadro de Misère Crosses, faça uma jogada ótima.
Um quadro é composto por três linhas de três caracteres cada, que são X
ou . Portanto:
X X
X
XX
é uma placa válida. Você pode fazer isso em qualquer formato conveniente, desde que sua entrada e saída usem o mesmo formato. Os formatos incluem (mas não estão limitados a): Uma sequência de várias linhas (com nova linha à direita opcional); Uma matriz 2D de caracteres que são X
ou ; uma matriz 1D achatada de valores booleanos representando se cada posição foi jogada.
Uma jogada ideal é aquela que garante que você vencerá, continuando a jogar de maneira ideal ou prolongando sua perda pelo maior tempo possível e é definido pelas seguintes regras:
- Evite fazer três seguidas.
- Se você for o primeiro, jogue no meio.
- Se o único espaço ocupado for o meio, toque em qualquer um dos espaços restantes.
- Se o quadrado do meio não estiver ocupado e um quadrado externo, jogue na frente do último jogo do seu oponente.
- Se o quadrado do meio estiver ocupado e um quadrado externo, toque um "movimento de cavaleiro" (oposto, um acima) do movimento anterior que não faz com que você perca.
- Se nenhum quadrado restante for deixado onde você não perderá, jogue em qualquer um dos quadrados restantes.
[OBSERVAÇÃO: isso provou não ser o ideal em um caso, mas você deve usar esse algoritmo de qualquer maneira.]
Você pode supor que todos os seus movimentos anteriores foram ótimos. Portanto, o primeiro quadro de exemplo não é uma entrada válida. Os movimentos do seu oponente podem ou não ser ótimos.
Se o jogo terminou (ou seja, foram feitos três em sequência), o comportamento é indefinido.
Como esse é o código-golfe , a resposta mais curta em bytes vence!
Um caminho possível, usando apenas movimentos ideais, é o seguinte:
[ ] [ ] [X ] [X ] [X ] [X ] [XX ]
[ ]->[ X ]->[ X ]->[ XX]->[ XX]->[ XX]->[ XX]
[ ] [ ] [ ] [ ] [ X ] [XX ] [XX ]
Aqui estão possíveis entradas originárias do oponente usando movimentos não ideais:
(Observe que apenas as placas do lado esquerdo nesta lista são entradas válidas.)
[X ] [X ]
[ ]->[ ]
[ ] [ X]
[XX ] [XX ]
[ ]->[ ]
[ X] [ XX]
[XX ] [XX ]
[X ]->[X X]
[ XX] [ XX]
.XX\nX..\nX..
por exemplo. Temos que considerar a possibilidade de herdar conselhos como este?Respostas:
Ruby, Rev B 121 bytes
Submissão é a função anônima, menos o
f=
. Mostrado no programa de teste para ilustrar o uso.2 bytes salvos tornando o quadrado do centro o bit menos significativo em vez do bit mais significativo (remova por em
/2
vez de%256
). Economias remanescentes por uma reorganização da tabela de movimentos aceitáveis. Organizar como quadrado central livre / ocupado, em vez de pelo número total de X, permite um teste mais simples. Além disso, agora existem apenas duas cadeias na matriz, portanto a%w{string1 string2}
sintaxe é abandonada em favor da["string1","string2"]
sintaxe. Isso permite que um caractere não imprimível\7
seja incluído, o que, por sua vez, permite que uma codificação mais simples seja usada: em126-t
vez de(36-t)%120
.Ruby, Rev A 143 bytes
Esta é uma função anônima. O formato de entrada / saída foi deixado aberto, por isso procurei um número binário de 9 bits. o bit de 512 representa o centro, com os bits restantes em espiral em torno dele (o bit de 1 é considerado um canto).
Existem muito mais entradas possíveis do que saídas aceitáveis; portanto, o algoritmo é tentar todas as jogadas e encontrar uma que se encaixe em um padrão de saída aceitável. Os padrões de saída aceitáveis para cada número de X são codificados.
As informações sobre o quadrado central são removidas e os 8 bits restantes são multiplicados por 257 para duplicá-los. Esse padrão é então rotacionado para além dos padrões aceitáveis pela mudança de direitos.
O loop não é encerrado quando um padrão é encontrado; portanto, o padrão retornado será o ÚLTIMO padrão aceitável encontrado. Por esse motivo, os padrões preferenciais (onde há uma preferência) aparecem mais adiante na lista.
Dada a estratégia 'Cavaleiros se movem', é de pouca importância se um padrão é girado 45 graus ou não. A versão não-gasta segue a estratégia de movimento dos cavaleiros e, portanto, não precisa diferenciar os quadrados dos cantos e dos quadrados das arestas: três de uma vez devem ser evitados de qualquer maneira.
No entanto, descobri que essa nem sempre é a melhor estratégia, pois existe o seguinte truque. Se o seu oponente for o primeiro e tomar o centro, ele deve vencer. Mas em seu segundo movimento, ele comete o erro de permitir que você faça um quadrado de 2x2, você deve aceitá-lo, pois isso permite que você o force a fazer três seguidas. Isso é implementado na versão golfed. É necessário um pouco de código extra nesse caso para distinguir entre três Xs em um canto (forçar o oponente a perder) e 3 Xs em uma borda (suicídio imediato).
Ungolfed in program program
A versão ungolfed segue a lógica expressa na pergunta.
Na versão golfed a tabela é ligeiramente modificado para
[[0],[1,17],[9],[37,7,51,85],[45],[47,119]]
implementar o comportamento ligeiramente diferente para o casor=3
. Em seguida, é compactado para ASCII imprimível (exigindo decodificação(t-36)%120
). É necessário um pouco de lógica adicional para diferenciar entre três Xs em um canto e três Xs ao longo de uma borda no caso da entrada da tabela 7:&&t+j%2!=43
Saída do programa de teste
É o que acontece quando o computador se reproduz.
ANÁLISE DO JOGO QUE JOGA PRIMEIRO
Isso é realmente muito simples e linear.
Ao jogar primeiro, o quadrado do meio será sempre o primeiro quadrado ocupado.
r = 0
r = 2
r = 4
Existe apenas uma maneira (até simetria) de ter cinco Xs, incluindo o quadrado do meio no tabuleiro, sem que o jogo termine. Há um X no quadrado do meio, um em cada diagonal (a 90 graus um do outro) e um em cada linha central horizontal / vertical (a 90 graus um do outro). Como uma borda inteira não pode ser ocupada, a única acima é a única arranjo possível. Outro jogador deve perder na próxima jogada.
ANÁLISE DO JOGO EM SEGUNDO JOGO
O jogo é bem diferente dependendo do outro jogador escolher o quadrado do meio.
r = 1
praça do meio ocupada
praça do meio livre
r = 3
Quadrado médio ocupado, se outro jogador jogar ao lado do seu último X. Jogar a jogada de um cavaleiro, como abaixo, é suportado na versão não-gasta
No entanto, a descrição acima NÃO é a melhor jogada e não é suportada na versão golfed. A melhor jogada é a seguinte, forçando uma vitória no próximo turno:
Quadrado médio ocupado, se outro jogador jogar a 90 ou 135 graus até o seu último X (toque o cavaleiro se afastar).
Praça do meio livre
r = 5
praça do meio ocupada. Pelas razões expostas acima em r = 4, há quatro movimentos possíveis, todos perdendo. apenas um é suportado: 101111 = 47.
praça do meio livre. Existe apenas uma placa possível até simetria, como segue. Outro jogador deve perder na próxima jogada, portanto não há necessidade de apoiar r> 5.
fonte