mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-09-06 09:56:09 +00:00
Add examples for how to use views
This commit is contained in:
139
examples/views/tic_tac_toe.py
Normal file
139
examples/views/tic_tac_toe.py
Normal file
@ -0,0 +1,139 @@
|
||||
from typing import List
|
||||
from discord.ext import commands
|
||||
import discord
|
||||
|
||||
# Defines a custom button that contains the logic of the game.
|
||||
# The ['TicTacToe'] bit is for type hinting purposes to tell your IDE or linter
|
||||
# what the type of `self.view` is. It is not required.
|
||||
class TicTacToeButton(discord.ui.Button['TicTacToe']):
|
||||
def __init__(self, x: int, y: int):
|
||||
# A label is required, but we don't need one so a zero-width space is used
|
||||
# The row parameter tells the View which row to place the button under.
|
||||
# A View can only contain up to 5 rows -- each row can only have 5 buttons.
|
||||
# Since a Tic Tac Toe grid is 3x3 that means we have 3 rows and 3 columns.
|
||||
super().__init__(style=discord.ButtonStyle.secondary, label='\u200b', row=y)
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
# This function is called whenever this particular button is pressed
|
||||
# This is part of the "meat" of the game logic
|
||||
async def callback(self, interaction: discord.Interaction):
|
||||
assert self.view is not None
|
||||
view: TicTacToe = self.view
|
||||
state = view.board[self.y][self.x]
|
||||
if state in (view.X, view.O):
|
||||
return
|
||||
|
||||
if view.current_player == view.X:
|
||||
self.style = discord.ButtonStyle.danger
|
||||
self.label = 'X'
|
||||
self.disabled = True
|
||||
view.board[self.y][self.x] = view.X
|
||||
view.current_player = view.O
|
||||
content = "It is now O's turn"
|
||||
else:
|
||||
self.style = discord.ButtonStyle.success
|
||||
self.label = 'O'
|
||||
self.disabled = True
|
||||
view.board[self.y][self.x] = view.O
|
||||
view.current_player = view.X
|
||||
content = "It is now X's turn"
|
||||
|
||||
winner = view.check_board_winner()
|
||||
if winner is not None:
|
||||
if winner == view.X:
|
||||
content = 'X won!'
|
||||
elif winner == view.O:
|
||||
content = 'O won!'
|
||||
else:
|
||||
content = "It's a tie!"
|
||||
|
||||
for child in view.children:
|
||||
child.disabled = True
|
||||
|
||||
view.stop()
|
||||
|
||||
await interaction.response.edit_message(content=content, view=view)
|
||||
|
||||
|
||||
# This is our actual board View
|
||||
class TicTacToe(discord.ui.View):
|
||||
# This tells the IDE or linter that all our children will be TicTacToeButtons
|
||||
# This is not required
|
||||
children: List[TicTacToeButton]
|
||||
X = -1
|
||||
O = 1
|
||||
Tie = 2
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.current_player = self.X
|
||||
self.board = [
|
||||
[0, 0, 0],
|
||||
[0, 0, 0],
|
||||
[0, 0, 0],
|
||||
]
|
||||
|
||||
# Our board is made up of 3 by 3 TicTacToeButtons
|
||||
# The TicTacToeButton maintains the callbacks and helps steer
|
||||
# the actual game.
|
||||
for x in range(3):
|
||||
for y in range(3):
|
||||
self.add_item(TicTacToeButton(x, y))
|
||||
|
||||
# This method checks for the board winner -- it is used by the TicTacToeButton
|
||||
def check_board_winner(self):
|
||||
for across in self.board:
|
||||
value = sum(across)
|
||||
if value == 3:
|
||||
return self.O
|
||||
elif value == -3:
|
||||
return self.X
|
||||
|
||||
# Check vertical
|
||||
for line in range(3):
|
||||
value = self.board[0][line] + self.board[1][line] + self.board[2][line]
|
||||
if value == 3:
|
||||
return self.O
|
||||
elif value == -3:
|
||||
return self.X
|
||||
|
||||
# Check diagonals
|
||||
diag = self.board[0][2] + self.board[1][1] + self.board[2][0]
|
||||
if diag == 3:
|
||||
return self.O
|
||||
elif diag == -3:
|
||||
return self.X
|
||||
|
||||
diag = self.board[0][0] + self.board[1][1] + self.board[2][2]
|
||||
if diag == 3:
|
||||
return self.O
|
||||
elif diag == -3:
|
||||
return self.X
|
||||
|
||||
# If we're here, we need to check if a tie was made
|
||||
if all(i != 0 for row in self.board for i in row):
|
||||
return self.Tie
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class TicTacToeBot(commands.Bot):
|
||||
def __init__(self):
|
||||
super().__init__(command_prefix=commands.when_mentioned_or('$'))
|
||||
|
||||
async def on_ready(self):
|
||||
print(f'Logged in as {self.user} (ID: {self.user.id})')
|
||||
print('------')
|
||||
|
||||
|
||||
bot = TicTacToeBot()
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def tic(ctx: commands.Context):
|
||||
"""Starts a tic-tac-toe game with yourself."""
|
||||
await ctx.send('Tic Tac Toe: X goes first', view=TicTacToe())
|
||||
|
||||
|
||||
bot.run('token')
|
Reference in New Issue
Block a user