第3課

Desenvolver um jogo TicTactoe no Tezos

O mundo dos jogos blockchain está cheio de oportunidades para os programadores. Fornece uma maneira única e inovadora de integrar mecanismos descentralizados e transparentes nos jogos. Ao desenvolver jogos numa cadeia de blocos, podemos incorporar funcionalidades como transações seguras e transparentes, propriedade de ativos no jogo e muito mais. Nesta lição, vamos entrar no jogo de blockchain desenvolvendo um jogo clássico de TicTacToe na cadeia de blocos Tezos. O nosso objetivo com esta lição é compreender a dinâmica da lógica do jogo e da gestão do estado num jogo baseado em blockchain.

Vamos começar por explorar o nosso contrato para o jogo TicTactoe:

Estrutura do Contrato

Python
# TicTacToe - Exemplo apenas para fins ilustrativos.

importar de forma inteligente como sp


@sp .módulo
def principal ():
 classe 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 .ponto de entrada
 def play (self, parâmetros):
 assert self.data.winner == 0 e não self.data.draw
 afirmar params.i >= 0 e param.i <3
 afirmar params.j >= 0 e params.j <3
 assert params.move == Self.Data.NextPlayer
 afirmar 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 (vencedor=self.data.winner, line=self.data.deck [params.i])
            )
 self.data.winner = Self.Checkline (
                sp.registro (
 winner=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.registro (
 winner=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.registro (
 winner=self.data.winner,
                    linha ={
                        0: self.data.deck[0][2],
                        1: self.data.deck[1][1],
                        2: self.data.deck[2][0],
                    },
 )
 )
 se self.data.nbmove == 9 e self.data.winner == 0:
 self.data.draw = Verdadeiro

 @sp .privado ()
 def CheckLine (auto, vencedor, linha):
 vencedor_ = vencedor
 se linha [0]! = 0 e linha [0] == linha [1] e linha [0] == linha [2]:
 vencedor_ = linha [0]
 retorno ganhador_

 # Adicionar uma função de redefinição de jogo
 @sp .ponto de entrada
 def confirmar_e_reset (self):
 afirme self.data.winner! = 0 ou self.data.draw
 eu mesmo.__init__()

# Testes
se " os modelos " não estiverem em __name__:

 @sp .add_test (nome = TicTacToe) " "
 teste def ():
 cenário = sp.test_scenario (principal)
        cenário.h1 (Tic-Tac-Toe) " "
        # definir um contrato
 c1 = main.TicTactoe ()

 # mostrar a sua representação
 cenário.h2 (A " sequência de interações com um vencedor")
 cenário += c1
 scenario.h2 (Mensagem) " execução")
 cenário.h3 (A " primeiro passo no centro")
 c1.play (i=1, j=1, movimento=1)
 cenário.h3 (A " movimento proibido")
 c1.play (i=1, j=1, move=2) .run (válido = falso)
        cenário.h3 (A " segunda jogada")
 c1.play (i=1, j=2, movimento=2)
 scenario.h3 (Outro " movimentos")
 c1.play (i=2, j=1, movimento=1)
 c1.play (i=2, j=2, movimento=2)
 cenário.verify (c1.data.winner == 0)
 c1.play (i=0, j=1, movimento=1)
 cenário.verify (c1.data.winner == 1)
 scenario.p (Jogador1 " ganhou")
 c1.play (i=0, j=0, move=2) .run (válido = falso)

        c2 = main.TicTactoe ()
 cenário.h2 (A " sequência de interações com um empate")
 cenário += c2
 scenario.h2 (Mensagem) " execução")
 cenário.h3 (A " primeiro passo no centro")
 c2.play (i=1, j=1, movimento=1)
 cenário.h3 (A " movimento proibido")
 c2.play (i=1, j=1, move=2) .run (válido = falso)
        cenário.h3 (A " segunda jogada")
 c2.play (i=1, j=2, movimento=2)
 scenario.h3 (Outro " movimentos")
 c2.play (i=2, j=1, movimento=1)
 c2.play (i=2, j=2, movimento=2)
 c2.play (i=0, j=0, movimento=1)
 c2.play (i=0, j=1, movimento=2)
 c2.play (i=0, j=2, movimento=1)
 c2.play (i=2, j=0, movimento=2)
 c2.play (i=1, j=0, movimento=1)

 # Adicionar testes para o reset do jogo
 scenario.h2 (Testes " redefinição do jogo")
 scenario.p (Vencedor " ou sorteio confirmado, agora reiniciando o jogo")
 c1.confirm_e_reset ()
 scenário.verify (C1.data.nbMoves == 0)
 cenário.verify (c1.data.winner == 0)
 scenario.verify (não c1.data.draw)

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

