第3課

Desenvolvendo um jogo TicTacToe no Tezos

O mundo dos jogos blockchain está repleto de oportunidades para desenvolvedores. Ele fornece uma maneira única e inovadora de integrar mecanismos descentralizados e transparentes aos jogos. Ao desenvolver jogos em blockchain, podemos incorporar recursos como transações seguras e transparentes, propriedade de ativos no jogo e muito mais. Nesta lição, entraremos nos jogos blockchain desenvolvendo um jogo clássico de TicTacToe no blockchain Tezos. Nosso objetivo com esta lição é compreender a dinâmica da lógica do jogo e do gerenciamento de estado em um jogo baseado em blockchain.

Vamos começar explorando nosso contrato para o jogo TicTacToe:

Estrutura do Contrato

Python 
 # TicTacToe - Exemplo apenas para fins ilustrativos.

importar smartpy como sp 


 @sp.module 
 def main(): 
 class TicTacToe(sp.Contract): 
 def __init__(self): 
 self.data.nbMoves = 0 
 self.data.winner = 0 
 self.data.draw = Falso 
 self.data.deck = { 
 0: {0: 0, 1: 0, 2: 0}, 
 1: {0: 0, 1: 0, 2: 0}, 
 2: {0: 0, 1: 0, 2: 0}, 
 } 
 self.data.nextPlayer = 1 

 @ sp.entrypoint 
 def play(self, params): 
 assert self.data.winner == 0 e não self.data.draw 
 assert params.i >= 0 e params.i <3 
 afirmar params.j >= 0 e params.j <3 
 assert params.move == self.data.nextPlayer 
 assert self.data.deck[params.i][params.j] == 0 
 self.data.deck[params.i][params.j] = params.move 
 self.data.nbMoves += 1 
 self.data.nextPlayer = 3 - self.data.nextPlayer 
 self.data.winner = self.checkLine(
                sp.record(winner=self.data.winner, linha=self.data.deck[params.i])
            ) 
 self.data.winner = self.checkLine(
                sp.record( 
 vencedor = self.data.winner,
                    linha ={
                        0: self.data.deck[0][params.j],
                        1: self.data.deck[1][params.j],
                        2: self.data.deck[2][params.j],
                    }, 
 ) 
 ) 
 self.data.winner = self.checkLine(
                sp.record( 
 vencedor = self.data.winner,
                    linha ={
                        0: self.data.deck[0][0],
                        1: self.data.deck[1][1],
                        2: self.data.deck[2][2],
                    }, 
 ) 
 ) 
 self.data.winner = self.checkLine (
                sp.record( 
 vencedor = self.data.winner,
                    line={
                        0: self.data.deck[0][2],
                        1: self.data.deck[1][1],
                        2: self.data.deck[2][0],
                    }, 
 ) 
 ) 
 if self.data.nbMoves == 9 e self.data.winner == 0: 
 self.data.draw = True 

 @sp.private() 
 def checkLine(self , vencedor, linha): 
 vencedor_ = vencedor 
 if linha[0] != 0 e linha[0] == linha[1] e linha[0] == linha[2]: 
 vencedor_ = linha[0] 
 return vencedor_ 

 # Adiciona uma função de reinicialização do jogo 
 @sp.entrypoint 
 def confirm_and_reset(self): 
 assert self.data.winner != 0 ou self.data.draw 
 self.__init__()

