ДЗ tic_tac_toy&quest
parent
f33802a740
commit
49c74ea2b6
|
@ -621,6 +621,24 @@ files = [
|
||||||
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "networkx"
|
||||||
|
version = "3.2.1"
|
||||||
|
description = "Python package for creating and manipulating graphs and networks"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"},
|
||||||
|
{file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
default = ["matplotlib (>=3.5)", "numpy (>=1.22)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"]
|
||||||
|
developer = ["changelist (==0.4)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"]
|
||||||
|
doc = ["nb2plots (>=0.7)", "nbconvert (<7.9)", "numpydoc (>=1.6)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"]
|
||||||
|
extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.11)", "sympy (>=1.10)"]
|
||||||
|
test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodeenv"
|
name = "nodeenv"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
|
@ -1093,4 +1111,4 @@ multidict = ">=4.0"
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "74b5d10c672b860dada4f42ba97679cbab3b3e9b29d92a9ff7fbed7f61bfd5c5"
|
content-hash = "cd0c5b9b5963bfaaf67b54596050f1f7d860381ae6e360dc266ad14dc186d30c"
|
||||||
|
|
|
@ -13,6 +13,7 @@ requests = "^2.31.0"
|
||||||
types-requests = "^2.31.0.20240125"
|
types-requests = "^2.31.0.20240125"
|
||||||
mypy = "^1.8.0"
|
mypy = "^1.8.0"
|
||||||
pyquizapi = "^0.0.14"
|
pyquizapi = "^0.0.14"
|
||||||
|
networkx = "^3.2.1"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
|
|
@ -16,12 +16,18 @@ from tg_bot.handlers import (
|
||||||
lesson_one,
|
lesson_one,
|
||||||
lesson_tree,
|
lesson_tree,
|
||||||
lesson_two,
|
lesson_two,
|
||||||
|
quest,
|
||||||
|
quiz,
|
||||||
|
tic_tac_toy,
|
||||||
)
|
)
|
||||||
|
|
||||||
TOKEN: str = getenv('BOT_TOKEN') or 'Your TG_BOT token'
|
TOKEN: str = getenv('BOT_TOKEN') or 'Your TG_BOT token'
|
||||||
|
|
||||||
dp = Dispatcher()
|
dp = Dispatcher()
|
||||||
dp.include_routers(
|
dp.include_routers(
|
||||||
|
quest.router,
|
||||||
|
tic_tac_toy.router,
|
||||||
|
quiz.router,
|
||||||
games.router,
|
games.router,
|
||||||
lesson_five.router,
|
lesson_five.router,
|
||||||
lesson_four.router,
|
lesson_four.router,
|
||||||
|
|
|
@ -1,29 +1,6 @@
|
||||||
from os import getenv
|
from aiogram import Router
|
||||||
|
|
||||||
from aiogram import Bot, F, Router
|
|
||||||
from aiogram.filters import Command
|
from aiogram.filters import Command
|
||||||
from aiogram.fsm.context import FSMContext
|
from aiogram.types import KeyboardButton, Message, ReplyKeyboardMarkup
|
||||||
from aiogram.fsm.state import State, StatesGroup
|
|
||||||
from aiogram.types import (
|
|
||||||
CallbackQuery,
|
|
||||||
InlineKeyboardButton,
|
|
||||||
InlineKeyboardMarkup,
|
|
||||||
KeyboardButton,
|
|
||||||
Message,
|
|
||||||
ReplyKeyboardMarkup,
|
|
||||||
ReplyKeyboardRemove,
|
|
||||||
)
|
|
||||||
from pyquizAPI import QuizClient
|
|
||||||
|
|
||||||
|
|
||||||
async def get_question():
|
|
||||||
api = getenv('QUIZ_API')
|
|
||||||
client = QuizClient(api)
|
|
||||||
client.make_config(limit=1, difficulty='Easy')
|
|
||||||
|
|
||||||
questions = client.get_questions(use_config=True)
|
|
||||||
return questions
|
|
||||||
|
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
kb = [
|
kb = [
|
||||||
|
@ -33,87 +10,9 @@ kb = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class GameState(StatesGroup):
|
|
||||||
game = State()
|
|
||||||
quiz = State()
|
|
||||||
tic_tac_toy = State()
|
|
||||||
quest = State()
|
|
||||||
|
|
||||||
|
|
||||||
markup_kb = ReplyKeyboardMarkup(keyboard=kb, resize_keyboard=True)
|
markup_kb = ReplyKeyboardMarkup(keyboard=kb, resize_keyboard=True)
|
||||||
|
|
||||||
|
|
||||||
@router.message(Command('games'))
|
@router.message(Command('games'))
|
||||||
async def games(message: Message):
|
async def games(message: Message):
|
||||||
await message.answer('Select Game:', reply_markup=markup_kb)
|
await message.answer('Select Game:', reply_markup=markup_kb)
|
||||||
|
|
||||||
|
|
||||||
@router.message(F.text.lower() == 'exit game')
|
|
||||||
async def exit_games(message: Message, state: FSMContext):
|
|
||||||
await state.clear()
|
|
||||||
await message.reply('Game is finished', reply_markup=ReplyKeyboardRemove())
|
|
||||||
|
|
||||||
|
|
||||||
@router.message(F.text.lower() == 'quiz')
|
|
||||||
async def with_puree(message: Message, state: FSMContext):
|
|
||||||
quiz_kb = [
|
|
||||||
[KeyboardButton(text='Next question')],
|
|
||||||
[KeyboardButton(text='Exit Game')],
|
|
||||||
]
|
|
||||||
await state.set_state(GameState.quiz)
|
|
||||||
|
|
||||||
await message.reply('Start Quiz', reply_markup=ReplyKeyboardRemove())
|
|
||||||
await message.reply(
|
|
||||||
'First question:',
|
|
||||||
reply_markup=ReplyKeyboardMarkup(keyboard=quiz_kb, resize_keyboard=True),
|
|
||||||
)
|
|
||||||
await question(message, state)
|
|
||||||
|
|
||||||
|
|
||||||
@router.message(GameState.quiz, F.text)
|
|
||||||
async def question(message: Message, state: FSMContext):
|
|
||||||
data = await state.get_data()
|
|
||||||
question_data = await get_question()
|
|
||||||
question = question_data[0].get('question')
|
|
||||||
answers = {
|
|
||||||
question_data[0]['answers'][k]: question_data[0]['correct_answers'][
|
|
||||||
k + '_correct'
|
|
||||||
]
|
|
||||||
for k in question_data[0]['answers'].keys()
|
|
||||||
if question_data[0]['answers'][k] is not None
|
|
||||||
}
|
|
||||||
buttons = []
|
|
||||||
|
|
||||||
idx = 1
|
|
||||||
text = f'Question:\n{question}\n\nanswers:\n'
|
|
||||||
|
|
||||||
for k, v in answers.items():
|
|
||||||
buttons.append([InlineKeyboardButton(text=f'choice {idx}', callback_data=k)])
|
|
||||||
if v == 'true':
|
|
||||||
data['answer'] = k
|
|
||||||
text = text + f'{idx} - {k}\n'
|
|
||||||
idx += 1
|
|
||||||
|
|
||||||
data['question'] = question
|
|
||||||
await state.update_data(data)
|
|
||||||
|
|
||||||
await message.answer(
|
|
||||||
text=text,
|
|
||||||
reply_markup=InlineKeyboardMarkup(inline_keyboard=buttons),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.callback_query(GameState.quiz)
|
|
||||||
async def check_answer(callback: CallbackQuery, state: FSMContext, bot: Bot):
|
|
||||||
answer = (await state.get_data())['answer']
|
|
||||||
|
|
||||||
await callback.answer()
|
|
||||||
if answer == callback.data:
|
|
||||||
await callback.message.answer(text='Correct')
|
|
||||||
else:
|
|
||||||
await callback.message.answer(text='Opps. You miss')
|
|
||||||
await bot.edit_message_text(
|
|
||||||
chat_id=callback.from_user.id,
|
|
||||||
message_id=callback.message.message_id,
|
|
||||||
text=callback.message.text,
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
import networkx as nx
|
||||||
|
from aiogram import Bot, F, Router
|
||||||
|
from aiogram.fsm.context import FSMContext
|
||||||
|
from aiogram.fsm.state import State, StatesGroup
|
||||||
|
from aiogram.types import (
|
||||||
|
CallbackQuery,
|
||||||
|
InlineKeyboardButton,
|
||||||
|
InlineKeyboardMarkup,
|
||||||
|
KeyboardButton,
|
||||||
|
Message,
|
||||||
|
ReplyKeyboardMarkup,
|
||||||
|
ReplyKeyboardRemove,
|
||||||
|
)
|
||||||
|
from aiogram.utils.formatting import Bold, as_list, as_marked_section
|
||||||
|
|
||||||
|
G = nx.Graph()
|
||||||
|
|
||||||
|
G.add_node('start')
|
||||||
|
G.add_node('A')
|
||||||
|
G.add_node('B')
|
||||||
|
G.add_node('C')
|
||||||
|
G.add_node('D')
|
||||||
|
G.add_node('end')
|
||||||
|
|
||||||
|
G.add_edge('start', 'A')
|
||||||
|
G.add_edge('start', 'B')
|
||||||
|
G.add_edge('A', 'C')
|
||||||
|
G.add_edge('A', 'D')
|
||||||
|
G.add_edge('D', 'end')
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
|
class GameState(StatesGroup):
|
||||||
|
quest = State()
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(F.text.lower() == 'exit game')
|
||||||
|
async def exit_games(message: Message, state: FSMContext):
|
||||||
|
await state.clear()
|
||||||
|
await message.reply('Game is finished', reply_markup=ReplyKeyboardRemove())
|
||||||
|
|
||||||
|
|
||||||
|
async def get_content(place, backward, forward):
|
||||||
|
if forward != ['None']:
|
||||||
|
f_text = 'Можете продолжить путь'
|
||||||
|
else:
|
||||||
|
f_text = 'Вы пришли в тупик, поищите другой путь'
|
||||||
|
|
||||||
|
content = as_list(
|
||||||
|
as_marked_section(
|
||||||
|
Bold('Вы находитесь в локации:'),
|
||||||
|
place,
|
||||||
|
marker='*️⃣ ',
|
||||||
|
),
|
||||||
|
as_marked_section(
|
||||||
|
Bold(
|
||||||
|
'Вы можете вернуться назад в локацию'
|
||||||
|
if backward
|
||||||
|
else 'Вы в начале, пути назад нет'
|
||||||
|
),
|
||||||
|
backward,
|
||||||
|
marker='⏪ ',
|
||||||
|
),
|
||||||
|
as_marked_section(
|
||||||
|
Bold(f_text),
|
||||||
|
*forward,
|
||||||
|
marker='⏩ ',
|
||||||
|
),
|
||||||
|
sep='\n\n',
|
||||||
|
)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
async def get_keyboard(backward, forward):
|
||||||
|
buttons = []
|
||||||
|
|
||||||
|
if backward is not None:
|
||||||
|
buttons.append(
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text=f'◀️◀️◀️ Вернуться в {backward}',
|
||||||
|
callback_data=f'bacward_{backward}',
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
if forward is not None:
|
||||||
|
for f in forward:
|
||||||
|
buttons.append(
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text=f'Идти в {f} ▶️▶️▶️', callback_data=f'forward_{f}'
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(F.text.lower() == 'quest')
|
||||||
|
async def start_quest(message: Message, state: FSMContext):
|
||||||
|
quest_kb = [
|
||||||
|
[KeyboardButton(text='Exit Game')],
|
||||||
|
]
|
||||||
|
|
||||||
|
await state.set_state(GameState.quest)
|
||||||
|
|
||||||
|
data = {'backward': None, 'place': 'start', 'forward': ['A', 'B']}
|
||||||
|
|
||||||
|
await state.set_data(data)
|
||||||
|
|
||||||
|
await message.reply('Start quest', reply_markup=ReplyKeyboardRemove())
|
||||||
|
await message.reply(
|
||||||
|
'Make your move',
|
||||||
|
reply_markup=ReplyKeyboardMarkup(keyboard=quest_kb, resize_keyboard=True),
|
||||||
|
)
|
||||||
|
await make_move(message, state)
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(GameState.quest, F.text)
|
||||||
|
async def make_move(message: Message, state: FSMContext):
|
||||||
|
data = await state.get_data()
|
||||||
|
|
||||||
|
keyboard = await get_keyboard(data['backward'], data['forward'])
|
||||||
|
content = await get_content(data['place'], data['backward'], data['forward'])
|
||||||
|
|
||||||
|
await message.answer(**content.as_kwargs(), reply_markup=keyboard)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(GameState.quest)
|
||||||
|
async def check_answer(callback: CallbackQuery, state: FSMContext, bot: Bot):
|
||||||
|
data = await state.get_data()
|
||||||
|
data['backward'] = data['place']
|
||||||
|
data['place'] = (callback.data.split('_'))[1]
|
||||||
|
data['forward'] = list(G.neighbors(data['place']))
|
||||||
|
data['forward'].remove(data['backward'])
|
||||||
|
|
||||||
|
await state.update_data(data)
|
||||||
|
if data['place'] == 'end':
|
||||||
|
await callback.answer(text='Вы дошли до конца!!!', show_alert=True)
|
||||||
|
await start_quest(callback.message, state)
|
||||||
|
return
|
||||||
|
|
||||||
|
content = await get_content(
|
||||||
|
data['place'], data['backward'], data['forward'] or ['None']
|
||||||
|
)
|
||||||
|
keyboard = await get_keyboard(data['backward'], data['forward'])
|
||||||
|
|
||||||
|
await bot.send_message(
|
||||||
|
**content.as_kwargs(), chat_id=callback.from_user.id, reply_markup=keyboard
|
||||||
|
)
|
||||||
|
await callback.answer()
|
|
@ -0,0 +1,142 @@
|
||||||
|
from os import getenv
|
||||||
|
|
||||||
|
from aiogram import Bot, F, Router, html
|
||||||
|
from aiogram.fsm.context import FSMContext
|
||||||
|
from aiogram.fsm.state import State, StatesGroup
|
||||||
|
from aiogram.types import (
|
||||||
|
CallbackQuery,
|
||||||
|
InlineKeyboardButton,
|
||||||
|
InlineKeyboardMarkup,
|
||||||
|
KeyboardButton,
|
||||||
|
Message,
|
||||||
|
ReplyKeyboardMarkup,
|
||||||
|
ReplyKeyboardRemove,
|
||||||
|
)
|
||||||
|
from aiogram.utils.formatting import Bold, as_key_value, as_list, as_marked_section
|
||||||
|
from pyquizAPI import QuizClient
|
||||||
|
|
||||||
|
|
||||||
|
async def get_question():
|
||||||
|
api = getenv('QUIZ_API')
|
||||||
|
client = QuizClient(api)
|
||||||
|
client.make_config(limit=1, difficulty='Easy')
|
||||||
|
|
||||||
|
questions = client.get_questions(use_config=True)
|
||||||
|
return questions
|
||||||
|
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
|
class GameState(StatesGroup):
|
||||||
|
quiz = State()
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(F.text.lower() == 'exit game')
|
||||||
|
async def exit_games(message: Message, state: FSMContext):
|
||||||
|
await state.clear()
|
||||||
|
await message.reply('Game is finished', reply_markup=ReplyKeyboardRemove())
|
||||||
|
|
||||||
|
|
||||||
|
async def get_formated_question(
|
||||||
|
qnt: int, correct: int, question: str, answers: list[str]
|
||||||
|
):
|
||||||
|
content = as_list(
|
||||||
|
as_marked_section(
|
||||||
|
Bold('Game summary:'),
|
||||||
|
as_key_value('Total questions', qnt),
|
||||||
|
as_key_value('Success', correct),
|
||||||
|
as_key_value('Failed', qnt - correct),
|
||||||
|
marker=' ',
|
||||||
|
),
|
||||||
|
as_marked_section(
|
||||||
|
Bold('Question:'),
|
||||||
|
html.quote(question),
|
||||||
|
marker='❔ ',
|
||||||
|
),
|
||||||
|
as_marked_section(
|
||||||
|
Bold('Answers:'),
|
||||||
|
*[html.quote(item) for item in answers],
|
||||||
|
marker='➖ ',
|
||||||
|
),
|
||||||
|
sep='\n\n',
|
||||||
|
)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(F.text.lower() == 'quiz')
|
||||||
|
async def start_quiz(message: Message, state: FSMContext):
|
||||||
|
quiz_kb = [
|
||||||
|
[KeyboardButton(text='Next question')],
|
||||||
|
[KeyboardButton(text='Exit Game')],
|
||||||
|
]
|
||||||
|
await state.set_state(GameState.quiz)
|
||||||
|
|
||||||
|
await message.reply('Start Quiz', reply_markup=ReplyKeyboardRemove())
|
||||||
|
await message.reply(
|
||||||
|
'First question:',
|
||||||
|
reply_markup=ReplyKeyboardMarkup(keyboard=quiz_kb, resize_keyboard=True),
|
||||||
|
)
|
||||||
|
await question(message, state)
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(GameState.quiz, F.text)
|
||||||
|
async def question(message: Message, state: FSMContext):
|
||||||
|
data = await state.get_data()
|
||||||
|
question_data = await get_question()
|
||||||
|
question = question_data[0].get('question')
|
||||||
|
answers = {
|
||||||
|
question_data[0]['answers'][k]: question_data[0]['correct_answers'][
|
||||||
|
k + '_correct'
|
||||||
|
]
|
||||||
|
for k in question_data[0]['answers'].keys()
|
||||||
|
if question_data[0]['answers'][k] is not None
|
||||||
|
}
|
||||||
|
buttons = []
|
||||||
|
|
||||||
|
idx = 1
|
||||||
|
|
||||||
|
for k, v in answers.items():
|
||||||
|
buttons.append([InlineKeyboardButton(text=f'choice {idx}', callback_data=k)])
|
||||||
|
if v == 'true':
|
||||||
|
data['answer'] = k
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
content = await get_formated_question(
|
||||||
|
data.get('quantity', 0), data.get('score', 0), question, list(answers.keys())
|
||||||
|
)
|
||||||
|
data['question'] = question
|
||||||
|
await state.update_data(data)
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
**content.as_kwargs(),
|
||||||
|
reply_markup=InlineKeyboardMarkup(inline_keyboard=buttons),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(GameState.quiz)
|
||||||
|
async def check_answer(callback: CallbackQuery, state: FSMContext, bot: Bot):
|
||||||
|
data = await state.get_data()
|
||||||
|
answer = data['answer']
|
||||||
|
score = data.get('score', 0)
|
||||||
|
qnt = data.get('quantity', 0)
|
||||||
|
|
||||||
|
await callback.answer()
|
||||||
|
if answer == callback.data:
|
||||||
|
await callback.message.answer(text='Correct')
|
||||||
|
score += 1
|
||||||
|
else:
|
||||||
|
await callback.message.answer(text='Opps. You miss')
|
||||||
|
qnt += 1
|
||||||
|
|
||||||
|
data['score'] = score
|
||||||
|
data['quantity'] = qnt
|
||||||
|
await state.update_data(data)
|
||||||
|
|
||||||
|
msg_text: str = callback.message.text
|
||||||
|
|
||||||
|
await bot.edit_message_text(
|
||||||
|
chat_id=callback.from_user.id,
|
||||||
|
message_id=callback.message.message_id,
|
||||||
|
text=msg_text,
|
||||||
|
)
|
|
@ -0,0 +1,213 @@
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
from aiogram import Bot, F, Router
|
||||||
|
from aiogram.fsm.context import FSMContext
|
||||||
|
from aiogram.fsm.state import State, StatesGroup
|
||||||
|
from aiogram.types import (
|
||||||
|
CallbackQuery,
|
||||||
|
InlineKeyboardButton,
|
||||||
|
InlineKeyboardMarkup,
|
||||||
|
KeyboardButton,
|
||||||
|
Message,
|
||||||
|
ReplyKeyboardMarkup,
|
||||||
|
ReplyKeyboardRemove,
|
||||||
|
)
|
||||||
|
from aiogram.utils.formatting import Bold, as_key_value, as_list, as_marked_section
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
|
class GameState(StatesGroup):
|
||||||
|
tic_tac_toy = State()
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(F.text.lower() == 'exit game')
|
||||||
|
async def exit_games(message: Message, state: FSMContext):
|
||||||
|
await state.clear()
|
||||||
|
await message.reply('Game is finished', reply_markup=ReplyKeyboardRemove())
|
||||||
|
|
||||||
|
|
||||||
|
async def get_keyboard(field: list):
|
||||||
|
buttons = []
|
||||||
|
|
||||||
|
for x in range(3):
|
||||||
|
row = []
|
||||||
|
for y in range(3):
|
||||||
|
callback_data = f'{x} {y}'
|
||||||
|
text = ''
|
||||||
|
|
||||||
|
match field[x][y]:
|
||||||
|
case None:
|
||||||
|
text = '⬛️'
|
||||||
|
case False:
|
||||||
|
text = '⭕️'
|
||||||
|
case True:
|
||||||
|
text = '❌'
|
||||||
|
|
||||||
|
row.append(
|
||||||
|
InlineKeyboardButton(text=text, callback_data=callback_data),
|
||||||
|
)
|
||||||
|
buttons.append(row)
|
||||||
|
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
|
||||||
|
async def get_content(bot_wins, user_wins, move):
|
||||||
|
content = as_list(
|
||||||
|
as_marked_section(
|
||||||
|
Bold('Game summary:'),
|
||||||
|
as_key_value('Total games', bot_wins + user_wins),
|
||||||
|
as_key_value('user wins', user_wins),
|
||||||
|
as_key_value('bot wins', bot_wins),
|
||||||
|
as_key_value('Move: ', move),
|
||||||
|
marker=' ',
|
||||||
|
),
|
||||||
|
sep='\n\n',
|
||||||
|
)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
async def check_winner(field):
|
||||||
|
winner = None
|
||||||
|
|
||||||
|
def check_equal_all_in_row(row):
|
||||||
|
if row[0] == row[1] and row[0] == row[2]:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
for row in field:
|
||||||
|
if check_equal_all_in_row(row):
|
||||||
|
winner = row[0]
|
||||||
|
|
||||||
|
for row in zip(*field):
|
||||||
|
if check_equal_all_in_row(row):
|
||||||
|
winner = row[0]
|
||||||
|
|
||||||
|
row = []
|
||||||
|
for i in range(3):
|
||||||
|
row.append(field[i][i])
|
||||||
|
|
||||||
|
if check_equal_all_in_row(row):
|
||||||
|
winner = row[0]
|
||||||
|
|
||||||
|
row = []
|
||||||
|
for i in range(3):
|
||||||
|
row.append(field[i][2 - i])
|
||||||
|
|
||||||
|
if check_equal_all_in_row(row):
|
||||||
|
winner = row[0]
|
||||||
|
|
||||||
|
return winner
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(F.text.lower() == 'tic_tac_toy')
|
||||||
|
async def start_tic_tac_toy(
|
||||||
|
message: Message, state: FSMContext, user_wins=0, bot_wins=0
|
||||||
|
):
|
||||||
|
tic_tac_toy_kb = [
|
||||||
|
[KeyboardButton(text='Exit Game')],
|
||||||
|
]
|
||||||
|
await state.clear()
|
||||||
|
await state.set_state(GameState.tic_tac_toy)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'field': [[None for _ in range(3)] for _ in range(3)],
|
||||||
|
'availible_moves': [(x, y) for x in range(3) for y in range(3)],
|
||||||
|
'user_wins': user_wins,
|
||||||
|
'bot_wins': bot_wins,
|
||||||
|
'move': 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
await state.set_data(data)
|
||||||
|
|
||||||
|
await message.reply('Start Tic Tac Toy', reply_markup=ReplyKeyboardRemove())
|
||||||
|
await message.reply(
|
||||||
|
'Make your move',
|
||||||
|
reply_markup=ReplyKeyboardMarkup(keyboard=tic_tac_toy_kb, resize_keyboard=True),
|
||||||
|
)
|
||||||
|
await make_move(message, state)
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(GameState.tic_tac_toy, F.text)
|
||||||
|
async def make_move(message: Message, state: FSMContext):
|
||||||
|
data = await state.get_data()
|
||||||
|
keyboard = await get_keyboard(data['field'])
|
||||||
|
await state.update_data(data)
|
||||||
|
content = await get_content(
|
||||||
|
data['bot_wins'],
|
||||||
|
data['user_wins'],
|
||||||
|
data['move'],
|
||||||
|
)
|
||||||
|
|
||||||
|
await message.answer(**content.as_kwargs(), reply_markup=keyboard)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(GameState.tic_tac_toy)
|
||||||
|
async def check_answer(callback: CallbackQuery, state: FSMContext, bot: Bot):
|
||||||
|
data = await state.get_data()
|
||||||
|
x, y = map(int, callback.data.split())
|
||||||
|
if (x, y) not in data['availible_moves']:
|
||||||
|
await callback.answer(text='Cell is busy', show_alert=True)
|
||||||
|
else:
|
||||||
|
data['move'] += 1
|
||||||
|
data['field'][x][y] = True
|
||||||
|
data['availible_moves'].remove((x, y))
|
||||||
|
await state.update_data(data)
|
||||||
|
|
||||||
|
keyboard = await get_keyboard(data['field'])
|
||||||
|
|
||||||
|
content = await get_content(
|
||||||
|
data['bot_wins'],
|
||||||
|
data['user_wins'],
|
||||||
|
data['move'],
|
||||||
|
)
|
||||||
|
|
||||||
|
await bot.edit_message_text(
|
||||||
|
**content.as_kwargs(),
|
||||||
|
chat_id=callback.from_user.id,
|
||||||
|
message_id=callback.message.message_id,
|
||||||
|
reply_markup=keyboard,
|
||||||
|
)
|
||||||
|
winner = await check_winner(data['field'])
|
||||||
|
if winner is True:
|
||||||
|
await callback.answer()
|
||||||
|
await start_tic_tac_toy(
|
||||||
|
callback.message, state, data['user_wins'] + 1, data['bot_wins']
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not data['availible_moves']:
|
||||||
|
await callback.answer('A draw game')
|
||||||
|
await start_tic_tac_toy(
|
||||||
|
callback.message, state, data['user_wins'], data['bot_wins']
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
x, y = choice(data['availible_moves'])
|
||||||
|
data['field'][x][y] = False
|
||||||
|
data['availible_moves'].remove((x, y))
|
||||||
|
data['move'] += 1
|
||||||
|
await state.update_data(data)
|
||||||
|
keyboard = await get_keyboard(data['field'])
|
||||||
|
content = await get_content(
|
||||||
|
data['bot_wins'],
|
||||||
|
data['user_wins'],
|
||||||
|
data['move'],
|
||||||
|
)
|
||||||
|
await bot.edit_message_text(
|
||||||
|
**content.as_kwargs(),
|
||||||
|
chat_id=callback.from_user.id,
|
||||||
|
message_id=callback.message.message_id,
|
||||||
|
reply_markup=keyboard,
|
||||||
|
)
|
||||||
|
|
||||||
|
winner = await check_winner(data['field'])
|
||||||
|
if winner is False:
|
||||||
|
await callback.answer(text='Bot is WINNER')
|
||||||
|
await start_tic_tac_toy(
|
||||||
|
callback.message, state, data['user_wins'], data['bot_wins'] + 1
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
await callback.answer()
|
Loading…
Reference in New Issue