レッスン3

Розробка гри TicTacToe на Tezos

Світ блокчейн-ігор наповнений можливостями для розробників. Він забезпечує унікальний інноваційний спосіб інтеграції децентралізованих і прозорих механізмів в ігри. Розробляючи ігри на блокчейні, ми можемо включити такі функції, як безпечні та прозорі транзакції, право власності на ігрові активи тощо. У цьому уроці ми збираємось увійти в блокчейн-ігри, розробляючи класичну гру TicTacToe на блокчейні Tezos. Наша мета цього уроку — зрозуміти динаміку логіки гри та управління станом у грі, заснованій на блокчейні.

Давайте почнемо з вивчення нашого контракту на гру 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 демонструє цей сценарій малювання. Він імітує серію ходів, які призводять до нічиєї, і перевіряє, чи контракт обробляє це правильно.

免責事項
* 暗号資産投資には重大なリスクが伴います。注意して進めてください。このコースは投資アドバイスを目的としたものではありません。
※ このコースはGate Learnに参加しているメンバーが作成したものです。作成者が共有した意見はGate Learnを代表するものではありません。
カタログ
レッスン3

Розробка гри TicTacToe на Tezos

Світ блокчейн-ігор наповнений можливостями для розробників. Він забезпечує унікальний інноваційний спосіб інтеграції децентралізованих і прозорих механізмів в ігри. Розробляючи ігри на блокчейні, ми можемо включити такі функції, як безпечні та прозорі транзакції, право власності на ігрові активи тощо. У цьому уроці ми збираємось увійти в блокчейн-ігри, розробляючи класичну гру TicTacToe на блокчейні Tezos. Наша мета цього уроку — зрозуміти динаміку логіки гри та управління станом у грі, заснованій на блокчейні.

Давайте почнемо з вивчення нашого контракту на гру 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 демонструє цей сценарій малювання. Він імітує серію ходів, які призводять до нічиєї, і перевіряє, чи контракт обробляє це правильно.

免責事項
* 暗号資産投資には重大なリスクが伴います。注意して進めてください。このコースは投資アドバイスを目的としたものではありません。
※ このコースはGate Learnに参加しているメンバーが作成したものです。作成者が共有した意見はGate Learnを代表するものではありません。