Давайте почнемо з вивчення нашого контракту на гру TicTacToe:
Python
# TicTacToe - Приклад лише для ілюстрації.
імпортуйте smartpy як sp
@sp.module
def main():
class TicTacToe(sp.Contract):
def __init__(self):
self.data.nbMoves = 0
self.data.winner = 0
self.data.draw = False
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, а не self.data.draw
assert params.i >= 0 і params.i < 3
assert params.j >= 0 і 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, line=self.data.deck[params.i])
)
self.data.winner = self.checkLine(
sp.record(
переможець=self.data.winner,
лінія={
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(
переможець=self.data.winner,
лінія={
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(
переможець=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 and self.data.winner == 0:
self.data.draw = True
@sp.private()
def checkLine(self , переможець, рядок):
переможець_ = переможець
, якщо рядок[0] != 0 і рядок[0] == рядок[1] і рядок[0] == рядок[2]:
переможець_ = рядок[0]
return winner_
# Додати функцію скидання гри
@sp.entrypoint
def confirm_and_reset(self):
assert self.data.winner != 0 або self.data.draw
self.__init__()
# Тести
, якщо «шаблони» не в __name__:
@sp.add_test(name="TicTacToe")
def test():
scenario = sp.test_scenario(main)
scenario.h1("Хрестики-нулики")
# визначити контракт
c1 = main.TicTacToe()
# показати його представлення
scenario.h2("A послідовність взаємодії з переможцем")
сценарій += c1
scenario.h2("Повідомлення виконання")
сценарій.h3("A перший хід у центр")
c1.play(i=1, j=1, хід=1)
scenario.h3("A заборонений хід")
c1.play(i=1, j=1, move=2).run(valid=False)
scenario.h3("A другий хід")
c1.play(i=1, j=2, move=2)
scenario.h3("Інше ходи")
c1.play(i=2, j=1, move=1)
c1.play(i=2, j=2, move=2)
scenario.verify(c1.data.winner == 0 )
c1.play(i=0, j=1, move=1)
scenario.verify(c1.data.winner == 1)
scenario.p("Гравець1 виграв")
c1.play(i=0, j=0, move=2).run(valid=False)
c2 = main.TicTacToe()
scenario.h2("A послідовність взаємодій із нічиєю")
сценарій += c2
scenario.h2("Повідомлення виконання")
сценарій.h3("A перший хід у центр")
c2.play(i=1, j=1, хід=1)
scenario.h3("A заборонений хід")
c2.play(i=1, j=1, move=2).run(valid=False)
scenario.h3("A другий хід")
c2.play(i=1, j=2, move=2)
scenario.h3("Інше ходи")
c2.play(i=2, j=1, переміщення=1)
c2.play(i=2, j=2, переміщення=2)
c2.play(i=0, j=0, переміщення=1)
c2.play(i=0, j=1, переміщення=2)
c2.play(i=0, j=2, переміщення=1)
c2.play(i=2, j=0) , move=2)
c2.play(i=1, j=0, move=1)
# Додати тести для скидання гри
scenario.h2("Тестування скидання гри")
scenario.p("Переможець або нічия підтверджена, тепер скидання гри")
c1.confirm_and_reset()
scenario.verify(c1.data.nbMoves == 0)
scenario.verify(c1.data.winner == 0)
scenario.verify(not c1.data.draw)
c2.confirm_and_reset()
scenario.verify(c2.data.nbMoves == 0)
scenario.verify(c2.data.winner == 0)
scenario.verify(not c2.data.draw)
Договір для нашої гри TicTacToe на Tezos написаний мовою SmartPy. Він складається з двох основних частин: стан контракту та логіка гри.
Стан контракту ініціалізується у функції **init .
Це включає:
nbMoves
: це лічильник кількості ходів, зроблених у грі. Починається з нуля.winner
: відстежує переможця гри. Спочатку він дорівнює нулю, що означає відсутність переможця.draw
: це позначка, яка вказує, чи закінчилася гра нічиєю. Спочатку це False.deck
: це сітка 3x3, яка представляє дошку TicTacToe. Усі точки на дошці спочатку порожні, представлені нулями.nextPlayer
: це вказує, чия черга грати. Гра починається з гравця 1, тому спочатку встановлено 1.Логіка гри міститься у функції play
. Він виконує кілька перевірок, щоб переконатися в дійсності переміщення:
nextPlayer
.nbMoves
, перемикає nextPlayer
і перевіряє, чи хід призвів до перемоги чи нічиєї.Умова виграшу перевіряється по рядку та стовпчику останнього ходу, а також по двох діагоналях.
Якщо всі місця на дошці заповнені і жоден гравець не виграв (тобто nbMoves
дорівнює 9, а winner
усе ще 0), гра оголошується нічиєю.
Функція checkLine
використовується, щоб перевірити, чи виграв будь-який гравець. Він перевіряє, чи всі місця в лінії (яка може бути рядком, стовпцем або діагоналлю) заповнені одним гравцем. Якщо так, цей гравець оголошується переможцем.
Взаємодії з контрактом представлені як транзакції. Коли гравець робить хід, викликаючи функцію play
, він генерує транзакцію. Ця транзакція реєструється, і її можна побачити на правій панелі SmartPy IDE:
Невдалий або недійсний хід також створить транзакцію, але з індикацією помилки:
Перший хід у нашій грі TicTacToe відносно простий, оскільки ігрове поле порожнє. Однак з другим ходом і наступними ходами все стає цікавішим. Ці ходи не лише додають фігури на ігрове поле, але й викликають логіку гри, щоб перевірити потенційних переможців.
Після першого ходу значення nextPlayer
перемикається на гравця 2. Тепер функція play
перевіряє хід гравця 2. Подібні перевірки виконуються, щоб переконатися, що переміщення дійсне, тобто вибрана точка сітки знаходиться в межах і порожня.
Коли кожен гравець робить хід, стан гри змінюється. nbMoves
збільшується, nextPlayer
перемикається, і deck
оновлюється. Крім того, після кожного ходу контракт перевіряє, чи є переможець, чи нічия.
Наприклад, після того, як перший гравець зробить хід у центрі дошки на i=1, j=1
, другий гравець може грати в іншому місці, скажімо, i=1, j=2
. Обидва ці кроки будуть перевірені та виконані успішно, із згенерованими відповідними транзакціями.
Подальші рухи продовжуються таким же чином. Кожен гравець грає по черзі, вибираючи вільне місце на дошці. Після кожного ходу контракт перевіряє наявність виграшних умов. Якщо гравець заповнює весь рядок, стовпець або діагональ своїм символом, гра закінчується, і цей гравець оголошується переможцем. Змінна winner
в стані контракту буде відповідним чином оновлена.
Важливо зауважити, що після того, як гравець виграє, подальші ходи не є дійсними. Будь-яка спроба зробити хід після завершення гри вважатиметься недійсною, а відповідна транзакція буде невдалою.
У деяких іграх можливо, що жоден гравець не досягне умови перемоги, навіть якщо все ігрове поле заповнено. Це призводить до нічиєї. Контракт також був розроблений для вирішення цієї ситуації.
Якщо всі місця на дошці заповнені (nbMoves
дорівнює 9) і жоден гравець не виграв (winner
залишається 0), партія оголошується нічиєю. Прапор draw
в стані контракту має значення True, що вказує на те, що гра закінчилася внічию. Знову ж таки, після цього моменту жодні подальші ходи недійсні. Будь-які спроби зробити хід після нічиєї також будуть невдалими.
Друга частина тестового сценарію контракту TicTacToe демонструє цей сценарій малювання. Він імітує серію ходів, які призводять до нічиєї, і перевіряє, чи контракт обробляє це правильно.
Давайте почнемо з вивчення нашого контракту на гру TicTacToe:
Python
# TicTacToe - Приклад лише для ілюстрації.
імпортуйте smartpy як sp
@sp.module
def main():
class TicTacToe(sp.Contract):
def __init__(self):
self.data.nbMoves = 0
self.data.winner = 0
self.data.draw = False
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, а не self.data.draw
assert params.i >= 0 і params.i < 3
assert params.j >= 0 і 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, line=self.data.deck[params.i])
)
self.data.winner = self.checkLine(
sp.record(
переможець=self.data.winner,
лінія={
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(
переможець=self.data.winner,
лінія={
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(
переможець=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 and self.data.winner == 0:
self.data.draw = True
@sp.private()
def checkLine(self , переможець, рядок):
переможець_ = переможець
, якщо рядок[0] != 0 і рядок[0] == рядок[1] і рядок[0] == рядок[2]:
переможець_ = рядок[0]
return winner_
# Додати функцію скидання гри
@sp.entrypoint
def confirm_and_reset(self):
assert self.data.winner != 0 або self.data.draw
self.__init__()
# Тести
, якщо «шаблони» не в __name__:
@sp.add_test(name="TicTacToe")
def test():
scenario = sp.test_scenario(main)
scenario.h1("Хрестики-нулики")
# визначити контракт
c1 = main.TicTacToe()
# показати його представлення
scenario.h2("A послідовність взаємодії з переможцем")
сценарій += c1
scenario.h2("Повідомлення виконання")
сценарій.h3("A перший хід у центр")
c1.play(i=1, j=1, хід=1)
scenario.h3("A заборонений хід")
c1.play(i=1, j=1, move=2).run(valid=False)
scenario.h3("A другий хід")
c1.play(i=1, j=2, move=2)
scenario.h3("Інше ходи")
c1.play(i=2, j=1, move=1)
c1.play(i=2, j=2, move=2)
scenario.verify(c1.data.winner == 0 )
c1.play(i=0, j=1, move=1)
scenario.verify(c1.data.winner == 1)
scenario.p("Гравець1 виграв")
c1.play(i=0, j=0, move=2).run(valid=False)
c2 = main.TicTacToe()
scenario.h2("A послідовність взаємодій із нічиєю")
сценарій += c2
scenario.h2("Повідомлення виконання")
сценарій.h3("A перший хід у центр")
c2.play(i=1, j=1, хід=1)
scenario.h3("A заборонений хід")
c2.play(i=1, j=1, move=2).run(valid=False)
scenario.h3("A другий хід")
c2.play(i=1, j=2, move=2)
scenario.h3("Інше ходи")
c2.play(i=2, j=1, переміщення=1)
c2.play(i=2, j=2, переміщення=2)
c2.play(i=0, j=0, переміщення=1)
c2.play(i=0, j=1, переміщення=2)
c2.play(i=0, j=2, переміщення=1)
c2.play(i=2, j=0) , move=2)
c2.play(i=1, j=0, move=1)
# Додати тести для скидання гри
scenario.h2("Тестування скидання гри")
scenario.p("Переможець або нічия підтверджена, тепер скидання гри")
c1.confirm_and_reset()
scenario.verify(c1.data.nbMoves == 0)
scenario.verify(c1.data.winner == 0)
scenario.verify(not c1.data.draw)
c2.confirm_and_reset()
scenario.verify(c2.data.nbMoves == 0)
scenario.verify(c2.data.winner == 0)
scenario.verify(not c2.data.draw)
Договір для нашої гри TicTacToe на Tezos написаний мовою SmartPy. Він складається з двох основних частин: стан контракту та логіка гри.
Стан контракту ініціалізується у функції **init .
Це включає:
nbMoves
: це лічильник кількості ходів, зроблених у грі. Починається з нуля.winner
: відстежує переможця гри. Спочатку він дорівнює нулю, що означає відсутність переможця.draw
: це позначка, яка вказує, чи закінчилася гра нічиєю. Спочатку це False.deck
: це сітка 3x3, яка представляє дошку TicTacToe. Усі точки на дошці спочатку порожні, представлені нулями.nextPlayer
: це вказує, чия черга грати. Гра починається з гравця 1, тому спочатку встановлено 1.Логіка гри міститься у функції play
. Він виконує кілька перевірок, щоб переконатися в дійсності переміщення:
nextPlayer
.nbMoves
, перемикає nextPlayer
і перевіряє, чи хід призвів до перемоги чи нічиєї.Умова виграшу перевіряється по рядку та стовпчику останнього ходу, а також по двох діагоналях.
Якщо всі місця на дошці заповнені і жоден гравець не виграв (тобто nbMoves
дорівнює 9, а winner
усе ще 0), гра оголошується нічиєю.
Функція checkLine
використовується, щоб перевірити, чи виграв будь-який гравець. Він перевіряє, чи всі місця в лінії (яка може бути рядком, стовпцем або діагоналлю) заповнені одним гравцем. Якщо так, цей гравець оголошується переможцем.
Взаємодії з контрактом представлені як транзакції. Коли гравець робить хід, викликаючи функцію play
, він генерує транзакцію. Ця транзакція реєструється, і її можна побачити на правій панелі SmartPy IDE:
Невдалий або недійсний хід також створить транзакцію, але з індикацією помилки:
Перший хід у нашій грі TicTacToe відносно простий, оскільки ігрове поле порожнє. Однак з другим ходом і наступними ходами все стає цікавішим. Ці ходи не лише додають фігури на ігрове поле, але й викликають логіку гри, щоб перевірити потенційних переможців.
Після першого ходу значення nextPlayer
перемикається на гравця 2. Тепер функція play
перевіряє хід гравця 2. Подібні перевірки виконуються, щоб переконатися, що переміщення дійсне, тобто вибрана точка сітки знаходиться в межах і порожня.
Коли кожен гравець робить хід, стан гри змінюється. nbMoves
збільшується, nextPlayer
перемикається, і deck
оновлюється. Крім того, після кожного ходу контракт перевіряє, чи є переможець, чи нічия.
Наприклад, після того, як перший гравець зробить хід у центрі дошки на i=1, j=1
, другий гравець може грати в іншому місці, скажімо, i=1, j=2
. Обидва ці кроки будуть перевірені та виконані успішно, із згенерованими відповідними транзакціями.
Подальші рухи продовжуються таким же чином. Кожен гравець грає по черзі, вибираючи вільне місце на дошці. Після кожного ходу контракт перевіряє наявність виграшних умов. Якщо гравець заповнює весь рядок, стовпець або діагональ своїм символом, гра закінчується, і цей гравець оголошується переможцем. Змінна winner
в стані контракту буде відповідним чином оновлена.
Важливо зауважити, що після того, як гравець виграє, подальші ходи не є дійсними. Будь-яка спроба зробити хід після завершення гри вважатиметься недійсною, а відповідна транзакція буде невдалою.
У деяких іграх можливо, що жоден гравець не досягне умови перемоги, навіть якщо все ігрове поле заповнено. Це призводить до нічиєї. Контракт також був розроблений для вирішення цієї ситуації.
Якщо всі місця на дошці заповнені (nbMoves
дорівнює 9) і жоден гравець не виграв (winner
залишається 0), партія оголошується нічиєю. Прапор draw
в стані контракту має значення True, що вказує на те, що гра закінчилася внічию. Знову ж таки, після цього моменту жодні подальші ходи недійсні. Будь-які спроби зробити хід після нічиєї також будуть невдалими.
Друга частина тестового сценарію контракту TicTacToe демонструє цей сценарій малювання. Він імітує серію ходів, які призводять до нічиєї, і перевіряє, чи контракт обробляє це правильно.