O contrato para o 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 para o número de movimentos feitos no jogo. Começa no zero.
  • vencedor: Isto mantém o registo do vencedor do jogo. Inicialmente, é zero, indicando nenhum vencedor.
  • empate: Esta é uma bandeira que indica se o jogo terminou num empate. Inicialmente, é falso.
  • deck: Esta é uma grelha 3x3 que representa a placa TicTactoe. Todos os pontos no quadro estão inicialmente vazios, representados por zeros.
  • NextPlayer: Isso indica de quem é a vez de jogar. O jogo começa com o jogador 1, por isso é inicialmente definido como 1.

Lógica do Jogo

A lógica do jogo está encapsulada na função de jogo. Realiza várias verificações para garantir uma jogada válida:

  • Verifica se nenhum jogador ganhou ainda e que o jogo não é um empate.
  • Verifica se os índices para o ponto de grelha escolhido pelo jogador estão dentro dos limites da grelha.
  • Garante que o jogador que faz a jogada corresponde ao NextPlayer.
  • Garante que o local escolhido na grelha está vazio.
    Uma vez feita uma jogada, a lógica do jogo incrementa os NBMoves, muda o NextPlayer e verifica se a jogada resultou numa vitória ou num empate.

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

Se todas as vagas no tabuleiro estiverem preenchidas e nenhum jogador tiver ganho (ou seja, NBMoves é igual a 9 e o vencedor ainda é 0), o jogo é declarado empate.

Verificando se há uma vitória

A função CheckLine é utilizada para verificar se algum jogador ganhou. Verifica se todos os pontos numa linha (que pode ser uma linha, uma coluna ou uma diagonal) são preenchidos pelo mesmo jogador. Se sim, esse jogador é declarado o vencedor.

Interagir com o Contrato

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

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

O Segundo Movimento e Mais Além

A primeira jogada no nosso jogo TicTactoe é relativamente simples, uma vez que o tabuleiro de jogo está vazio. No entanto, as coisas ficam mais interessantes com o segundo movimento e movimentos subsequentes. Estes movimentos não só adicionam peças ao tabuleiro de jogo mas também invocam a lógica do jogo para verificar possíveis vencedores.

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

À medida que cada jogador faz um movimento, o estado do jogo evolui. O NBMoves aumenta, o NextPlayer muda e o baralho é atualizado. Além disso, após cada jogada, o contrato verifica se há um vencedor ou se é um empate.

Por exemplo, depois de o primeiro jogador fazer uma jogada no centro do tabuleiro em i=1, j=1, o segundo jogador pode jogar num ponto diferente, digamos i=1, j=2. Ambos os movimentos seriam validados e executados com sucesso, com as transações correspondentes a serem geradas.

Os Outros Moves e Progressão do Jogo

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

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

O cenário do sorteio

Em alguns jogos, é possível que nenhum jogador atinja uma condição de vitória mesmo depois de todo o tabuleiro de jogo estar cheio. Isso resulta num 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 (o vencedor permanece 0), o jogo é declarado empate. A bandeira de sorteio no estado do contrato está definida como Verdadeiro, indicando que o jogo terminou num empate. Mais uma vez, nenhum outro movimento é válido após este ponto. Qualquer tentativa de fazer um movimento depois de um empate também falharia.

A segunda parte do cenário de teste do contrato TicTacToe demonstra este cenário de desenho. Simula uma série de movimentos que resultam num empate e verifica se o contrato lida com isso corretamente.

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