# Testa 
 se "modelos" não estiverem em __name__: 

 @sp.add_test(name="TicTacToe") 
 def test(): 
 cenário = sp.test_scenario(main)
        cenário.h1("Jogo da Velha")
        # define um contrato 
 c1 = main.TicTacToe() 

 # mostra sua representação 
 cenário.h2("A sequência de interações com um vencedor") 
 cenário += c1 
 cenário.h2("Mensagem execução") 
 cenário.h3("A primeiro movimento no centro") 
 c1.play(i=1, j=1, move=1) 
 cenário.h3("A movimento proibido") 
 c1.play(i=1, j=1, move=2).run(valid=False)
        cenário.h3("Um segundo movimento") 
 c1.play(i=1, j=2, movimento=2) 
 cenário.h3("Outro movimentos") 
 c1.play(i=2, j=1, move=1) 
 c1.play(i=2, j=2, move=2) 
 cenário.verify(c1.data.winner == 0 ) 
 c1.play(i=0, j=1, move=1) 
 cenário.verify(c1.data.winner == 1) 
 cenário.p("Jogador1 ganhou") 
 c1.play(i=0, j=0, move=2).run(valid=False)

        c2 = main.TicTacToe() 
 cenário.h2("A sequência de interações com empate") 
 cenário += c2 
 cenário.h2("Mensagem execução") 
 cenário.h3("A primeiro movimento no centro") 
 c2.play(i=1, j=1, move=1) 
 cenário.h3("A movimento proibido") 
 c2.play(i=1, j=1, move=2).run(valid=False)
        cenário.h3("Um segundo movimento") 
 c2.play(i=1, j=2, movimento=2) 
 cenário.h3("Outro movimentos") 
 c2.play(i=2, j=1, move=1) 
 c2.play(i=2, j=2, move=2) 
 c2.play(i=0, j=0, mover=1) 
 c2.play(i=0, j=1, mover=2) 
 c2.play(i=0, j=2, mover=1) 
 c2.play(i=2, j=0 , move=2) 
 c2.play(i=1, j=0, move=1) 

 # Adiciona testes para reinicialização do jogo 
 cenário.h2("Testando reinicialização do jogo") 
 cenário.p("Vencedor ou empate confirmado, agora zerando o jogo") 
 c1.confirm_and_reset() 
 cenário.verify(c1.data.nbMoves == 0) 
 cenário.verify(c1.data.winner == 0) 
 cenário.verify(not c1.data.draw)

        c2.confirm_and_reset() 
 cenário.verify(c2.data.nbMoves == 0) 
 cenário.verify(c2.data.winner == 0) 
 cenário.verify(não c2.data.draw)

O contrato do nosso jogo TicTacToe no Tezos está escrito na linguagem SmartPy. Consiste em duas partes principais: o estado do contrato e a lógica do jogo.

Estado do Contrato

O estado do contrato é inicializado na função **init . Inclui:

  • nbMoves: Este é um contador do número de movimentos feitos no jogo. Começa do zero.
  • winner: Isso mantém o controle do vencedor do jogo. Inicialmente é zero, indicando que não há vencedor.
  • draw: Esta é uma bandeira que indica se o jogo terminou empatado. Inicialmente, é falso.
  • deck: Esta é uma grade 3x3 que representa o tabuleiro TicTacToe. Todos os espaços do tabuleiro estão inicialmente vazios, representados por zeros.
  • nextPlayer: indica de quem é a vez de jogar. O jogo começa com o jogador 1, então inicialmente é definido como 1.

Lógica do jogo

A lógica do jogo está encapsulada na função play . Ele executa diversas verificações para garantir uma movimentação válida:

  • Ele verifica se nenhum jogador ganhou ainda e se o jogo não está empatado.
  • Verifica se os índices do ponto da grade escolhido pelo jogador estão dentro dos limites da grade.
  • Garante que o jogador que faz a jogada corresponda ao nextPlayer.
  • Garante que o local escolhido na grade esteja vazio.
    Depois que um movimento é feito, a lógica do jogo incrementa nbMoves, troca o nextPlayer e verifica se o movimento resultou em vitória ou empate.

A condição de vitória é verificada na linha e coluna do último movimento, bem como nas duas diagonais.

Se todas as vagas no tabuleiro estiverem preenchidas e nenhum jogador tiver vencido (ou seja, nbMoves é igual a 9 e winner ainda é 0), o jogo é declarado empatado.

Verificando uma vitória

A função checkLine é usada para verificar se algum jogador ganhou. Ele verifica se todos os espaços de uma linha (que pode ser uma linha, uma coluna ou uma diagonal) foram preenchidos pelo mesmo jogador. Nesse caso, esse jogador é declarado o vencedor.

Interagindo com o Contrato

As interações com o contrato são representadas como transações. Quando um jogador faz uma jogada chamando a função play , isso gera uma transação. Esta transação é registrada e pode ser vista no painel direito do SmartPy IDE:

Uma movimentação malsucedida ou inválida também geraria uma transação, mas com uma indicação de erro:

O segundo movimento e além

O primeiro movimento em nosso jogo TicTacToe é relativamente simples, pois o tabuleiro do jogo está vazio. No entanto, as coisas ficam mais interessantes com o segundo movimento e os movimentos subsequentes. Esses movimentos não apenas adicionam peças ao tabuleiro, mas também invocam a lógica do jogo para verificar possíveis vencedores.

Após o primeiro movimento, o valor nextPlayer muda para o jogador 2. Agora, a função play valida o movimento do jogador 2. Verificações semelhantes são realizadas para garantir que o movimento é válido, ou seja, o ponto da grade selecionado está dentro dos limites e está vazio.

