{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "710e0279",
   "metadata": {},
   "outputs": [],
   "source": [
    "import tkinter as tk\n",
    "import random\n",
    "\n",
    "\n",
    "# =========================\n",
    "# 游戏参数\n",
    "# =========================\n",
    "WINDOW_WIDTH = 600\n",
    "WINDOW_HEIGHT = 400\n",
    "CELL_SIZE = 20\n",
    "GAME_SPEED = 120       # 数值越小，蛇移动越快\n",
    "\n",
    "BACKGROUND_COLOR = \"black\"\n",
    "SNAKE_COLOR = \"lime\"\n",
    "SNAKE_HEAD_COLOR = \"green\"\n",
    "FOOD_COLOR = \"red\"\n",
    "\n",
    "\n",
    "class SnakeGame:\n",
    "    def __init__(self, root):\n",
    "        self.root = root\n",
    "        self.root.title(\"贪吃蛇游戏\")\n",
    "        self.root.resizable(False, False)\n",
    "\n",
    "        # 显示分数\n",
    "        self.score_label = tk.Label(\n",
    "            root,\n",
    "            text=\"得分：0\",\n",
    "            font=(\"Microsoft YaHei\", 16)\n",
    "        )\n",
    "        self.score_label.pack()\n",
    "\n",
    "        # 创建游戏画布\n",
    "        self.canvas = tk.Canvas(\n",
    "            root,\n",
    "            width=WINDOW_WIDTH,\n",
    "            height=WINDOW_HEIGHT,\n",
    "            bg=BACKGROUND_COLOR,\n",
    "            highlightthickness=0\n",
    "        )\n",
    "        self.canvas.pack()\n",
    "\n",
    "        # 操作说明\n",
    "        self.help_label = tk.Label(\n",
    "            root,\n",
    "            text=\"方向键控制移动｜空格键暂停｜Enter 键重新开始\",\n",
    "            font=(\"Microsoft YaHei\", 11)\n",
    "        )\n",
    "        self.help_label.pack(pady=5)\n",
    "\n",
    "        # 绑定键盘事件\n",
    "        self.root.bind(\"<KeyPress>\", self.change_direction)\n",
    "\n",
    "        self.timer_id = None\n",
    "        self.start_game()\n",
    "\n",
    "    def start_game(self):\n",
    "        \"\"\"初始化游戏\"\"\"\n",
    "        if self.timer_id is not None:\n",
    "            self.root.after_cancel(self.timer_id)\n",
    "            self.timer_id = None\n",
    "\n",
    "        self.canvas.delete(\"all\")\n",
    "\n",
    "        self.score = 0\n",
    "        self.direction = \"Right\"\n",
    "        self.next_direction = \"Right\"\n",
    "        self.is_running = True\n",
    "        self.is_paused = False\n",
    "\n",
    "        # 蛇的初始位置\n",
    "        start_x = WINDOW_WIDTH // 2\n",
    "        start_y = WINDOW_HEIGHT // 2\n",
    "\n",
    "        self.snake = [\n",
    "            (start_x, start_y),\n",
    "            (start_x - CELL_SIZE, start_y),\n",
    "            (start_x - 2 * CELL_SIZE, start_y)\n",
    "        ]\n",
    "\n",
    "        self.food = self.create_food()\n",
    "        self.score_label.config(text=\"得分：0\")\n",
    "\n",
    "        self.update_game()\n",
    "\n",
    "    def create_food(self):\n",
    "        \"\"\"随机生成食物，避免生成在蛇身体上\"\"\"\n",
    "        while True:\n",
    "            x = random.randrange(0, WINDOW_WIDTH, CELL_SIZE)\n",
    "            y = random.randrange(0, WINDOW_HEIGHT, CELL_SIZE)\n",
    "\n",
    "            if (x, y) not in self.snake:\n",
    "                return x, y\n",
    "\n",
    "    def change_direction(self, event):\n",
    "        \"\"\"处理键盘输入\"\"\"\n",
    "        key = event.keysym\n",
    "\n",
    "        direction_map = {\n",
    "            \"Up\": \"Up\",\n",
    "            \"Down\": \"Down\",\n",
    "            \"Left\": \"Left\",\n",
    "            \"Right\": \"Right\"\n",
    "        }\n",
    "\n",
    "        opposite_direction = {\n",
    "            \"Up\": \"Down\",\n",
    "            \"Down\": \"Up\",\n",
    "            \"Left\": \"Right\",\n",
    "            \"Right\": \"Left\"\n",
    "        }\n",
    "\n",
    "        # 按空格键暂停或继续\n",
    "        if key == \"space\" and self.is_running:\n",
    "            self.is_paused = not self.is_paused\n",
    "\n",
    "            if self.is_paused:\n",
    "                self.canvas.create_text(\n",
    "                    WINDOW_WIDTH // 2,\n",
    "                    WINDOW_HEIGHT // 2,\n",
    "                    text=\"游戏暂停\",\n",
    "                    fill=\"white\",\n",
    "                    font=(\"Microsoft YaHei\", 26, \"bold\"),\n",
    "                    tag=\"pause_text\"\n",
    "                )\n",
    "            else:\n",
    "                self.canvas.delete(\"pause_text\")\n",
    "\n",
    "            return\n",
    "\n",
    "        # 游戏结束后按 Enter 重新开始\n",
    "        if key == \"Return\" and not self.is_running:\n",
    "            self.start_game()\n",
    "            return\n",
    "\n",
    "        # 处理方向键\n",
    "        if key in direction_map:\n",
    "            new_direction = direction_map[key]\n",
    "\n",
    "            # 防止蛇直接反向移动\n",
    "            if new_direction != opposite_direction[self.direction]:\n",
    "                self.next_direction = new_direction\n",
    "\n",
    "    def move_snake(self):\n",
    "        \"\"\"计算蛇头的新位置\"\"\"\n",
    "        head_x, head_y = self.snake[0]\n",
    "\n",
    "        if self.direction == \"Up\":\n",
    "            head_y -= CELL_SIZE\n",
    "        elif self.direction == \"Down\":\n",
    "            head_y += CELL_SIZE\n",
    "        elif self.direction == \"Left\":\n",
    "            head_x -= CELL_SIZE\n",
    "        elif self.direction == \"Right\":\n",
    "            head_x += CELL_SIZE\n",
    "\n",
    "        return head_x, head_y\n",
    "\n",
    "    def check_collision(self, new_head):\n",
    "        \"\"\"判断是否撞墙或撞到自身\"\"\"\n",
    "        head_x, head_y = new_head\n",
    "\n",
    "        # 撞墙\n",
    "        if (\n",
    "            head_x < 0\n",
    "            or head_x >= WINDOW_WIDTH\n",
    "            or head_y < 0\n",
    "            or head_y >= WINDOW_HEIGHT\n",
    "        ):\n",
    "            return True\n",
    "\n",
    "        # 撞到自身\n",
    "        if new_head in self.snake:\n",
    "            return True\n",
    "\n",
    "        return False\n",
    "\n",
    "    def draw_game(self):\n",
    "        \"\"\"绘制蛇和食物\"\"\"\n",
    "        self.canvas.delete(\"snake\")\n",
    "        self.canvas.delete(\"food\")\n",
    "\n",
    "        # 绘制蛇\n",
    "        for index, (x, y) in enumerate(self.snake):\n",
    "            color = SNAKE_HEAD_COLOR if index == 0 else SNAKE_COLOR\n",
    "\n",
    "            self.canvas.create_rectangle(\n",
    "                x + 1,\n",
    "                y + 1,\n",
    "                x + CELL_SIZE - 1,\n",
    "                y + CELL_SIZE - 1,\n",
    "                fill=color,\n",
    "                outline=\"white\",\n",
    "                tag=\"snake\"\n",
    "            )\n",
    "\n",
    "        # 绘制食物\n",
    "        food_x, food_y = self.food\n",
    "\n",
    "        self.canvas.create_oval(\n",
    "            food_x + 2,\n",
    "            food_y + 2,\n",
    "            food_x + CELL_SIZE - 2,\n",
    "            food_y + CELL_SIZE - 2,\n",
    "            fill=FOOD_COLOR,\n",
    "            outline=\"white\",\n",
    "            tag=\"food\"\n",
    "        )\n",
    "\n",
    "    def update_game(self):\n",
    "        \"\"\"游戏主循环\"\"\"\n",
    "        if not self.is_running:\n",
    "            return\n",
    "\n",
    "        if not self.is_paused:\n",
    "            self.direction = self.next_direction\n",
    "            new_head = self.move_snake()\n",
    "\n",
    "            # 检查碰撞\n",
    "            if self.check_collision(new_head):\n",
    "                self.game_over()\n",
    "                return\n",
    "\n",
    "            # 将新蛇头加入身体\n",
    "            self.snake.insert(0, new_head)\n",
    "\n",
    "            # 判断是否吃到食物\n",
    "            if new_head == self.food:\n",
    "                self.score += 1\n",
    "                self.score_label.config(text=f\"得分：{self.score}\")\n",
    "                self.food = self.create_food()\n",
    "            else:\n",
    "                # 没吃到食物时删除蛇尾\n",
    "                self.snake.pop()\n",
    "\n",
    "            self.draw_game()\n",
    "\n",
    "        self.timer_id = self.root.after(GAME_SPEED, self.update_game)\n",
    "\n",
    "    def game_over(self):\n",
    "        \"\"\"显示游戏结束信息\"\"\"\n",
    "        self.is_running = False\n",
    "        self.timer_id = None\n",
    "\n",
    "        self.canvas.create_rectangle(\n",
    "            120,\n",
    "            130,\n",
    "            WINDOW_WIDTH - 120,\n",
    "            WINDOW_HEIGHT - 130,\n",
    "            fill=\"black\",\n",
    "            outline=\"white\",\n",
    "            width=2\n",
    "        )\n",
    "\n",
    "        self.canvas.create_text(\n",
    "            WINDOW_WIDTH // 2,\n",
    "            WINDOW_HEIGHT // 2 - 35,\n",
    "            text=\"游戏结束\",\n",
    "            fill=\"red\",\n",
    "            font=(\"Microsoft YaHei\", 28, \"bold\")\n",
    "        )\n",
    "\n",
    "        self.canvas.create_text(\n",
    "            WINDOW_WIDTH // 2,\n",
    "            WINDOW_HEIGHT // 2 + 5,\n",
    "            text=f\"最终得分：{self.score}\",\n",
    "            fill=\"white\",\n",
    "            font=(\"Microsoft YaHei\", 18)\n",
    "        )\n",
    "\n",
    "        self.canvas.create_text(\n",
    "            WINDOW_WIDTH // 2,\n",
    "            WINDOW_HEIGHT // 2 + 40,\n",
    "            text=\"按 Enter 键重新开始\",\n",
    "            fill=\"yellow\",\n",
    "            font=(\"Microsoft YaHei\", 14)\n",
    "        )\n",
    "\n",
    "\n",
    "# =========================\n",
    "# 启动游戏\n",
    "# =========================\n",
    "root = tk.Tk()\n",
    "game = SnakeGame(root)\n",
    "root.mainloop()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eee38261",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
