Vamos começar explorando nosso contrato para o jogo TicTacToe:
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.
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.A lógica do jogo está encapsulada na função play
. Ele executa diversas verificações para garantir uma movimentação válida:
nextPlayer
.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.
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.
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 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 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.
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.
Vamos começar explorando nosso contrato para o jogo TicTacToe:
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.
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.A lógica do jogo está encapsulada na função play
. Ele executa diversas verificações para garantir uma movimentação válida:
nextPlayer
.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.
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.
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 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 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.
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.