Bài học 3

การพัฒนาเกม TicTacToe บน Tezos

โลกแห่งเกมบล็อกเชนเต็มไปด้วยโอกาสสำหรับนักพัฒนา เป็นแนวทางที่แปลกใหม่และเป็นนวัตกรรมในการบูรณาการกลไกการกระจายอำนาจและโปร่งใสเข้าไปในเกม ด้วยการพัฒนาเกมบนบล็อกเชน เราสามารถรวมคุณสมบัติต่างๆ เช่น ธุรกรรมที่ปลอดภัยและโปร่งใส การเป็นเจ้าของทรัพย์สินในเกม และอื่นๆ อีกมากมาย ในบทเรียนนี้ เราจะก้าวเข้าสู่การเล่นเกมบล็อกเชนโดยการพัฒนาเกมคลาสสิกของ TicTacToe บนบล็อกเชน Tezos เป้าหมายของเราในบทเรียนนี้คือการทำความเข้าใจพลวัตของตรรกะของเกมและการจัดการสถานะในเกมที่ใช้บล็อกเชน

เริ่มต้นด้วยการสำรวจสัญญาของเราสำหรับเกม TicTacToe:

โครงสร้างสัญญา

Python 
 # TicTacToe - ตัวอย่างเพื่อจุดประสงค์ในการอธิบายเท่านั้น

นำเข้า smartpy เป็น sp 


 @sp.module 
 def main(): 
 คลาส TicTacToe(sp.Contract): 
 def __init__(ตนเอง): 
 self.data.nbMoves = 0 
 self.data.winner = 0 
 self.data.draw = เท็จ 
 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): 
 ยืนยัน self.data.winner == 0 และไม่ใช่ self.data.draw 
 ยืนยัน params.i >= 0 และ params.i < 3 
 ยืนยัน params.j >= 0 และ params.j < 3 
 ยืนยัน params.move == self.data.nextPlayer 
 ยืนยัน 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],
                    }, 
 ) 
 ) 
 ถ้า self.data.nbMoves == 9 และ 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 ยืนยัน_และ_รีเซ็ต(ตนเอง): 
 ยืนยัน self.data.winner != 0 หรือ self.data.draw 
 ตนเอง __init__()

# ทดสอบ 
 หาก "เทมเพลต" ไม่ได้อยู่ใน __name__: 

 @sp.add_test(name="TicTacToe") 
 def test(): 
 สถานการณ์ = sp.test_scenario(main)
        สถานการณ์.h1("Tic-Tac-Toe")
        # กำหนดสัญญา 
 c1 = main.TicTacToe() 

 # แสดงการเป็นตัวแทน 
 สถานการณ์ h2("A ลำดับการโต้ตอบกับผู้ชนะ") 
 สถานการณ์ += c1 
 สถานการณ์ h2("Message การดำเนินการ") 
 สถานการณ์ h3 ("A ย้ายครั้งแรกตรงกลาง") 
 c1.play(i=1, j=1, move=1) 
 สถานการณ์ h3("A การย้ายที่ต้องห้าม") 
 c1.play(i=1, j=1, move=2).run(valid=False)
        สถานการณ์.h3("A การย้ายครั้งที่สอง") 
 c1.play(i=1, j=2, move=2) 
 สถานการณ์ h3("Other ย้าย") 
 c1.play(i=2, j=1, move=1) 
 c1.play(i=2, j=2, move=2) 
 สถานการณ์ ตรวจสอบ (c1.data.winner == 0 ) 
 c1.play(i=0, j=1, move=1) 
 สถานการณ์ ตรวจสอบ (c1.data.winner == 1) 
 สถานการณ์ p ("ผู้เล่น 1) ชนะแล้ว") 
 c1.play(i=0, j=0, move=2).run(valid=False)

        c2 = main.TicTacToe() 
 สถานการณ์ h2("A ลำดับของการโต้ตอบด้วยการเสมอกัน") 
 สถานการณ์ += c2 
 สถานการณ์ h2("Message การดำเนินการ") 
 สถานการณ์ h3 ("A ย้ายครั้งแรกตรงกลาง") 
 c2.play(i=1, j=1, move=1) 
 สถานการณ์ h3("A การย้ายที่ต้องห้าม") 
 c2.play(i=1, j=1, move=2).run(valid=False)
        สถานการณ์.h3("A การย้ายครั้งที่สอง") 
 c2.play(i=1, j=2, move=2) 
 สถานการณ์ h3("Other ย้าย") 
 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) 

 # เพิ่มการทดสอบสำหรับการรีเซ็ตเกม 
 สถานการณ์ h2("การทดสอบ รีเซ็ตเกม") 
 สถานการณ์ p ("ผู้ชนะ หรือยืนยันการจับฉลาก ตอนนี้กำลังรีเซ็ตเกม") 
 c1.confirm_and_reset() 
 สถานการณ์ ตรวจสอบ(c1.data.nbMoves == 0) 
 สถานการณ์ ตรวจสอบ(c1.data.winner == 0) 
 สถานการณ์ ตรวจสอบ(ไม่ใช่ c1.data.draw)

        c2.confirm_and_reset() 
 สถานการณ์ ตรวจสอบ (c2.data.nbMoves == 0) 
 สถานการณ์ ตรวจสอบ (c2.data.winner == 0) 
 สถานการณ์ ตรวจสอบ (ไม่ใช่ c2.data.draw)

