Talvez muitos dos veteranos se lembrem de uma epidemia de artigos com manchetes como "% something% in 30 lines of JS". E também o post épico "
Jogo em 0 linhas de código em JS puro " que se seguiu, após o qual a epidemia diminuiu abruptamente. Consciente de que nunca iria superar essa obra-prima, decidi, cinco anos depois, terminar meus cinco centavos.
Senhoras e senhores, oferecemos o jogo "Jogo da velha" em zero linhas de JS e, ao contrário do jogo mencionado acima, em zero linhas de CSS (incluindo estilos em linha). Apenas HTML, apenas hardcore.
→
Link para o jogoParece feio, mas funcionará em qualquer navegador. Abaixo, mostrarei por que o jogo sem JS estava na seção "Friday JS", além de outros detalhes sujos. No entanto, eu não vou abrir a América para ninguém, se você é um programador experiente, você não pode nem se deixar levar
Na verdade, tudo é muito estúpido. O jogo consiste em quase 6 mil páginas de HTML estático, vinculadas entre si. Quando você cutuca uma célula do campo de jogo, você acessa a página em que a mudança para essa célula já foi feita. Obviamente, escrever 6k páginas com as mãos é um prazer abaixo da média. Portanto (surpresa!) As páginas são geradas por scripts JS usando o NodeJS.
Digressão líricaTendo escrito a linha anterior, de repente me perguntei se a expressão "script JS" não é uma tautologia, como "CD-ROM" ou "VIP-person". Por um lado, parece ser. Por outro lado, JS ainda não é uma abreviação, mas uma abreviação de natureza ligeiramente diferente. No entanto, o post ainda não é sobre filologia, porque a digressão lírica termina e o ataque lírico começa.
Primeiro, construímos a chamada árvore dos jogos - a totalidade de todos os estados e transições possíveis entre eles. O estado inicial do jogo no meu código é o seguinte:
const initialState = { player: PLAYER_X, field: Array.from(Array(9)).map(() => EMPTY_CELL), moves: {} }
Ele contém informações sobre quem é a vez agora e qual é o estado do campo de jogo. No futuro, também conterá informações sobre quais movimentos podem ser feitos e em quais estados eles levarão, além de outras coisas agradáveis.
Então começamos, peço desculpas pela tautologia, a partir do estado inicial e faço o seguinte:
- Verificamos se o estado é terminal (vitória das cruzes, vitória das fichas, empate).
- Nesse caso, adicione informações sobre isso ao objeto state e finalize.
- Caso contrário, passe por todas as células no campo.
- Para cada célula vazia no campo, crie um novo estado de jogo no qual o jogador atual fez uma mudança para essa célula e a passagem foi passada para o próximo jogador.
- No campo de
moves
do estado atual, adicione um registro de um possível movimento. A chave para esta entrada é o índice da célula e o valor é o link para o novo estado. - Repetimos esse algoritmo recursivamente para todos os estados recém-exibidos.
De fato, meu código é um pouco mais complicado, por hábito desdobrei a recursão em um loop e, em vez de referências a outros estados nos
moves
suas chaves de string são armazenadas em uma certa matriz associativa. Mas estes são todos os detalhes.
Então, a partir de cada objeto de estado do jogo, geramos uma página HTML. Percorrendo o objeto de
moves
, preenchemos as células vazias do campo com links para as páginas correspondentes aos movimentos feitos nessas células. Em seguida, transformamos a matriz unidimensional do campo em uma tabela HTML bidimensional. Adicionamos todo tipo de coisas agradáveis, como instruções que o jogador percorre e links para a página inicial - e pronto!
Além do modo, quando as cruzes e os zeros são colocados por uma pessoa, no meu mega hit indie também há a oportunidade de jogar contra o cérebro de ferro. Isso é alcançado da seguinte maneira:
- Primeiro, recursivamente (na verdade não) para cada estado do jogo, o resultado esperado do jogo é calculado - aquele que será alcançado se os dois lados jogarem perfeitamente.
- Em seguida, a árvore do jogo é modificada da seguinte forma: em vez do movimento do jogador, agora fazemos dois movimentos ao mesmo tempo. O segundo movimento é o movimento da inteligência artificial. Além disso, a partir de todas as respostas possíveis à mudança do jogador, é selecionada aquela com o melhor resultado esperado. Assim, tendo cutucado uma gaiola vazia, o jogador vai imediatamente para a posição em que uma cruz (ou zero) apareceu nesta célula e um zero (ou cruz) apareceu em alguma outra célula.
- Todas as posições de jogo correspondentes aos movimentos que a IA não realiza são descartadas sem piedade.
- Em seguida, o HTML é gerado a partir das posições restantes em uma pasta separada - exatamente o mesmo que no caso de dois jogadores.
Por princípios semelhantes, você pode implementar qualquer jogo com uma árvore não muito grande. No entanto, se eu quiser fazer xadrez dessa maneira, parece-me que o github se recusará a hospedar isso =)
Falando no github: você pode ver todo o código (o link está na página principal do jogo). Sobre isso, em geral, é tudo. Adeus, meninas e meninos. Vejo você de novo.
PS A substituição de quebras de linha do estilo Windows para o estilo Unix é muito longa quando se trata de 6 mil arquivos. Eu me arrependi de não ter resolvido isso na fase de escrever o código, mas ainda assim suportou corajosamente o
git add
no final.