À medida que cada jogador faz uma jogada, o estado do jogo evolui. O nbMoves aumenta, o nextPlayer alterna e o deck é atualizado. Além disso, após cada jogada, o contrato verifica se há vencedor ou se há empate.

Por exemplo, depois que o primeiro jogador faz um movimento no centro do tabuleiro em i=1, j=1, o segundo jogador pode jogar em um local diferente, digamos i=1, j=2. Ambos os movimentos seriam validados e executados com sucesso, com as transações correspondentes sendo geradas.

Os outros movimentos e progressão do jogo

Os movimentos subsequentes continuam de maneira semelhante. Cada jogador se reveza no jogo, escolhendo um lugar vazio no tabuleiro. Após cada movimento, o contrato verifica qualquer condição de vitória. Se um jogador preencher uma linha, coluna ou diagonal inteira com seu símbolo, o jogo termina e esse jogador é declarado vencedor. A variável winner no estado do contrato seria atualizada adequadamente.

É importante notar que uma vez que um jogador tenha vencido, nenhum outro movimento será válido. Qualquer tentativa de fazer um movimento após o término do jogo seria considerada inválida e a transação correspondente falharia.

O cenário do sorteio

Em alguns jogos, é possível que nenhum jogador alcance a condição de vitória mesmo depois de todo o tabuleiro estar preenchido. Isso resulta em um empate. O contrato também foi concebido para lidar com esta situação.

Se todas as vagas no tabuleiro estiverem preenchidas (nbMoves é igual a 9) e nenhum jogador ganhou (winner permanece 0), o jogo é declarado empatado. A bandeira draw no estado do contrato é definida como True, indicando que o jogo terminou empatado. Mais uma vez, nenhum movimento adicional é válido após este ponto. Qualquer tentativa de fazer um movimento após um empate também falharia.

A segunda parte do cenário de teste do contrato TicTacToe demonstra esse cenário de desenho. Simula uma série de movimentos que resultam em empate e verifica se o contrato o trata corretamente.

免責聲明
* 投資有風險,入市須謹慎。本課程不作為投資理財建議。
* 本課程由入駐Gate Learn的作者創作,觀點僅代表作者本人,絕不代表Gate Learn讚同其觀點或證實其描述。
目錄
第3課

Desenvolvendo um jogo TicTacToe no Tezos

O mundo dos jogos blockchain está repleto de oportunidades para desenvolvedores. Ele fornece uma maneira única e inovadora de integrar mecanismos descentralizados e transparentes aos jogos. Ao desenvolver jogos em blockchain, podemos incorporar recursos como transações seguras e transparentes, propriedade de ativos no jogo e muito mais. Nesta lição, entraremos nos jogos blockchain desenvolvendo um jogo clássico de TicTacToe no blockchain Tezos. Nosso objetivo com esta lição é compreender a dinâmica da lógica do jogo e do gerenciamento de estado em um jogo baseado em blockchain.

Vamos começar explorando nosso contrato para o jogo TicTacToe:

Estrutura do Contrato

Python 
 # TicTacToe - Exemplo apenas para fins ilustrativos.

importar smartpy como sp 


 @sp.module 
 def main(): 
 class TicTacToe(sp.Contract): 
 def __init__(self): 
 self.data.nbMoves = 0 
 self.data.winner = 0 
 self.data.draw = Falso 
 self.data.deck = { 
 0: {0: 0, 1: 0, 2: 0}, 
 1: {0: 0, 1: 0, 2: 0}, 
 2: {0: 0, 1: 0, 2: 0}, 
 } 
 self.data.nextPlayer = 1 

 @ sp.entrypoint 
 def play(self, params): 
 assert self.data.winner == 0 e não self.data.draw 
 assert params.i >= 0 e params.i <3 
 afirmar params.j >= 0 e params.j <3 
 assert params.move == self.data.nextPlayer 
 assert self.data.deck[params.i][params.j] == 0 
 self.data.deck[params.i][params.j] = params.move 
 self.data.nbMoves += 1 
 self.data.nextPlayer = 3 - self.data.nextPlayer 
 self.data.winner = self.checkLine(
                sp.record(winner=self.data.winner, linha=self.data.deck[params.i])
            ) 
 self.data.winner = self.checkLine(
                sp.record( 
 vencedor = self.data.winner,
                    linha ={
                        0: self.data.deck[0][params.j],
                        1: self.data.deck[1][params.j],
                        2: self.data.deck[2][params.j],
                    }, 
 ) 
 ) 
 self.data.winner = self.checkLine(
                sp.record( 
 vencedor = self.data.winner,
                    linha ={
                        0: self.data.deck[0][0],
                        1: self.data.deck[1][1],
                        2: self.data.deck[2][2],
                    }, 
 ) 
 ) 
 self.data.winner = self.checkLine (
                sp.record( 
 vencedor = self.data.winner,
                    line={
                        0: self.data.deck[0][2],
                        1: self.data.deck[1][1],
                        2: self.data.deck[2][0],
                    }, 
 ) 
 ) 
 if self.data.nbMoves == 9 e self.data.winner == 0: 
 self.data.draw = True 

 @sp.private() 
 def checkLine(self , vencedor, linha): 
 vencedor_ = vencedor 
 if linha[0] != 0 e linha[0] == linha[1] e linha[0] == linha[2]: 
 vencedor_ = linha[0] 
 return vencedor_ 

 # Adiciona uma função de reinicialização do jogo 
 @sp.entrypoint 
 def confirm_and_reset(self): 
 assert self.data.winner != 0 ou self.data.draw 
 self.__init__()