สัญญาสำหรับเกม TicTacToe ของเราบน Tezos เขียนขึ้นในภาษา SmartPy ประกอบด้วยสองส่วนหลัก: สถานะของสัญญา และตรรกะของเกม

สถานะของสัญญา

สถานะของสัญญาเริ่มต้นได้ในฟังก์ชัน **init ประกอบด้วย:

  • nbMoves: นี่คือตัวนับจำนวนการเคลื่อนไหวในเกม มันเริ่มต้นที่ศูนย์
  • winner: สิ่งนี้จะติดตามผู้ชนะของเกม เริ่มแรกจะเป็นศูนย์ แสดงว่าไม่มีผู้ชนะ
  • draw: นี่คือธงที่ระบุว่าเกมจบลงด้วยการเสมอกันหรือไม่ ตอนแรกมันเป็นเท็จ
  • 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 แสดงให้เห็นถึงสถานการณ์การวาดนี้ โดยจะจำลองชุดของการเคลื่อนไหวที่ส่งผลให้เกิดการเสมอกัน และตรวจสอบว่าสัญญาจัดการได้อย่างถูกต้อง

Tuyên bố từ chối trách nhiệm
* Đầu tư tiền điện tử liên quan đến rủi ro đáng kể. Hãy tiến hành một cách thận trọng. Khóa học không nhằm mục đích tư vấn đầu tư.
* Khóa học được tạo bởi tác giả đã tham gia Gate Learn. Mọi ý kiến chia sẻ của tác giả không đại diện cho Gate Learn.
Danh mục
Bài học 3

การพัฒนาเกม TicTacToe บน Tezos

โลกแห่งเกมบล็อกเชนเต็มไปด้วยโอกาสสำหรับนักพัฒนา เป็นแนวทางที่แปลกใหม่และเป็นนวัตกรรมในการบูรณาการกลไกการกระจายอำนาจและโปร่งใสเข้าไปในเกม ด้วยการพัฒนาเกมบนบล็อกเชน เราสามารถรวมคุณสมบัติต่างๆ เช่น ธุรกรรมที่ปลอดภัยและโปร่งใส การเป็นเจ้าของทรัพย์สินในเกม และอื่นๆ อีกมากมาย ในบทเรียนนี้ เราจะก้าวเข้าสู่การเล่นเกมบล็อกเชนโดยการพัฒนาเกมคลาสสิกของ TicTacToe บนบล็อกเชน Tezos เป้าหมายของเราในบทเรียนนี้คือการทำความเข้าใจพลวัตของตรรกะของเกมและการจัดการสถานะในเกมที่ใช้บล็อกเชน

เริ่มต้นด้วยการสำรวจสัญญาของเราสำหรับเกม TicTacToe:

โครงสร้างสัญญา

Python 
 # TicTacToe - ตัวอย่างเพื่อจุดประสงค์ในการอธิบายเท่านั้น

นำเข้า smartpy เป็น sp 


 @sp.module 
 def main(): 
 คลาส TicTacToe(sp.Contract): 
 def __init__(ตนเอง): 
 self.data.nbMoves = 0 
 self.data.winner = 0 
 self.data.draw = เท็จ 
 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): 
 ยืนยัน self.data.winner == 0 และไม่ใช่ self.data.draw 
 ยืนยัน params.i >= 0 และ params.i < 3 
 ยืนยัน params.j >= 0 และ params.j < 3 
 ยืนยัน params.move == self.data.nextPlayer 
 ยืนยัน 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],
                    }, 
 ) 
 ) 
 ถ้า self.data.nbMoves == 9 และ 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 ยืนยัน_และ_รีเซ็ต(ตนเอง): 
 ยืนยัน self.data.winner != 0 หรือ self.data.draw 
 ตนเอง __init__()

