|
@@ -0,0 +1,264 @@
|
|
|
+import telebot
|
|
|
+import random
|
|
|
+import os
|
|
|
+
|
|
|
+TOKEN = "7030023448:AAFRdU_uwxpgT0K-mYy_UtohgkRnhpjE3IM"
|
|
|
+bot = telebot.TeleBot(TOKEN)
|
|
|
+
|
|
|
+DATABASE_FILE = "users.txt"
|
|
|
+
|
|
|
+EMPTY = "⬜"
|
|
|
+CROSS = "❌"
|
|
|
+CIRCLE = "⭕"
|
|
|
+
|
|
|
+def register_user(chat_id):
|
|
|
+ with open(DATABASE_FILE, "a") as f:
|
|
|
+ f.write(f"{chat_id},0,0\n")
|
|
|
+ print(f"User {chat_id} registered.")
|
|
|
+
|
|
|
+
|
|
|
+def get_user_data(chat_id):
|
|
|
+ with open(DATABASE_FILE, "r") as f:
|
|
|
+ for line in f:
|
|
|
+ data = line.strip().split(",")
|
|
|
+ if int(data[0]) == chat_id:
|
|
|
+ return {
|
|
|
+ "chat_id": int(data[0]),
|
|
|
+ "win_bot": int(data[1]),
|
|
|
+ "balance": int(data[2])
|
|
|
+ }
|
|
|
+ return None
|
|
|
+
|
|
|
+
|
|
|
+def update_user_data(chat_id, win_bot=None, balance=None):
|
|
|
+ lines = []
|
|
|
+ with open(DATABASE_FILE, "r") as f:
|
|
|
+ for line in f:
|
|
|
+ data = line.strip().split(",")
|
|
|
+ if int(data[0]) == chat_id:
|
|
|
+ if win_bot is not None:
|
|
|
+ data[1] = str(win_bot)
|
|
|
+ if balance is not None:
|
|
|
+ data[2] = str(balance)
|
|
|
+ lines.append(",".join(data) + "\n")
|
|
|
+
|
|
|
+ with open(DATABASE_FILE, "w") as f:
|
|
|
+ f.writelines(lines)
|
|
|
+ print(f"User {chat_id} data updated.")
|
|
|
+
|
|
|
+# --- Игровые функции ---
|
|
|
+def create_board():
|
|
|
+ return [EMPTY] * 9
|
|
|
+
|
|
|
+def print_board(board):
|
|
|
+ row1 = board[0:3]
|
|
|
+ row2 = board[3:6]
|
|
|
+ row3 = board[6:9]
|
|
|
+
|
|
|
+ return f'{row1[0]}{row1[1]}{row1[2]}\n{row2[0]}{row2[1]}{row2[2]}\n{row3[0]}{row3[1]}{row3[2]}'
|
|
|
+
|
|
|
+def check_winner(board, player):
|
|
|
+ # Проверка строк, столбцов и диагоналей
|
|
|
+ for i in range(0, 9, 3):
|
|
|
+ if board[i] == board[i+1] == board[i+2] == player:
|
|
|
+ return True
|
|
|
+ for i in range(3):
|
|
|
+ if board[i] == board[i+3] == board[i+6] == player:
|
|
|
+ return True
|
|
|
+ if board[0] == board[4] == board[8] == player:
|
|
|
+ return True
|
|
|
+ if board[2] == board[4] == board[6] == player:
|
|
|
+ return True
|
|
|
+ return False
|
|
|
+
|
|
|
+def is_board_full(board):
|
|
|
+ return EMPTY not in board
|
|
|
+
|
|
|
+def bot_move(board):
|
|
|
+ # 1. Проверка возможности выигрыша для бота
|
|
|
+ for i in range(9):
|
|
|
+ if board[i] == EMPTY:
|
|
|
+ temp_board = board[:]
|
|
|
+ temp_board[i] = CIRCLE
|
|
|
+ if check_winner(temp_board, CIRCLE):
|
|
|
+ return i
|
|
|
+
|
|
|
+ # 2. Проверка возможности выигрыша для игрока и блокировка
|
|
|
+ for i in range(9):
|
|
|
+ if board[i] == EMPTY:
|
|
|
+ temp_board = board[:]
|
|
|
+ temp_board[i] = CROSS
|
|
|
+ if check_winner(temp_board, CROSS):
|
|
|
+ return i
|
|
|
+
|
|
|
+ # 3. Выбор случайной пустой клетки (стратегически)
|
|
|
+ corners = [0, 2, 6, 8]
|
|
|
+ available_corners = [i for i in corners if board[i] == EMPTY]
|
|
|
+ if available_corners:
|
|
|
+ return random.choice(available_corners)
|
|
|
+
|
|
|
+ center = 4
|
|
|
+ if board[center] == EMPTY:
|
|
|
+ return center
|
|
|
+
|
|
|
+ edges = [1, 3, 5, 7]
|
|
|
+ available_edges = [i for i in edges if board[i] == EMPTY]
|
|
|
+ if available_edges:
|
|
|
+ return random.choice(available_edges)
|
|
|
+
|
|
|
+ return None # Доска заполнена, и нет доступных ходов
|
|
|
+
|
|
|
+def create_board_markup(board):
|
|
|
+ markup = telebot.types.InlineKeyboardMarkup(row_width=3)
|
|
|
+ buttons = []
|
|
|
+ for i in range(9):
|
|
|
+ buttons.append(telebot.types.InlineKeyboardButton(board[i], callback_data=f"move_{i}"))
|
|
|
+ markup.add(*buttons)
|
|
|
+ return markup
|
|
|
+
|
|
|
+# --- Обработчики ---
|
|
|
+@bot.message_handler(commands=["start"])
|
|
|
+def start(message):
|
|
|
+ chat_id = message.chat.id
|
|
|
+ user_data = get_user_data(chat_id)
|
|
|
+
|
|
|
+ if user_data is None:
|
|
|
+ register_user(chat_id)
|
|
|
+ bot.send_message(chat_id, "Вы успешно зарегистрированы!")
|
|
|
+
|
|
|
+ markup = telebot.types.InlineKeyboardMarkup(row_width=2)
|
|
|
+ item_profile = telebot.types.InlineKeyboardButton("Профиль", callback_data="profile")
|
|
|
+ item_play = telebot.types.InlineKeyboardButton("Играть", callback_data="play")
|
|
|
+ markup.add(item_profile, item_play)
|
|
|
+
|
|
|
+ with open("zastavka.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Выберите действие:", reply_markup=markup)
|
|
|
+
|
|
|
+# Обработчик inline кнопок
|
|
|
+@bot.callback_query_handler(func=lambda call: True)
|
|
|
+def callback_inline(call):
|
|
|
+ chat_id = call.message.chat.id
|
|
|
+ message_id = call.message.message_id
|
|
|
+
|
|
|
+ if call.data == "profile":
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ show_profile(chat_id)
|
|
|
+
|
|
|
+ elif call.data == "play":
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ start_game(chat_id)
|
|
|
+
|
|
|
+ elif call.data.startswith("move_"):
|
|
|
+ handle_move(call)
|
|
|
+
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+
|
|
|
+def handle_move(call):
|
|
|
+ chat_id = call.message.chat.id
|
|
|
+ message_id = call.message.message_id
|
|
|
+ move = int(call.data.split("_")[1])
|
|
|
+
|
|
|
+ game_data = games.get(chat_id)
|
|
|
+ if not game_data:
|
|
|
+ bot.send_message(chat_id, "Игра не найдена.")
|
|
|
+ return
|
|
|
+
|
|
|
+ board = game_data["board"]
|
|
|
+
|
|
|
+ if board[move] != EMPTY:
|
|
|
+ bot.send_message(chat_id, "Эта клетка уже занята!")
|
|
|
+ return
|
|
|
+
|
|
|
+ # Ход человека
|
|
|
+ board[move] = CROSS
|
|
|
+ if check_winner(board, CROSS):
|
|
|
+ user_data = get_user_data(chat_id)
|
|
|
+ if user_data:
|
|
|
+ update_user_data(chat_id, win_bot=int(user_data["win_bot"]) + 1, balance=int(user_data["balance"]) + 10)
|
|
|
+ with open("pobeda.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Вы выйграли!\n+10 монет")
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ del games[chat_id]
|
|
|
+ show_menu(chat_id)
|
|
|
+ return
|
|
|
+
|
|
|
+ if is_board_full(board):
|
|
|
+ with open("niza.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Ничья!")
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ del games[chat_id]
|
|
|
+ show_menu(chat_id)
|
|
|
+ return
|
|
|
+
|
|
|
+ # Ход бота
|
|
|
+ bot_choice = bot_move(board)
|
|
|
+ if bot_choice is not None:
|
|
|
+ board[bot_choice] = CIRCLE
|
|
|
+ else:
|
|
|
+ with open("niza.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Ничья!")
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ del games[chat_id]
|
|
|
+ show_menu(chat_id)
|
|
|
+ return
|
|
|
+
|
|
|
+ if check_winner(board, CIRCLE):
|
|
|
+ with open("lose.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Вы проиграли!")
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ del games[chat_id]
|
|
|
+ show_menu(chat_id)
|
|
|
+ return
|
|
|
+
|
|
|
+ if is_board_full(board):
|
|
|
+ with open("niza.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Ничья!")
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ del games[chat_id]
|
|
|
+ show_menu(chat_id)
|
|
|
+ return
|
|
|
+
|
|
|
+ game_data["board"] = board
|
|
|
+ games[chat_id] = game_data
|
|
|
+ bot.delete_message(chat_id, message_id)
|
|
|
+ send_board(chat_id, board)
|
|
|
+
|
|
|
+def show_profile(chat_id):
|
|
|
+ user_data = get_user_data(chat_id)
|
|
|
+
|
|
|
+ if user_data:
|
|
|
+ profile_info = (
|
|
|
+ f"Имя аккаунта: {chat_id}\n"
|
|
|
+ f"Побед с ботом: {user_data['win_bot']}\n"
|
|
|
+ f"Баланс: {user_data['balance']} серебра"
|
|
|
+ )
|
|
|
+
|
|
|
+ with open("profil.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption=profile_info)
|
|
|
+ else:
|
|
|
+ bot.send_message(chat_id, "Произошла ошибка при получении данных профиля.")
|
|
|
+ show_menu(chat_id)
|
|
|
+
|
|
|
+def start_game(chat_id):
|
|
|
+ board = create_board()
|
|
|
+ game_data = {"board": board}
|
|
|
+ games[chat_id] = game_data
|
|
|
+ send_board(chat_id, board)
|
|
|
+
|
|
|
+def send_board(chat_id, board):
|
|
|
+ markup = create_board_markup(board)
|
|
|
+ bot.send_message(chat_id, print_board(board), reply_markup=markup)
|
|
|
+
|
|
|
+def show_menu(chat_id):
|
|
|
+ markup = telebot.types.InlineKeyboardMarkup(row_width=2)
|
|
|
+ item_profile = telebot.types.InlineKeyboardButton("Профиль", callback_data="profile")
|
|
|
+ item_play = telebot.types.InlineKeyboardButton("Играть", callback_data="play")
|
|
|
+ markup.add(item_profile, item_play)
|
|
|
+
|
|
|
+ with open("zastavka.jpg", "rb") as photo:
|
|
|
+ bot.send_photo(chat_id, photo, caption="Выберите действие:", reply_markup=markup)
|
|
|
+
|
|
|
+
|
|
|
+games = {}
|
|
|
+bot.polling(none_stop=True)
|