quine-ish tic-tac-dedo do pé

19

Escreva um programa no idioma escolhido que jogue o jogo da velha em um tabuleiro 3 * 3 contra um jogador humano. No entanto, cada movimento deve ser um programa diferente , gerado a partir da iteração anterior.

A decisão de como e de que forma você avalia a contribuição humana depende de você, mas deve ser lida na contribuição padrão. Da mesma forma, você é livre para escolher um método para determinar qual jogador será iniciado (por exemplo, você pergunta primeiro ou permite que o ser humano insira um movimento inválido para sinalizar que o computador é iniciado ou outras idéias).

A validação de movimentos não é necessária, você pode assumir um oponente humano que joga bastante.

Basicamente, você tem um programa que corresponde a um estado do quadro. O estado é impresso de qualquer maneira reconhecível, mas pelo menos o seguinte nível de detalhe é esperado:

X..
00X
x..

Depois que o jogador humano entrou em seus movimentos, seu programa precisa gerar a próxima iteração de si mesmo como um arquivo de origem no mesmo idioma (para saída padrão ou para um arquivo) e finalizar. Você não tem permissão para armazenar informações em nenhum outro lugar fora desse arquivo de origem. (não é necessário que seu programa crie e execute o programa gerado, isso pode ser feito pelo usuário - no entanto, não é proibido). Quando o programa gerado for criado e executado, ele se comportará de maneira semelhante, exibirá o estado, aguardará a entrada do usuário etc.

No final do jogo, você deve imprimir o resultado (se ganhou ou é um empate) de qualquer maneira inequívoca.

Por jogo perfeito, quero dizer que o programa não deve perder e, se houver a possibilidade de forçar uma vitória, ele deve vencer.

O código mais curto vence , o vencedor é selecionado pelo menos 10 dias após a primeira entrada válida.

Você obtém uma redução de 10% na pontuação se o seu programa puder lidar com a criação e o lançamento de sua próxima iteração. (Eu sei, provavelmente não vale a pena) É claro que o próprio programa deve ser encerrado no momento em que a próxima iteração aceitar as mudanças do usuário.

Se você usar alguns truques estranhos e incomuns, poste uma breve explicação com seu código.

vsz
fonte
2
Bom desafio, mas acho que vou optar por não participar.
John Dvorak
"Todo movimento tem que ser um programa diferente". Você quer dizer "cada jogo deve ser iniciado e gerenciado por uma instância nova e distinta do programa original"?
DavidC 23/05
11
@DavidCarraher: Não. Todo movimento, não apenas todo jogo. Verifique a descrição abaixo do exemplo do quadro. Quando o computador precisa fazer uma mudança (para que o estado da placa mude), seu programa precisa gerar um arquivo de origem que, quando criado e executado, se tornará o próximo estado. O programa original então sai. O programa recém-gerado, ao fazer uma movimentação, se comportará de maneira semelhante: ele cria um arquivo de origem que, quando criado e executado, se tornará o próximo estado e assim por diante. Como nenhum armazenamento de informações é permitido, exceto no arquivo de origem gerado, é como uma solução com diferenças entre as iterações.
vsz 23/05

Respostas:

13

Perl, 933 caracteres

$m=<<'';$_='         ';
sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}

sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}

Observe que a linha em branco no meio do script realmente precisa estar lá. (As quebras de linha no final das linhas longas não são necessárias, exceto para legibilidade, e não estão incluídas na contagem de caracteres.)

Uso: Quando o programa é executado sem argumentos, ele exibe o estado atual do jogo. Como no início o quadro está vazio, a saída será:

...
...
...

Execute o programa com um argumento entre 1 e 9 para reivindicar esse quadrado como sua jogada. O programa fará sua própria jogada e, em seguida, produzirá um script de substituição com o novo estado. Assim, por exemplo:

$ perl ./qttt 5 > ./qttt-2
$ perl ./qttt-2
O..
.X.
...

Apenas no primeiro turno, você pode dar um passo 0para indicar que o computador deve dar o primeiro passo. Note que o primeiro jogador será sempre X.

Quando o jogo terminar, a saída do monitor incluirá uma nota para esse efeito:

$ perl ./qttt-4 6 > ./qttt-5
$ perl ./qttt-5
O wins
OXX
OOX
X.O

O programa funciona fazendo uma pesquisa minimax padrão da árvore do jogo. (O jogo da velha é um jogo pequeno o suficiente para que uma árvore de jogo completa possa ser gerada a cada corrida.) A exceção é quando o computador se move primeiro - nesse caso, o movimento inicial para o canto superior esquerdo é difícil. codificado.

Observe que este programa funciona da maneira adequada - em nenhum momento o script acessa seu próprio arquivo de origem para produzir sua saída.

caixa de pão
fonte
11
Isso é bonito! Eu não percebi que estava olhando para um imenso documento aqui por mais tempo, então dei uma olhada dupla.
21713 Jesse Smith