# Testa 
 se "modelos" não estiverem em __name__: 

 @sp.add_test(name="TicTacToe") 
 def test(): 
 cenário = sp.test_scenario(main)
        cenário.h1("Jogo da Velha")
        # define um contrato 
 c1 = main.TicTacToe() 

 # mostra sua representação 
 cenário.h2("A sequência de interações com um vencedor") 
 cenário += c1 
 cenário.h2("Mensagem execução") 
 cenário.h3("A primeiro movimento no centro") 
 c1.play(i=1, j=1, move=1) 
 cenário.h3("A movimento proibido") 
 c1.play(i=1, j=1, move=2).run(valid=False)
        cenário.h3("Um segundo movimento") 
 c1.play(i=1, j=2, movimento=2) 
 cenário.h3("Outro movimentos") 
 c1.play(i=2, j=1, move=1) 
 c1.play(i=2, j=2, move=2) 
 cenário.verify(c1.data.winner == 0 ) 
 c1.play(i=0, j=1, move=1) 
 cenário.verify(c1.data.winner == 1) 
 cenário.p("Jogador1 ganhou") 
 c1.play(i=0, j=0, move=2).run(valid=False)

        c2 = main.TicTacToe() 
 cenário.h2("A sequência de interações com empate") 
 cenário += c2 
 cenário.h2("Mensagem execução") 
 cenário.h3("A primeiro movimento no centro") 
 c2.play(i=1, j=1, move=1) 
 cenário.h3("A movimento proibido") 
 c2.play(i=1, j=1, move=2).run(valid=False)
        cenário.h3("Um segundo movimento") 
 c2.play(i=1, j=2, movimento=2) 
 cenário.h3("Outro movimentos") 
 c2.play(i=2, j=1, move=1) 
 c2.play(i=2, j=2, move=2) 
 c2.play(i=0, j=0, mover=1) 
 c2.play(i=0, j=1, mover=2) 
 c2.play(i=0, j=2, mover=1) 
 c2.play(i=2, j=0 , move=2) 
 c2.play(i=1, j=0, move=1) 

 # Adiciona testes para reinicialização do jogo 
 cenário.h2("Testando reinicialização do jogo") 
 cenário.p("Vencedor ou empate confirmado, agora zerando o jogo") 
 c1.confirm_and_reset() 
 cenário.verify(c1.data.nbMoves == 0) 
 cenário.verify(c1.data.winner == 0) 
 cenário.verify(not c1.data.draw)

        c2.confirm_and_reset() 
 cenário.verify(c2.data.nbMoves == 0) 
 cenário.verify(c2.data.winner == 0) 
 cenário.verify(não c2.data.draw)

O contrato do nosso jogo TicTacToe no Tezos está escrito na linguagem SmartPy. Consiste em duas partes principais: o estado do contrato e a lógica do jogo.

Estado do Contrato

O estado do contrato é inicializado na função **init . Inclui:

  • nbMoves: Este é um contador do número de movimentos feitos no jogo. Começa do zero.
  • winner: Isso mantém o controle do vencedor do jogo. Inicialmente é zero, indicando que não há vencedor.
  • draw: Esta é uma bandeira que indica se o jogo terminou empatado. Inicialmente, é falso.
  • deck: Esta é uma grade 3x3 que representa o tabuleiro TicTacToe. Todos os espaços do tabuleiro estão inicialmente vazios, representados por zeros.
  • nextPlayer: indica de quem é a vez de jogar. O jogo começa com o jogador 1, então inicialmente é definido como 1.