Desenvolver um jogo TicTactoe no Tezos

O mundo dos jogos blockchain está cheio de oportunidades para os programadores. Fornece uma maneira única e inovadora de integrar mecanismos descentralizados e transparentes nos jogos. Ao desenvolver jogos numa cadeia de blocos, podemos incorporar funcionalidades como transações seguras e transparentes, propriedade de ativos no jogo e muito mais. Nesta lição, vamos entrar no jogo de blockchain desenvolvendo um jogo clássico de TicTacToe na cadeia de blocos Tezos. O nosso objetivo com esta lição é compreender a dinâmica da lógica do jogo e da gestão do estado num jogo baseado em blockchain.

Vamos começar por explorar o nosso contrato para o jogo TicTactoe:

Estrutura do Contrato

Python
# TicTacToe - Exemplo apenas para fins ilustrativos.

importar de forma inteligente como sp


@sp .módulo
def principal ():
 classe 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 .ponto de entrada
 def play (self, parâmetros):
 assert self.data.winner == 0 e não self.data.draw
 afirmar params.i >= 0 e param.i <3
 afirmar params.j >= 0 e params.j <3
 assert params.move == Self.Data.NextPlayer
 afirmar 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 (vencedor=self.data.winner, line=self.data.deck [params.i])
            )
 self.data.winner = Self.Checkline (
                sp.registro (
 winner=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.registro (
 winner=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.registro (
 winner=self.data.winner,
                    linha ={
                        0: self.data.deck[0][2],
                        1: self.data.deck[1][1],
                        2: self.data.deck[2][0],
                    },
 )
 )
 se self.data.nbmove == 9 e self.data.winner == 0:
 self.data.draw = Verdadeiro

 @sp .privado ()
 def CheckLine (auto, vencedor, linha):
 vencedor_ = vencedor
 se linha [0]! = 0 e linha [0] == linha [1] e linha [0] == linha [2]:
 vencedor_ = linha [0]
 retorno ganhador_

 # Adicionar uma função de redefinição de jogo
 @sp .ponto de entrada
 def confirmar_e_reset (self):
 afirme self.data.winner! = 0 ou self.data.draw
 eu mesmo.__init__()

# Testes
se " os modelos " não estiverem em __name__:

 @sp .add_test (nome = TicTacToe) " "
 teste def ():
 cenário = sp.test_scenario (principal)
        cenário.h1 (Tic-Tac-Toe) " "
        # definir um contrato
 c1 = main.TicTactoe ()

 # mostrar a sua representação
 cenário.h2 (A " sequência de interações com um vencedor")
 cenário += c1
 scenario.h2 (Mensagem) " execução")
 cenário.h3 (A " primeiro passo no centro")
 c1.play (i=1, j=1, movimento=1)
 cenário.h3 (A " movimento proibido")
 c1.play (i=1, j=1, move=2) .run (válido = falso)
        cenário.h3 (A " segunda jogada")
 c1.play (i=1, j=2, movimento=2)
 scenario.h3 (Outro " movimentos")
 c1.play (i=2, j=1, movimento=1)
 c1.play (i=2, j=2, movimento=2)
 cenário.verify (c1.data.winner == 0)
 c1.play (i=0, j=1, movimento=1)
 cenário.verify (c1.data.winner == 1)
 scenario.p (Jogador1 " ganhou")
 c1.play (i=0, j=0, move=2) .run (válido = falso)

        c2 = main.TicTactoe ()
 cenário.h2 (A " sequência de interações com um empate")
 cenário += c2
 scenario.h2 (Mensagem) " execução")
 cenário.h3 (A " primeiro passo no centro")
 c2.play (i=1, j=1, movimento=1)
 cenário.h3 (A " movimento proibido")
 c2.play (i=1, j=1, move=2) .run (válido = falso)
        cenário.h3 (A " segunda jogada")
 c2.play (i=1, j=2, movimento=2)
 scenario.h3 (Outro " movimentos")
 c2.play (i=2, j=1, movimento=1)
 c2.play (i=2, j=2, movimento=2)
 c2.play (i=0, j=0, movimento=1)
 c2.play (i=0, j=1, movimento=2)
 c2.play (i=0, j=2, movimento=1)
 c2.play (i=2, j=0, movimento=2)
 c2.play (i=1, j=0, movimento=1)

 # Adicionar testes para o reset do jogo
 scenario.h2 (Testes " redefinição do jogo")
 scenario.p (Vencedor " ou sorteio confirmado, agora reiniciando o jogo")
 c1.confirm_e_reset ()
 scenário.verify (C1.data.nbMoves == 0)
 cenário.verify (c1.data.winner == 0)
 scenario.verify (não c1.data.draw)

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