# ทดสอบ 
 หาก "เทมเพลต" ไม่ได้อยู่ใน __name__: 

 @sp.add_test(name="TicTacToe") 
 def test(): 
 สถานการณ์ = sp.test_scenario(main)
        สถานการณ์.h1("Tic-Tac-Toe")
        # กำหนดสัญญา 
 c1 = main.TicTacToe() 

 # แสดงการเป็นตัวแทน 
 สถานการณ์ h2("A ลำดับการโต้ตอบกับผู้ชนะ") 
 สถานการณ์ += c1 
 สถานการณ์ h2("Message การดำเนินการ") 
 สถานการณ์ h3 ("A ย้ายครั้งแรกตรงกลาง") 
 c1.play(i=1, j=1, move=1) 
 สถานการณ์ h3("A การย้ายที่ต้องห้าม") 
 c1.play(i=1, j=1, move=2).run(valid=False)
        สถานการณ์.h3("A การย้ายครั้งที่สอง") 
 c1.play(i=1, j=2, move=2) 
 สถานการณ์ h3("Other ย้าย") 
 c1.play(i=2, j=1, move=1) 
 c1.play(i=2, j=2, move=2) 
 สถานการณ์ ตรวจสอบ (c1.data.winner == 0 ) 
 c1.play(i=0, j=1, move=1) 
 สถานการณ์ ตรวจสอบ (c1.data.winner == 1) 
 สถานการณ์ p ("ผู้เล่น 1) ชนะแล้ว") 
 c1.play(i=0, j=0, move=2).run(valid=False)

        c2 = main.TicTacToe() 
 สถานการณ์ h2("A ลำดับของการโต้ตอบด้วยการเสมอกัน") 
 สถานการณ์ += c2 
 สถานการณ์ h2("Message การดำเนินการ") 
 สถานการณ์ h3 ("A ย้ายครั้งแรกตรงกลาง") 
 c2.play(i=1, j=1, move=1) 
 สถานการณ์ h3("A การย้ายที่ต้องห้าม") 
 c2.play(i=1, j=1, move=2).run(valid=False)
        สถานการณ์.h3("A การย้ายครั้งที่สอง") 
 c2.play(i=1, j=2, move=2) 
 สถานการณ์ h3("Other ย้าย") 
 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) 

 # เพิ่มการทดสอบสำหรับการรีเซ็ตเกม 
 สถานการณ์ h2("การทดสอบ รีเซ็ตเกม") 
 สถานการณ์ p ("ผู้ชนะ หรือยืนยันการจับฉลาก ตอนนี้กำลังรีเซ็ตเกม") 
 c1.confirm_and_reset() 
 สถานการณ์ ตรวจสอบ(c1.data.nbMoves == 0) 
 สถานการณ์ ตรวจสอบ(c1.data.winner == 0) 
 สถานการณ์ ตรวจสอบ(ไม่ใช่ c1.data.draw)

        c2.confirm_and_reset() 
 สถานการณ์ ตรวจสอบ (c2.data.nbMoves == 0) 
 สถานการณ์ ตรวจสอบ (c2.data.winner == 0) 
 สถานการณ์ ตรวจสอบ (ไม่ใช่ c2.data.draw)

สัญญาสำหรับเกม TicTacToe ของเราบน Tezos เขียนขึ้นในภาษา SmartPy ประกอบด้วยสองส่วนหลัก: สถานะของสัญญา และตรรกะของเกม

สถานะของสัญญา

สถานะของสัญญาเริ่มต้นได้ในฟังก์ชัน **init ประกอบด้วย:

  • nbMoves: นี่คือตัวนับจำนวนการเคลื่อนไหวในเกม มันเริ่มต้นที่ศูนย์
  • winner: สิ่งนี้จะติดตามผู้ชนะของเกม เริ่มแรกจะเป็นศูนย์ แสดงว่าไม่มีผู้ชนะ
  • draw: นี่คือธงที่ระบุว่าเกมจบลงด้วยการเสมอกันหรือไม่ ตอนแรกมันเป็นเท็จ
  • 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 แสดงให้เห็นถึงสถานการณ์การวาดนี้ โดยจะจำลองชุดของการเคลื่อนไหวที่ส่งผลให้เกิดการเสมอกัน และตรวจสอบว่าสัญญาจัดการได้อย่างถูกต้อง

Tuyên bố từ chối trách nhiệm
* Đầu tư tiền điện tử liên quan đến rủi ro đáng kể. Hãy tiến hành một cách thận trọng. Khóa học không nhằm mục đích tư vấn đầu tư.
* Khóa học được tạo bởi tác giả đã tham gia Gate Learn. Mọi ý kiến chia sẻ của tác giả không đại diện cho Gate Learn.