214 lines
5.8 KiB
Python
214 lines
5.8 KiB
Python
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()
|