O contrato para o 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 para o número de movimentos feitos no jogo. Começa no zero.
  • vencedor: Isto mantém o registo do vencedor do jogo. Inicialmente, é zero, indicando nenhum vencedor.
  • empate: Esta é uma bandeira que indica se o jogo terminou num empate. Inicialmente, é falso.
  • deck: Esta é uma grelha 3x3 que representa a placa TicTactoe. Todos os pontos no quadro estão inicialmente vazios, representados por zeros.
  • NextPlayer: Isso indica de quem é a vez de jogar. O jogo começa com o jogador 1, por isso é inicialmente definido como 1.

Lógica do Jogo

A lógica do jogo está encapsulada na função de jogo. Realiza várias verificações para garantir uma jogada válida:

  • Verifica se nenhum jogador ganhou ainda e que o jogo não é um empate.
  • Verifica se os índices para o ponto de grelha escolhido pelo jogador estão dentro dos limites da grelha.
  • Garante que o jogador que faz a jogada corresponde ao NextPlayer.
  • Garante que o local escolhido na grelha está vazio.
    Uma vez feita uma jogada, a lógica do jogo incrementa os NBMoves, muda o NextPlayer e verifica se a jogada resultou numa vitória ou num empate.

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

Se todas as vagas no tabuleiro estiverem preenchidas e nenhum jogador tiver ganho (ou seja, NBMoves é igual a 9 e o vencedor ainda é 0), o jogo é declarado empate.

Verificando se há uma vitória

A função CheckLine é utilizada para verificar se algum jogador ganhou. Verifica se todos os pontos numa linha (que pode ser uma linha, uma coluna ou uma diagonal) são preenchidos pelo mesmo jogador. Se sim, esse jogador é declarado o vencedor.

Interagir com o Contrato

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

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

O Segundo Movimento e Mais Além

A primeira jogada no nosso jogo TicTactoe é relativamente simples, uma vez que o tabuleiro de jogo está vazio. No entanto, as coisas ficam mais interessantes com o segundo movimento e movimentos subsequentes. Estes movimentos não só adicionam peças ao tabuleiro de jogo mas também invocam a lógica do jogo para verificar possíveis vencedores.

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

À medida que cada jogador faz um movimento, o estado do jogo evolui. O NBMoves aumenta, o NextPlayer muda e o baralho é atualizado. Além disso, após cada jogada, o contrato verifica se há um vencedor ou se é um empate.

Por exemplo, depois de o primeiro jogador fazer uma jogada no centro do tabuleiro em i=1, j=1, o segundo jogador pode jogar num ponto diferente, digamos i=1, j=2. Ambos os movimentos seriam validados e executados com sucesso, com as transações correspondentes a serem geradas.

Os Outros Moves e Progressão do Jogo

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

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

O cenário do sorteio

Em alguns jogos, é possível que nenhum jogador atinja uma condição de vitória mesmo depois de todo o tabuleiro de jogo estar cheio. Isso resulta num 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 (o vencedor permanece 0), o jogo é declarado empate. A bandeira de sorteio no estado do contrato está definida como Verdadeiro, indicando que o jogo terminou num empate. Mais uma vez, nenhum outro movimento é válido após este ponto. Qualquer tentativa de fazer um movimento depois de um empate também falharia.

A segunda parte do cenário de teste do contrato TicTacToe demonstra este cenário de desenho. Simula uma série de movimentos que resultam num empate e verifica se o contrato lida com isso corretamente.

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