Lógica do jogo

A lógica do jogo está encapsulada na função play . Ele executa diversas verificações para garantir uma movimentação válida:

  • Ele verifica se nenhum jogador ganhou ainda e se o jogo não está empatado.
  • Verifica se os índices do ponto da grade escolhido pelo jogador estão dentro dos limites da grade.
  • Garante que o jogador que faz a jogada corresponda ao nextPlayer.
  • Garante que o local escolhido na grade esteja vazio.
    Depois que um movimento é feito, a lógica do jogo incrementa nbMoves, troca o nextPlayer e verifica se o movimento resultou em vitória ou empate.

A condição de vitória é verificada na linha e coluna do último movimento, bem como nas duas diagonais.

Se todas as vagas no tabuleiro estiverem preenchidas e nenhum jogador tiver vencido (ou seja, nbMoves é igual a 9 e winner ainda é 0), o jogo é declarado empatado.

Verificando uma vitória

A função checkLine é usada para verificar se algum jogador ganhou. Ele verifica se todos os espaços de uma linha (que pode ser uma linha, uma coluna ou uma diagonal) foram preenchidos pelo mesmo jogador. Nesse caso, esse jogador é declarado o vencedor.

Interagindo com o Contrato

As interações com o contrato são representadas como transações. Quando um jogador faz uma jogada chamando a função play , isso gera uma transação. Esta transação é registrada e pode ser vista no painel direito do SmartPy IDE:

Uma movimentação malsucedida ou inválida também geraria uma transação, mas com uma indicação de erro:

O segundo movimento e além

O primeiro movimento em nosso jogo TicTacToe é relativamente simples, pois o tabuleiro do jogo está vazio. No entanto, as coisas ficam mais interessantes com o segundo movimento e os movimentos subsequentes. Esses movimentos não apenas adicionam peças ao tabuleiro, mas também invocam a lógica do jogo para verificar possíveis vencedores.

Após o primeiro movimento, o valor nextPlayer muda para o jogador 2. Agora, a função play valida o movimento do jogador 2. Verificações semelhantes são realizadas para garantir que o movimento é válido, ou seja, o ponto da grade selecionado está dentro dos limites e está vazio.

À medida que cada jogador faz uma jogada, o estado do jogo evolui. O nbMoves aumenta, o nextPlayer alterna e o deck é atualizado. Além disso, após cada jogada, o contrato verifica se há vencedor ou se há empate.

Por exemplo, depois que o primeiro jogador faz um movimento no centro do tabuleiro em i=1, j=1, o segundo jogador pode jogar em um local diferente, digamos i=1, j=2. Ambos os movimentos seriam validados e executados com sucesso, com as transações correspondentes sendo geradas.

Os outros movimentos e progressão do jogo

Os movimentos subsequentes continuam de maneira semelhante. Cada jogador se reveza no jogo, escolhendo um lugar vazio no tabuleiro. Após cada movimento, o contrato verifica qualquer condição de vitória. Se um jogador preencher uma linha, coluna ou diagonal inteira com seu símbolo, o jogo termina e esse jogador é declarado vencedor. A variável winner no estado do contrato seria atualizada adequadamente.

É importante notar que uma vez que um jogador tenha vencido, nenhum outro movimento será válido. Qualquer tentativa de fazer um movimento após o término do jogo seria considerada inválida e a transação correspondente falharia.

O cenário do sorteio

Em alguns jogos, é possível que nenhum jogador alcance a condição de vitória mesmo depois de todo o tabuleiro estar preenchido. Isso resulta em um empate. O contrato também foi concebido para lidar com esta situação.

Se todas as vagas no tabuleiro estiverem preenchidas (nbMoves é igual a 9) e nenhum jogador ganhou (winner permanece 0), o jogo é declarado empatado. A bandeira draw no estado do contrato é definida como True, indicando que o jogo terminou empatado. Mais uma vez, nenhum movimento adicional é válido após este ponto. Qualquer tentativa de fazer um movimento após um empate também falharia.

A segunda parte do cenário de teste do contrato TicTacToe demonstra esse cenário de desenho. Simula uma série de movimentos que resultam em empate e verifica se o contrato o trata corretamente.

免責聲明
* 投資有風險,入市須謹慎。本課程不作為投資理財建議。
* 本課程由入駐Gate Learn的作者創作,觀點僅代表作者本人,絕不代表Gate Learn讚同其觀點或證實其描述。