Upload 132 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +2 -0
- 01_tkinter基础知识.ipynb +0 -0
- 02_tkinter实战:记事本软件开发.ipynb +234 -0
- 03_tkinter实战:开发画图软件.ipynb +282 -0
- 04_Pygame基础知识.ipynb +0 -0
- 05_Pygame实战:坦克大战游戏.ipynb +1124 -0
- 05_Pygame实战:坦克大战游戏.py +760 -0
- 06_PyQt5控件.ipynb +3 -0
- 06_PyQt6-PySide6.ipynb +3 -0
- 06_Pygame实战:AI贪吃蛇.ipynb +942 -0
- data/QObject.qss +18 -0
- data/style.qss +96 -0
- data/xxx.png +0 -0
- data//344/272/213/344/273/266/346/234/272/345/210/266/345/233/276/350/247/243.png +0 -0
- images/.DS_Store +0 -0
- images/Bold.png +0 -0
- images/IOS.png +0 -0
- images/Italic.png +0 -0
- images/android.png +0 -0
- images/bao0.png +0 -0
- images/bao1.png +0 -0
- images/bao10.png +0 -0
- images/bao11.png +0 -0
- images/bao12.png +0 -0
- images/bao13.png +0 -0
- images/bao14.png +0 -0
- images/bao2.png +0 -0
- images/bao3.png +0 -0
- images/bao4.png +0 -0
- images/bao5.png +0 -0
- images/bao6.png +0 -0
- images/bao7.png +0 -0
- images/bao8.png +0 -0
- images/bao9.png +0 -0
- images/boy.png +0 -0
- images/cartoon1.ico +0 -0
- images/cartoon2.ico +0 -0
- images/cartoon3.ico +0 -0
- images/cartoon4.ico +0 -0
- images/cartoon5.ico +0 -0
- images/cartoon6.ico +0 -0
- images/cartoon7.ico +0 -0
- images/cartoon8.ico +0 -0
- images/close.ico +0 -0
- images/close.png +0 -0
- images/copy.png +0 -0
- images/cut.png +0 -0
- images/doc.ico +0 -0
- images/down3.png +0 -0
- images/dropdown.png +0 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
06_PyQt5控件.ipynb filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
06_PyQt6-PySide6.ipynb filter=lfs diff=lfs merge=lfs -text
|
01_tkinter基础知识.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
02_tkinter实战:记事本软件开发.ipynb
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"id": "583a0ea6",
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"source": [
|
| 8 |
+
"## 开发记事本软件"
|
| 9 |
+
]
|
| 10 |
+
},
|
| 11 |
+
{
|
| 12 |
+
"cell_type": "code",
|
| 13 |
+
"execution_count": 1,
|
| 14 |
+
"id": "d5ea2318",
|
| 15 |
+
"metadata": {
|
| 16 |
+
"ExecuteTime": {
|
| 17 |
+
"end_time": "2023-10-05T06:41:22.135176Z",
|
| 18 |
+
"start_time": "2023-10-05T06:40:53.213945Z"
|
| 19 |
+
}
|
| 20 |
+
},
|
| 21 |
+
"outputs": [
|
| 22 |
+
{
|
| 23 |
+
"name": "stderr",
|
| 24 |
+
"output_type": "stream",
|
| 25 |
+
"text": [
|
| 26 |
+
"2023-10-05 14:40:56.137 python[83674:5585746] +[CATransaction synchronize] called within transaction\n"
|
| 27 |
+
]
|
| 28 |
+
}
|
| 29 |
+
],
|
| 30 |
+
"source": [
|
| 31 |
+
"\"\"\"开发记事本软件\"\"\"\n",
|
| 32 |
+
"\n",
|
| 33 |
+
"from tkinter.filedialog import *\n",
|
| 34 |
+
"from tkinter.colorchooser import *\n",
|
| 35 |
+
"from tkinter import *\n",
|
| 36 |
+
"\n",
|
| 37 |
+
"class Application(Frame):\n",
|
| 38 |
+
"\n",
|
| 39 |
+
" def __init__(self, master=None):\n",
|
| 40 |
+
" super().__init__(master)\n",
|
| 41 |
+
" self.master = master\n",
|
| 42 |
+
"\n",
|
| 43 |
+
" # textpad 表示 Text文本框对象\n",
|
| 44 |
+
" self.textpad = None\n",
|
| 45 |
+
"\n",
|
| 46 |
+
" # 布局app\n",
|
| 47 |
+
" self.pack()\n",
|
| 48 |
+
"\n",
|
| 49 |
+
" # 为app 添加组件\n",
|
| 50 |
+
" self.createWidget()\n",
|
| 51 |
+
"\n",
|
| 52 |
+
" def createWidget(self):\n",
|
| 53 |
+
" # 创建主菜单栏\n",
|
| 54 |
+
" menubar = Menu(root)\n",
|
| 55 |
+
"\n",
|
| 56 |
+
" # 创建子菜单\n",
|
| 57 |
+
" menuFile = Menu(menubar)\n",
|
| 58 |
+
" menuEdit = Menu(menubar)\n",
|
| 59 |
+
" menuHelp = Menu(menubar)\n",
|
| 60 |
+
"\n",
|
| 61 |
+
" # 将子菜单加入到主菜单栏\n",
|
| 62 |
+
" menubar.add_cascade(label=\"文件(F)\", menu=menuFile)\n",
|
| 63 |
+
" menubar.add_cascade(label=\"编辑(E)\", menu=menuEdit)\n",
|
| 64 |
+
" menubar.add_cascade(label=\"帮助(H)\", menu=menuHelp)\n",
|
| 65 |
+
"\n",
|
| 66 |
+
" # 添加菜单项\n",
|
| 67 |
+
" menuFile.add_command(\n",
|
| 68 |
+
" label=\"新建\", accelerator=\"ctrl+n\", command=self.newfile)\n",
|
| 69 |
+
" menuFile.add_command(\n",
|
| 70 |
+
" label=\"打开\", accelerator=\"ctrl+o\", command=self.openfile)\n",
|
| 71 |
+
" menuFile.add_command(\n",
|
| 72 |
+
" label=\"保存\", accelerator=\"ctrl+s\", command=self.savefile)\n",
|
| 73 |
+
" menuFile.add_separator() # 添加分割线\n",
|
| 74 |
+
" menuFile.add_command(\n",
|
| 75 |
+
" label=\"退出\", accelerator=\"ctrl+q\", command=self.exit)\n",
|
| 76 |
+
"\n",
|
| 77 |
+
" # 将主菜单栏 添加到根窗口\n",
|
| 78 |
+
" root[\"menu\"] = menubar\n",
|
| 79 |
+
"\n",
|
| 80 |
+
" # 增加快捷键的处理\n",
|
| 81 |
+
" root.bind(\"<Control-n>\", lambda event: self.newfile())\n",
|
| 82 |
+
" root.bind(\"<Control-o>\", lambda event: self.openfile())\n",
|
| 83 |
+
" root.bind(\"<Control-s>\", lambda event: self.savefile())\n",
|
| 84 |
+
" root.bind(\"<Control-q>\", lambda event: self.exit())\n",
|
| 85 |
+
"\n",
|
| 86 |
+
" # 创建 Text 多行文本框\n",
|
| 87 |
+
" self.textpad = Text(root, width=50, height=30)\n",
|
| 88 |
+
" self.textpad.pack() # 布局到 app中\n",
|
| 89 |
+
"\n",
|
| 90 |
+
" # 创建上下菜单,并添加菜单项\n",
|
| 91 |
+
" self.contextMenu = Menu(root)\n",
|
| 92 |
+
" self.contextMenu.add_command(label=\"背景颜色\", command=self.openAskColor)\n",
|
| 93 |
+
"\n",
|
| 94 |
+
" # 为右键绑定事件\n",
|
| 95 |
+
" root.bind(\"<Button-2>\", self.createContextMenu)\n",
|
| 96 |
+
"\n",
|
| 97 |
+
" def newfile(self):\n",
|
| 98 |
+
" \"\"\"新建文件\"\"\"\n",
|
| 99 |
+
"\n",
|
| 100 |
+
" # 把 text控件中所有的内容清空\n",
|
| 101 |
+
" self.textpad.delete(\"1.0\", \"end\")\n",
|
| 102 |
+
"\n",
|
| 103 |
+
" # 打开 创建文件对话框\n",
|
| 104 |
+
" self.filename = asksaveasfilename(title=\"另存为\",\n",
|
| 105 |
+
" initialfile=\"未命名.txt\", # 文件默认名\n",
|
| 106 |
+
" filetypes=[(\"文本文档\", \"*.txt\")],\n",
|
| 107 |
+
" defaultextension=\".txt\") # 默认文件类型\n",
|
| 108 |
+
" # 保存 新建的文件\n",
|
| 109 |
+
" self.savefile()\n",
|
| 110 |
+
"\n",
|
| 111 |
+
" def openfile(self):\n",
|
| 112 |
+
" \"\"\"打开文件\"\"\"\n",
|
| 113 |
+
"\n",
|
| 114 |
+
" # 把text控件中所有的内容清空\n",
|
| 115 |
+
" self.textpad.delete(\"1.0\", \"end\")\n",
|
| 116 |
+
"\n",
|
| 117 |
+
" # 创建文件对话框\n",
|
| 118 |
+
" with askopenfile(title=\"打开文本文件\") as f:\n",
|
| 119 |
+
"\n",
|
| 120 |
+
" # 读取文件内容\n",
|
| 121 |
+
" self.textpad.insert(INSERT, f.read())\n",
|
| 122 |
+
" self.filename = f.name\n",
|
| 123 |
+
"\n",
|
| 124 |
+
" def savefile(self):\n",
|
| 125 |
+
" \"\"\"将文本框的信息 保存到文件中\"\"\"\n",
|
| 126 |
+
" with open(self.filename, \"w\") as f:\n",
|
| 127 |
+
" c = self.textpad.get(1.0, END)\n",
|
| 128 |
+
" f.write(c)\n",
|
| 129 |
+
"\n",
|
| 130 |
+
" def exit(self):\n",
|
| 131 |
+
" root.quit()\n",
|
| 132 |
+
"\n",
|
| 133 |
+
" def openAskColor(self):\n",
|
| 134 |
+
" # 打开颜色选择框\n",
|
| 135 |
+
" s1 = askcolor(color=\"red\", title=\"选择背景色\")\n",
|
| 136 |
+
"\n",
|
| 137 |
+
" # 修改文本框的背景色\n",
|
| 138 |
+
" self.textpad.config(bg=s1[1])\n",
|
| 139 |
+
"\n",
|
| 140 |
+
" def createContextMenu(self, event):\n",
|
| 141 |
+
" # 菜单在鼠标右键单击的坐标处显示\n",
|
| 142 |
+
" self.contextMenu.post(event.x_root, event.y_root)\n",
|
| 143 |
+
"\n",
|
| 144 |
+
"\n",
|
| 145 |
+
"if __name__ == '__main__':\n",
|
| 146 |
+
" root = Tk()\n",
|
| 147 |
+
" root.geometry(\"450x300+200+300\")\n",
|
| 148 |
+
" root.title(\"简易记事本\")\n",
|
| 149 |
+
" app = Application(master=root)\n",
|
| 150 |
+
" root.mainloop()"
|
| 151 |
+
]
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
"cell_type": "markdown",
|
| 155 |
+
"id": "992ea581",
|
| 156 |
+
"metadata": {},
|
| 157 |
+
"source": [
|
| 158 |
+
"## 将 python 程序打包成 exe 文件\n",
|
| 159 |
+
"\n",
|
| 160 |
+
"\n",
|
| 161 |
+
"我们可以使用 pyinstaller 模块实现将 python 项目打包成 exe 文件。\n",
|
| 162 |
+
"\n",
|
| 163 |
+
"操作步骤如下: \n",
|
| 164 |
+
"\n",
|
| 165 |
+
"1. 安装 pyinstaller 模块\n",
|
| 166 |
+
" - 在 pycharm 中操作:file-->setting-->Project:xxx -->Project interpretor,再点 击+即可。\n",
|
| 167 |
+
"\n",
|
| 168 |
+
"\n",
|
| 169 |
+
"2. 在 pycharm 的 Terminal 终端输入如下命令: pyinstaller -F xxxx.py\n",
|
| 170 |
+
" - 【注】相关参数如下:\n",
|
| 171 |
+
" - --icon=图标路径 (pyinstaller -F --icon=my.ico XXXX.py)\n",
|
| 172 |
+
" - -F 打包成一个 exe 文件\n",
|
| 173 |
+
" - -w 使用窗口,无控制台\n",
|
| 174 |
+
" - -c 使用控制台,无窗口\n",
|
| 175 |
+
" - -D 创建一个目录,里面包含 exe 以及其他一些依赖性文件\n",
|
| 176 |
+
"\n",
|
| 177 |
+
"\n",
|
| 178 |
+
"3. 在项目的 dist 目录下可以看到生成了 exe 文件,直接在windows 系统中使用即可。\n",
|
| 179 |
+
"\n",
|
| 180 |
+
"\n",
|
| 181 |
+
"【注】exe 文件本质是将 python 解释器和程序打包到了一起,这样我们执行程序时就不用管 windows 系统是不是有 python 解释器。\n",
|
| 182 |
+
"\n",
|
| 183 |
+
"【注】pyinstaller 目前只支持 python3.6。如果你是 python3.7 会执行失败。"
|
| 184 |
+
]
|
| 185 |
+
},
|
| 186 |
+
{
|
| 187 |
+
"cell_type": "code",
|
| 188 |
+
"execution_count": null,
|
| 189 |
+
"id": "6e64e519",
|
| 190 |
+
"metadata": {},
|
| 191 |
+
"outputs": [],
|
| 192 |
+
"source": []
|
| 193 |
+
}
|
| 194 |
+
],
|
| 195 |
+
"metadata": {
|
| 196 |
+
"kernelspec": {
|
| 197 |
+
"display_name": "Python 3 (ipykernel)",
|
| 198 |
+
"language": "python",
|
| 199 |
+
"name": "python3"
|
| 200 |
+
},
|
| 201 |
+
"language_info": {
|
| 202 |
+
"codemirror_mode": {
|
| 203 |
+
"name": "ipython",
|
| 204 |
+
"version": 3
|
| 205 |
+
},
|
| 206 |
+
"file_extension": ".py",
|
| 207 |
+
"mimetype": "text/x-python",
|
| 208 |
+
"name": "python",
|
| 209 |
+
"nbconvert_exporter": "python",
|
| 210 |
+
"pygments_lexer": "ipython3",
|
| 211 |
+
"version": "3.9.12"
|
| 212 |
+
},
|
| 213 |
+
"toc": {
|
| 214 |
+
"base_numbering": 1,
|
| 215 |
+
"nav_menu": {},
|
| 216 |
+
"number_sections": true,
|
| 217 |
+
"sideBar": true,
|
| 218 |
+
"skip_h1_title": false,
|
| 219 |
+
"title_cell": "Table of Contents",
|
| 220 |
+
"title_sidebar": "Contents",
|
| 221 |
+
"toc_cell": false,
|
| 222 |
+
"toc_position": {
|
| 223 |
+
"height": "calc(100% - 180px)",
|
| 224 |
+
"left": "10px",
|
| 225 |
+
"top": "150px",
|
| 226 |
+
"width": "248.1875px"
|
| 227 |
+
},
|
| 228 |
+
"toc_section_display": true,
|
| 229 |
+
"toc_window_display": true
|
| 230 |
+
}
|
| 231 |
+
},
|
| 232 |
+
"nbformat": 4,
|
| 233 |
+
"nbformat_minor": 5
|
| 234 |
+
}
|
03_tkinter实战:开发画图软件.ipynb
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": 5,
|
| 6 |
+
"id": "13cd1000",
|
| 7 |
+
"metadata": {
|
| 8 |
+
"ExecuteTime": {
|
| 9 |
+
"end_time": "2023-10-05T07:16:15.649473Z",
|
| 10 |
+
"start_time": "2023-10-05T07:16:12.271320Z"
|
| 11 |
+
}
|
| 12 |
+
},
|
| 13 |
+
"outputs": [],
|
| 14 |
+
"source": [
|
| 15 |
+
"\"\"\"开发画图软件的菜单\"\"\"\n",
|
| 16 |
+
"\n",
|
| 17 |
+
"from tkinter.filedialog import *\n",
|
| 18 |
+
"from tkinter.colorchooser import *\n",
|
| 19 |
+
"from tkinter import *\n",
|
| 20 |
+
"\n",
|
| 21 |
+
"# 根窗口的宽度和高度\n",
|
| 22 |
+
"win_width = 900\n",
|
| 23 |
+
"win_height = 450\n",
|
| 24 |
+
"\n",
|
| 25 |
+
"\n",
|
| 26 |
+
"class Application(Frame):\n",
|
| 27 |
+
"\n",
|
| 28 |
+
" def __init__(self, master=None, # 设置父组件\n",
|
| 29 |
+
" bgcolor=\"#000000\"): # 设置背景色\n",
|
| 30 |
+
" super().__init__(master)\n",
|
| 31 |
+
"\n",
|
| 32 |
+
" self.master = master # app的父组件\n",
|
| 33 |
+
" self.bgcolor = bgcolor # 背景色\n",
|
| 34 |
+
" self.fgcolor = \"#ff0000\" # 前景色\n",
|
| 35 |
+
"\n",
|
| 36 |
+
" # 记录鼠标坐标\n",
|
| 37 |
+
" self.x = 0\n",
|
| 38 |
+
" self.y = 0\n",
|
| 39 |
+
"\n",
|
| 40 |
+
" # 是否开始画画\n",
|
| 41 |
+
" self.startDrawFlag = False\n",
|
| 42 |
+
"\n",
|
| 43 |
+
" # 记录最后绘制图形\n",
|
| 44 |
+
" self.lastDraw = 0\n",
|
| 45 |
+
"\n",
|
| 46 |
+
" # 绘图区canvas对象\n",
|
| 47 |
+
" self.drawpad = None\n",
|
| 48 |
+
"\n",
|
| 49 |
+
" # 部署app\n",
|
| 50 |
+
" self.pack()\n",
|
| 51 |
+
"\n",
|
| 52 |
+
" # 为app添加组件\n",
|
| 53 |
+
" self.createWidget()\n",
|
| 54 |
+
"\n",
|
| 55 |
+
" def createWidget(self):\n",
|
| 56 |
+
" # 绘图区:创建画布\n",
|
| 57 |
+
" self.drawpad = Canvas(root, width=win_width,\n",
|
| 58 |
+
" height=win_height*0.8, bg=self.bgcolor)\n",
|
| 59 |
+
" self.drawpad.pack()\n",
|
| 60 |
+
"\n",
|
| 61 |
+
" # 创建操作按钮\n",
|
| 62 |
+
" # 开始按钮\n",
|
| 63 |
+
" btn_start = Button(root, text=\"开始\", name=\"start\")\n",
|
| 64 |
+
" btn_start.pack(side=\"left\", padx=\"10\")\n",
|
| 65 |
+
"\n",
|
| 66 |
+
" # 画笔按钮\n",
|
| 67 |
+
" btn_pen = Button(root, text=\"画笔\", name=\"pen\")\n",
|
| 68 |
+
" btn_pen.pack(side=\"left\", padx=\"10\")\n",
|
| 69 |
+
"\n",
|
| 70 |
+
" # 画矩形按钮\n",
|
| 71 |
+
" btn_rect = Button(root, text=\"画矩形\", name=\"rect\")\n",
|
| 72 |
+
" btn_rect.pack(side=\"left\", padx=\"10\")\n",
|
| 73 |
+
"\n",
|
| 74 |
+
" # 清屏按钮\n",
|
| 75 |
+
" btn_clear = Button(root, text=\"清屏\", name=\"clear\")\n",
|
| 76 |
+
" btn_clear.pack(side=\"left\", padx=\"10\")\n",
|
| 77 |
+
"\n",
|
| 78 |
+
" # 橡皮擦按钮\n",
|
| 79 |
+
" btn_eraser = Button(root, text=\"橡皮擦\", name=\"eraser\")\n",
|
| 80 |
+
" btn_eraser.pack(side=\"left\", padx=\"10\")\n",
|
| 81 |
+
"\n",
|
| 82 |
+
" # 画直线按钮\n",
|
| 83 |
+
" btn_line = Button(root, text=\"直线\", name=\"line\")\n",
|
| 84 |
+
" btn_line.pack(side=\"left\", padx=\"10\")\n",
|
| 85 |
+
"\n",
|
| 86 |
+
" # 画箭头按钮\n",
|
| 87 |
+
" btn_lineArrow = Button(root, text=\"直线(箭头)\", name=\"lineArrow\")\n",
|
| 88 |
+
" btn_lineArrow.pack(side=\"left\", padx=\"10\")\n",
|
| 89 |
+
"\n",
|
| 90 |
+
" # 颜色按钮\n",
|
| 91 |
+
" btn_color = Button(root, text=\"颜色\", name=\"chooseColor\")\n",
|
| 92 |
+
" btn_color.pack(side=\"left\", padx=\"10\")\n",
|
| 93 |
+
"\n",
|
| 94 |
+
" # 给所有按钮 绑定鼠标点击事件\n",
|
| 95 |
+
" btn_pen.bind_class(\"Button\", \"<1>\", self.myEventManager)\n",
|
| 96 |
+
"\n",
|
| 97 |
+
" # 为右键绑定事件 -- 加载上下文菜单\n",
|
| 98 |
+
" root.bind(\"<Button-2>\", self.createContextMenu)\n",
|
| 99 |
+
"\n",
|
| 100 |
+
" # 画布绑定 鼠标拖动事件,默认使用画笔画画\n",
|
| 101 |
+
" self.drawpad.bind(\"<B1-Motion>\", self.myDrawPen)\n",
|
| 102 |
+
" self.drawpad.bind(\"<ButtonRelease-1>\", self.stopDraw)\n",
|
| 103 |
+
"\n",
|
| 104 |
+
" # 增加修改颜色的 快捷键\n",
|
| 105 |
+
" root.bind(\"<KeyPress-r>\", self.kuaijiejian)\n",
|
| 106 |
+
" root.bind(\"<KeyPress-g>\", self.kuaijiejian)\n",
|
| 107 |
+
" root.bind(\"<KeyPress-y>\", self.kuaijiejian)\n",
|
| 108 |
+
"\n",
|
| 109 |
+
" def myEventManager(self, event):\n",
|
| 110 |
+
"\n",
|
| 111 |
+
" # 获取组件的名字\n",
|
| 112 |
+
" name = event.widget.winfo_name()\n",
|
| 113 |
+
"\n",
|
| 114 |
+
" # 一松开鼠标,结束上一阶段绘画\n",
|
| 115 |
+
" self.drawpad.bind(\"<ButtonRelease-1>\", self.stopDraw)\n",
|
| 116 |
+
"\n",
|
| 117 |
+
" # 根据 按下按钮的不同,执行不同的函数\n",
|
| 118 |
+
" if name == \"rect\":\n",
|
| 119 |
+
" self.drawpad.bind(\"<B1-Motion>\", self.myDrawRect)\n",
|
| 120 |
+
"\n",
|
| 121 |
+
" elif name == \"clear\":\n",
|
| 122 |
+
" self.drawpad.delete(\"all\")\n",
|
| 123 |
+
"\n",
|
| 124 |
+
" elif name == \"eraser\":\n",
|
| 125 |
+
" self.drawpad.bind(\"<B1-Motion>\", self.myEraser)\n",
|
| 126 |
+
"\n",
|
| 127 |
+
" elif name == \"line\":\n",
|
| 128 |
+
" self.drawpad.bind(\"<B1-Motion>\", self.myLine)\n",
|
| 129 |
+
"\n",
|
| 130 |
+
" elif name == \"lineArrow\":\n",
|
| 131 |
+
" self.drawpad.bind(\"<B1-Motion>\", self.myLineArrow)\n",
|
| 132 |
+
"\n",
|
| 133 |
+
" elif name == \"chooseColor\":\n",
|
| 134 |
+
" # 创建颜色选择框\n",
|
| 135 |
+
" c = askcolor(color=self.fgcolor, title=\"选择画笔颜色\")\n",
|
| 136 |
+
" self.fgcolor = c[1]\n",
|
| 137 |
+
"\n",
|
| 138 |
+
" else: # 画笔\n",
|
| 139 |
+
" self.drawpad.bind(\"<B1-Motion>\", self.myDrawPen)\n",
|
| 140 |
+
"\n",
|
| 141 |
+
" def createContextMenu(self, event):\n",
|
| 142 |
+
" # 菜单在鼠标右键单击的坐标处显示\n",
|
| 143 |
+
" self.contextMenu.post(event.x_root, event.y_root)\n",
|
| 144 |
+
"\n",
|
| 145 |
+
" def myDrawPen(self, event):\n",
|
| 146 |
+
" \"\"\"画笔\"\"\"\n",
|
| 147 |
+
" \n",
|
| 148 |
+
" # 记录鼠标按下时的坐标\n",
|
| 149 |
+
" if not self.startDrawFlag:\n",
|
| 150 |
+
" self.startDrawFlag = True\n",
|
| 151 |
+
" self.x = event.x\n",
|
| 152 |
+
" self.y = event.y\n",
|
| 153 |
+
" \n",
|
| 154 |
+
" # 不停地绘制小矩形\n",
|
| 155 |
+
" self.lastDraw = self.drawpad.create_line(\n",
|
| 156 |
+
" self.x, self.y, event.x, event.y, fill=self.fgcolor)\n",
|
| 157 |
+
" self.x = event.x\n",
|
| 158 |
+
" self.y = event.y\n",
|
| 159 |
+
"\n",
|
| 160 |
+
" def stopDraw(self, event):\n",
|
| 161 |
+
" \"\"\"结束上一阶段的绘画,开启下一阶段的绘画\"\"\"\n",
|
| 162 |
+
" self.startDrawFlag = False\n",
|
| 163 |
+
" self.lastDraw = 0\n",
|
| 164 |
+
"\n",
|
| 165 |
+
" def myDrawRect(self, event):\n",
|
| 166 |
+
" \"\"\"绘制矩形\"\"\"\n",
|
| 167 |
+
"\n",
|
| 168 |
+
" # 鼠标拖动时,会不停地绘制矩形,我们只希望保留最后一个矩形\n",
|
| 169 |
+
" self.drawpad.delete(self.lastDraw)\n",
|
| 170 |
+
"\n",
|
| 171 |
+
" # 鼠标刚按下,记录此时的坐标\n",
|
| 172 |
+
" if not self.startDrawFlag:\n",
|
| 173 |
+
" self.startDrawFlag = True\n",
|
| 174 |
+
" self.x = event.x\n",
|
| 175 |
+
" self.y = event.y\n",
|
| 176 |
+
"\n",
|
| 177 |
+
" # 绘制矩形\n",
|
| 178 |
+
" self.lastDraw = self.drawpad.create_rectangle(\n",
|
| 179 |
+
" self.x, self.y, event.x, event.y, outline=self.fgcolor)\n",
|
| 180 |
+
"\n",
|
| 181 |
+
" def myEraser(self, event):\n",
|
| 182 |
+
" \"\"\"橡皮擦是一个小矩形,矩形内进行背景色填充\"\"\"\n",
|
| 183 |
+
" if not self.startDrawFlag:\n",
|
| 184 |
+
" self.startDrawFlag = True\n",
|
| 185 |
+
"\n",
|
| 186 |
+
" self.drawpad.create_rectangle(event.x - 4, event.y - 4, event.x + 4, event.y + 4,\n",
|
| 187 |
+
" outline=self.bgcolor, fill=self.bgcolor)\n",
|
| 188 |
+
"\n",
|
| 189 |
+
" def myLine(self, event):\n",
|
| 190 |
+
" \"\"\"绘制直线\"\"\"\n",
|
| 191 |
+
" \n",
|
| 192 |
+
" # 鼠标拖动时,会不停地绘制直线,我们只希望保留最后一个\n",
|
| 193 |
+
" self.drawpad.delete(self.lastDraw)\n",
|
| 194 |
+
"\n",
|
| 195 |
+
" # 按下鼠标时,记录鼠标位置\n",
|
| 196 |
+
" if not self.startDrawFlag:\n",
|
| 197 |
+
" self.startDrawFlag = True\n",
|
| 198 |
+
" self.x = event.x\n",
|
| 199 |
+
" self.y = event.y\n",
|
| 200 |
+
"\n",
|
| 201 |
+
" # 绘制直线\n",
|
| 202 |
+
" self.lastDraw = self.drawpad.create_line(self.x, self.y, event.x, event.y,\n",
|
| 203 |
+
" fill=self.fgcolor)\n",
|
| 204 |
+
"\n",
|
| 205 |
+
" def myLineArrow(self, event):\n",
|
| 206 |
+
" \"\"\"绘制箭头\"\"\"\n",
|
| 207 |
+
" \n",
|
| 208 |
+
" # 鼠标拖动时,会不停地绘制箭头,我们只希望保留最后一个\n",
|
| 209 |
+
" self.drawpad.delete(self.lastDraw)\n",
|
| 210 |
+
"\n",
|
| 211 |
+
" # 按下鼠标时,记录鼠标位置\n",
|
| 212 |
+
" if not self.startDrawFlag:\n",
|
| 213 |
+
" self.startDrawFlag = True\n",
|
| 214 |
+
" self.x = event.x\n",
|
| 215 |
+
" self.y = event.y\n",
|
| 216 |
+
"\n",
|
| 217 |
+
" # 绘制箭头\n",
|
| 218 |
+
" self.lastDraw = self.drawpad.create_line(self.x, self.y, event.x, event.y,\n",
|
| 219 |
+
" fill=self.fgcolor, arrow=LAST)\n",
|
| 220 |
+
"\n",
|
| 221 |
+
" # 处理快捷键\n",
|
| 222 |
+
" def kuaijiejian(self, event):\n",
|
| 223 |
+
" if event.char == \"r\":\n",
|
| 224 |
+
" self.fgcolor = \"#ff0000\"\n",
|
| 225 |
+
" elif event.char == \"g\":\n",
|
| 226 |
+
" self.fgcolor = \"#00ff00\"\n",
|
| 227 |
+
" elif event.char == \"y\":\n",
|
| 228 |
+
" self.fgcolor = \"#ffff00\"\n",
|
| 229 |
+
"\n",
|
| 230 |
+
"\n",
|
| 231 |
+
"if __name__ == '__main__':\n",
|
| 232 |
+
" \n",
|
| 233 |
+
" # 设置根窗口\n",
|
| 234 |
+
" root = Tk()\n",
|
| 235 |
+
" root.geometry(str(win_width)+\"x\"+str(win_height)+\"+400+400\")\n",
|
| 236 |
+
" root.title(\"画图软件\")\n",
|
| 237 |
+
" \n",
|
| 238 |
+
" app = Application(master=root)\n",
|
| 239 |
+
" root.mainloop()"
|
| 240 |
+
]
|
| 241 |
+
}
|
| 242 |
+
],
|
| 243 |
+
"metadata": {
|
| 244 |
+
"kernelspec": {
|
| 245 |
+
"display_name": "Python 3 (ipykernel)",
|
| 246 |
+
"language": "python",
|
| 247 |
+
"name": "python3"
|
| 248 |
+
},
|
| 249 |
+
"language_info": {
|
| 250 |
+
"codemirror_mode": {
|
| 251 |
+
"name": "ipython",
|
| 252 |
+
"version": 3
|
| 253 |
+
},
|
| 254 |
+
"file_extension": ".py",
|
| 255 |
+
"mimetype": "text/x-python",
|
| 256 |
+
"name": "python",
|
| 257 |
+
"nbconvert_exporter": "python",
|
| 258 |
+
"pygments_lexer": "ipython3",
|
| 259 |
+
"version": "3.9.12"
|
| 260 |
+
},
|
| 261 |
+
"toc": {
|
| 262 |
+
"base_numbering": 1,
|
| 263 |
+
"nav_menu": {},
|
| 264 |
+
"number_sections": true,
|
| 265 |
+
"sideBar": true,
|
| 266 |
+
"skip_h1_title": false,
|
| 267 |
+
"title_cell": "Table of Contents",
|
| 268 |
+
"title_sidebar": "Contents",
|
| 269 |
+
"toc_cell": false,
|
| 270 |
+
"toc_position": {
|
| 271 |
+
"height": "calc(100% - 180px)",
|
| 272 |
+
"left": "10px",
|
| 273 |
+
"top": "150px",
|
| 274 |
+
"width": "248.1875px"
|
| 275 |
+
},
|
| 276 |
+
"toc_section_display": true,
|
| 277 |
+
"toc_window_display": true
|
| 278 |
+
}
|
| 279 |
+
},
|
| 280 |
+
"nbformat": 4,
|
| 281 |
+
"nbformat_minor": 5
|
| 282 |
+
}
|
04_Pygame基础知识.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
05_Pygame实战:坦克大战游戏.ipynb
ADDED
|
@@ -0,0 +1,1124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"id": "ecf4b439",
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"source": [
|
| 8 |
+
"## 导包"
|
| 9 |
+
]
|
| 10 |
+
},
|
| 11 |
+
{
|
| 12 |
+
"cell_type": "code",
|
| 13 |
+
"execution_count": 1,
|
| 14 |
+
"id": "9ebb63d1",
|
| 15 |
+
"metadata": {
|
| 16 |
+
"ExecuteTime": {
|
| 17 |
+
"end_time": "2023-10-05T17:25:00.137183Z",
|
| 18 |
+
"start_time": "2023-10-05T17:25:00.017474Z"
|
| 19 |
+
}
|
| 20 |
+
},
|
| 21 |
+
"outputs": [
|
| 22 |
+
{
|
| 23 |
+
"name": "stdout",
|
| 24 |
+
"output_type": "stream",
|
| 25 |
+
"text": [
|
| 26 |
+
"pygame 2.1.0 (SDL 2.0.16, Python 3.9.12)\n",
|
| 27 |
+
"Hello from the pygame community. https://www.pygame.org/contribute.html\n"
|
| 28 |
+
]
|
| 29 |
+
}
|
| 30 |
+
],
|
| 31 |
+
"source": [
|
| 32 |
+
"import pygame\n",
|
| 33 |
+
"import time\n",
|
| 34 |
+
"import random\n",
|
| 35 |
+
"from pygame.sprite import Sprite"
|
| 36 |
+
]
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"cell_type": "markdown",
|
| 40 |
+
"id": "9f539676",
|
| 41 |
+
"metadata": {},
|
| 42 |
+
"source": [
|
| 43 |
+
"## 定义全局变量"
|
| 44 |
+
]
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"cell_type": "code",
|
| 48 |
+
"execution_count": 2,
|
| 49 |
+
"id": "488fc023",
|
| 50 |
+
"metadata": {
|
| 51 |
+
"ExecuteTime": {
|
| 52 |
+
"end_time": "2023-10-05T17:25:00.174212Z",
|
| 53 |
+
"start_time": "2023-10-05T17:25:00.146175Z"
|
| 54 |
+
}
|
| 55 |
+
},
|
| 56 |
+
"outputs": [],
|
| 57 |
+
"source": [
|
| 58 |
+
"SCREEN_WIDTH = 800\n",
|
| 59 |
+
"SCREEN_HEIGHT = 500\n",
|
| 60 |
+
"BG_COLOR = pygame.Color(0, 0, 0)\n",
|
| 61 |
+
"TEXT_COLOR = pygame.Color(255, 0, 0)"
|
| 62 |
+
]
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"cell_type": "markdown",
|
| 66 |
+
"id": "eb87a38f",
|
| 67 |
+
"metadata": {},
|
| 68 |
+
"source": [
|
| 69 |
+
"## 基类"
|
| 70 |
+
]
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"cell_type": "code",
|
| 74 |
+
"execution_count": 3,
|
| 75 |
+
"id": "5ce76157",
|
| 76 |
+
"metadata": {
|
| 77 |
+
"ExecuteTime": {
|
| 78 |
+
"end_time": "2023-10-05T17:25:00.199049Z",
|
| 79 |
+
"start_time": "2023-10-05T17:25:00.192539Z"
|
| 80 |
+
}
|
| 81 |
+
},
|
| 82 |
+
"outputs": [],
|
| 83 |
+
"source": [
|
| 84 |
+
"# 定义一个基类\n",
|
| 85 |
+
"class BaseItem(Sprite):\n",
|
| 86 |
+
" def __init__(self, color, width, height):\n",
|
| 87 |
+
" pygame.sprite.Sprite.__init__(self)"
|
| 88 |
+
]
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"cell_type": "markdown",
|
| 92 |
+
"id": "e6d9cfc3",
|
| 93 |
+
"metadata": {},
|
| 94 |
+
"source": [
|
| 95 |
+
"## 坦克类"
|
| 96 |
+
]
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"cell_type": "code",
|
| 100 |
+
"execution_count": 4,
|
| 101 |
+
"id": "15a2dd18",
|
| 102 |
+
"metadata": {
|
| 103 |
+
"ExecuteTime": {
|
| 104 |
+
"end_time": "2023-10-05T17:25:00.225216Z",
|
| 105 |
+
"start_time": "2023-10-05T17:25:00.207309Z"
|
| 106 |
+
}
|
| 107 |
+
},
|
| 108 |
+
"outputs": [],
|
| 109 |
+
"source": [
|
| 110 |
+
"class Tank(BaseItem):\n",
|
| 111 |
+
" def __init__(self, left, top):\n",
|
| 112 |
+
" \"\"\"初始化方法:添加距离左边left 距离上边top\"\"\"\n",
|
| 113 |
+
" \n",
|
| 114 |
+
" # 创建字典 -- 朝不同的方向走,坦克也不尽相同\n",
|
| 115 |
+
" self.images = {\n",
|
| 116 |
+
" 'U': pygame.image.load('img/p1tankU.gif'),\n",
|
| 117 |
+
" 'D': pygame.image.load('img/p1tankD.gif'),\n",
|
| 118 |
+
" 'L': pygame.image.load('img/p1tankL.gif'),\n",
|
| 119 |
+
" 'R': pygame.image.load('img/p1tankR.gif'),\n",
|
| 120 |
+
" }\n",
|
| 121 |
+
" \n",
|
| 122 |
+
" # 默认方向\n",
|
| 123 |
+
" self.direction = 'L'\n",
|
| 124 |
+
" \n",
|
| 125 |
+
" # 根据当前方向,获取图片\n",
|
| 126 |
+
" self.image = self.images[self.direction]\n",
|
| 127 |
+
" \n",
|
| 128 |
+
" # 根据图片,获取坦克所在区域\n",
|
| 129 |
+
" self.rect = self.image.get_rect()\n",
|
| 130 |
+
" \n",
|
| 131 |
+
" # 调整坦克所在区域\n",
|
| 132 |
+
" self.rect.left = left\n",
|
| 133 |
+
" self.rect.top = top\n",
|
| 134 |
+
" \n",
|
| 135 |
+
" # 设置速度 \n",
|
| 136 |
+
" self.speed = 5\n",
|
| 137 |
+
" \n",
|
| 138 |
+
" # 坦克移动的开关\n",
|
| 139 |
+
" self.stop = True\n",
|
| 140 |
+
" \n",
|
| 141 |
+
" # 是否活着\n",
|
| 142 |
+
" self.live = True\n",
|
| 143 |
+
" \n",
|
| 144 |
+
" # 记录坦克上一时刻的坐标\n",
|
| 145 |
+
" self.oldLeft = self.rect.left\n",
|
| 146 |
+
" self.oldTop = self.rect.top\n",
|
| 147 |
+
"\n",
|
| 148 |
+
"\n",
|
| 149 |
+
" def move(self):\n",
|
| 150 |
+
" \"\"\"移动函数\"\"\"\n",
|
| 151 |
+
" \n",
|
| 152 |
+
" # 记录坦克上一时刻的坐标\n",
|
| 153 |
+
" self.oldLeft = self.rect.left\n",
|
| 154 |
+
" self.oldTop = self.rect.top\n",
|
| 155 |
+
" \n",
|
| 156 |
+
" # 判断坦克的方向,根据一定的速度,进行移动\n",
|
| 157 |
+
" if self.direction == 'L':\n",
|
| 158 |
+
" if self.rect.left > 0:\n",
|
| 159 |
+
" self.rect.left -= self.speed\n",
|
| 160 |
+
" \n",
|
| 161 |
+
" elif self.direction == 'U':\n",
|
| 162 |
+
" if self.rect.top > 0:\n",
|
| 163 |
+
" self.rect.top -= self.speed\n",
|
| 164 |
+
" \n",
|
| 165 |
+
" elif self.direction == 'D':\n",
|
| 166 |
+
" if self.rect.top+self.rect.height < SCREEN_HEIGHT:\n",
|
| 167 |
+
" self.rect.top += self.speed\n",
|
| 168 |
+
" \n",
|
| 169 |
+
" elif self.direction == 'R':\n",
|
| 170 |
+
" if self.rect.left+self.rect.height < SCREEN_WIDTH:\n",
|
| 171 |
+
" self.rect.left += self.speed\n",
|
| 172 |
+
"\n",
|
| 173 |
+
" \n",
|
| 174 |
+
" def shot(self):\n",
|
| 175 |
+
" \"\"\"射击函数\"\"\"\n",
|
| 176 |
+
" return Bullet(self) # 返回子弹对象\n",
|
| 177 |
+
"\n",
|
| 178 |
+
" def stay(self):\n",
|
| 179 |
+
" \"\"\"暂停\"\"\"\n",
|
| 180 |
+
" self.rect.left = self.oldLeft\n",
|
| 181 |
+
" self.rect.top = self.oldTop\n",
|
| 182 |
+
" \n",
|
| 183 |
+
"\n",
|
| 184 |
+
" def hitWall(self):\n",
|
| 185 |
+
" \"\"\"撞到墙体\"\"\"\n",
|
| 186 |
+
" for wall in MainGame.wallList:\n",
|
| 187 |
+
" if pygame.sprite.collide_rect(self, wall):\n",
|
| 188 |
+
" self.stay()\n",
|
| 189 |
+
" \n",
|
| 190 |
+
"\n",
|
| 191 |
+
" def displayTank(self):\n",
|
| 192 |
+
" \"\"\"展示坦克\"\"\"\n",
|
| 193 |
+
" # 获取展示的对象\n",
|
| 194 |
+
" self.image = self.images[self.direction]\n",
|
| 195 |
+
" \n",
|
| 196 |
+
" # 调用blit方法展示\n",
|
| 197 |
+
" MainGame.window.blit(self.image, self.rect)\n",
|
| 198 |
+
"\n"
|
| 199 |
+
]
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"cell_type": "markdown",
|
| 203 |
+
"id": "873e8cdc",
|
| 204 |
+
"metadata": {},
|
| 205 |
+
"source": [
|
| 206 |
+
"## 我方坦克类"
|
| 207 |
+
]
|
| 208 |
+
},
|
| 209 |
+
{
|
| 210 |
+
"cell_type": "code",
|
| 211 |
+
"execution_count": 5,
|
| 212 |
+
"id": "e1b9c207",
|
| 213 |
+
"metadata": {
|
| 214 |
+
"ExecuteTime": {
|
| 215 |
+
"end_time": "2023-10-05T17:25:00.244806Z",
|
| 216 |
+
"start_time": "2023-10-05T17:25:00.227216Z"
|
| 217 |
+
}
|
| 218 |
+
},
|
| 219 |
+
"outputs": [],
|
| 220 |
+
"source": [
|
| 221 |
+
"# 我方坦克\n",
|
| 222 |
+
"class MyTank(Tank):\n",
|
| 223 |
+
" def __init__(self, left, top):\n",
|
| 224 |
+
" super(MyTank, self).__init__(left, top)\n",
|
| 225 |
+
"\n",
|
| 226 |
+
"\n",
|
| 227 |
+
" def myTank_hit_enemyTank(self):\n",
|
| 228 |
+
" \"\"\"撞到敌方坦克\"\"\"\n",
|
| 229 |
+
" # 循环遍历敌方坦克列表\n",
|
| 230 |
+
" for enemyTank in MainGame.enemyTankList:\n",
|
| 231 |
+
" if pygame.sprite.collide_rect(self, enemyTank):\n",
|
| 232 |
+
" # 暂停\n",
|
| 233 |
+
" self.stay()"
|
| 234 |
+
]
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"cell_type": "markdown",
|
| 238 |
+
"id": "4a2e4ee2",
|
| 239 |
+
"metadata": {},
|
| 240 |
+
"source": [
|
| 241 |
+
"## 敌方坦克类"
|
| 242 |
+
]
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"cell_type": "code",
|
| 246 |
+
"execution_count": 6,
|
| 247 |
+
"id": "bbc6b556",
|
| 248 |
+
"metadata": {
|
| 249 |
+
"ExecuteTime": {
|
| 250 |
+
"end_time": "2023-10-05T17:25:00.273074Z",
|
| 251 |
+
"start_time": "2023-10-05T17:25:00.246530Z"
|
| 252 |
+
}
|
| 253 |
+
},
|
| 254 |
+
"outputs": [],
|
| 255 |
+
"source": [
|
| 256 |
+
"# 敌方坦克\n",
|
| 257 |
+
"class EnemyTank(Tank):\n",
|
| 258 |
+
" def __init__(self, left, top, speed):\n",
|
| 259 |
+
" # 调用父类的初始化方法\n",
|
| 260 |
+
" super(EnemyTank, self).__init__(left, top)\n",
|
| 261 |
+
" \n",
|
| 262 |
+
" # 加载敌方坦克图片集\n",
|
| 263 |
+
" self.images = {\n",
|
| 264 |
+
" 'U': pygame.image.load('img/enemy1U.gif'),\n",
|
| 265 |
+
" 'D': pygame.image.load('img/enemy1D.gif'),\n",
|
| 266 |
+
" 'L': pygame.image.load('img/enemy1L.gif'),\n",
|
| 267 |
+
" 'R': pygame.image.load('img/enemy1R.gif')\n",
|
| 268 |
+
" }\n",
|
| 269 |
+
" \n",
|
| 270 |
+
" # 随机生成敌方坦克的方向\n",
|
| 271 |
+
" self.direction = self.randDirection()\n",
|
| 272 |
+
" \n",
|
| 273 |
+
" # 根据方向获取图片\n",
|
| 274 |
+
" self.image = self.images[self.direction]\n",
|
| 275 |
+
" \n",
|
| 276 |
+
" # 获取敌方坦克区域\n",
|
| 277 |
+
" self.rect = self.image.get_rect()\n",
|
| 278 |
+
" \n",
|
| 279 |
+
" # 更改敌方坦克位置\n",
|
| 280 |
+
" self.rect.left = left\n",
|
| 281 |
+
" self.rect.top = top\n",
|
| 282 |
+
" \n",
|
| 283 |
+
" # 速度\n",
|
| 284 |
+
" self.speed = speed\n",
|
| 285 |
+
" \n",
|
| 286 |
+
" # 移动开关键\n",
|
| 287 |
+
" self.flag = True\n",
|
| 288 |
+
" \n",
|
| 289 |
+
" # 增加一个步数变量 step -- 每移动 step步,改变一次方向\n",
|
| 290 |
+
" self.step = 60\n",
|
| 291 |
+
"\n",
|
| 292 |
+
" \n",
|
| 293 |
+
" def enemyTank_hit_myTank(self):\n",
|
| 294 |
+
" \"\"\"撞到我方坦克\"\"\"\n",
|
| 295 |
+
" if pygame.sprite.collide_rect(self, MainGame.my_tank):\n",
|
| 296 |
+
" # 停止\n",
|
| 297 |
+
" self.stay()\n",
|
| 298 |
+
" \n",
|
| 299 |
+
" def randDirection(self):\n",
|
| 300 |
+
" \"\"\"随机生成敌方坦克的方向\"\"\"\n",
|
| 301 |
+
" num = random.randint(1, 4)\n",
|
| 302 |
+
" \n",
|
| 303 |
+
" if num == 1:\n",
|
| 304 |
+
" return 'U'\n",
|
| 305 |
+
" elif num == 2:\n",
|
| 306 |
+
" return 'D'\n",
|
| 307 |
+
" elif num == 3:\n",
|
| 308 |
+
" return \"L\"\n",
|
| 309 |
+
" elif num == 4:\n",
|
| 310 |
+
" return 'R'\n",
|
| 311 |
+
"\n",
|
| 312 |
+
"\n",
|
| 313 |
+
" def randMove(self):\n",
|
| 314 |
+
" \"\"\"敌方坦克随机移动\"\"\"\n",
|
| 315 |
+
" \n",
|
| 316 |
+
" if self.step <= 0:\n",
|
| 317 |
+
" # 修改方向\n",
|
| 318 |
+
" self.direction = self.randDirection()\n",
|
| 319 |
+
" \n",
|
| 320 |
+
" # 让步数复位\n",
|
| 321 |
+
" self.step = 60\n",
|
| 322 |
+
" \n",
|
| 323 |
+
" else:\n",
|
| 324 |
+
" # 移动\n",
|
| 325 |
+
" self.move()\n",
|
| 326 |
+
" \n",
|
| 327 |
+
" # 让步数递减\n",
|
| 328 |
+
" self.step -= 1\n",
|
| 329 |
+
"\n",
|
| 330 |
+
" def shot(self):\n",
|
| 331 |
+
" \"\"\"重写 发射函数\"\"\"\n",
|
| 332 |
+
" \n",
|
| 333 |
+
" # 10% 的概率,发射子弹\n",
|
| 334 |
+
" num = random.randint(1, 100)\n",
|
| 335 |
+
" if num < 10:\n",
|
| 336 |
+
" return Bullet(self)"
|
| 337 |
+
]
|
| 338 |
+
},
|
| 339 |
+
{
|
| 340 |
+
"cell_type": "markdown",
|
| 341 |
+
"id": "afc41a05",
|
| 342 |
+
"metadata": {},
|
| 343 |
+
"source": [
|
| 344 |
+
"## 子弹类"
|
| 345 |
+
]
|
| 346 |
+
},
|
| 347 |
+
{
|
| 348 |
+
"cell_type": "code",
|
| 349 |
+
"execution_count": 7,
|
| 350 |
+
"id": "f23b42c3",
|
| 351 |
+
"metadata": {
|
| 352 |
+
"ExecuteTime": {
|
| 353 |
+
"end_time": "2023-10-05T17:25:00.288620Z",
|
| 354 |
+
"start_time": "2023-10-05T17:25:00.274879Z"
|
| 355 |
+
}
|
| 356 |
+
},
|
| 357 |
+
"outputs": [],
|
| 358 |
+
"source": [
|
| 359 |
+
"class Bullet(BaseItem):\n",
|
| 360 |
+
" \"\"\"子弹类\"\"\"\n",
|
| 361 |
+
"\n",
|
| 362 |
+
" def __init__(self, tank):\n",
|
| 363 |
+
" \"\"\"初始化函数\"\"\"\n",
|
| 364 |
+
"\n",
|
| 365 |
+
" # 加载子弹图片\n",
|
| 366 |
+
" self.image = pygame.image.load('img/enemymissile.gif')\n",
|
| 367 |
+
"\n",
|
| 368 |
+
" # 坦克的方向决定子弹的方向\n",
|
| 369 |
+
" self.direction = tank.direction\n",
|
| 370 |
+
"\n",
|
| 371 |
+
" # 获取子弹区域\n",
|
| 372 |
+
" self.rect = self.image.get_rect()\n",
|
| 373 |
+
"\n",
|
| 374 |
+
" # 初始化子弹的位置 -- 不同的方向,初始化的位置也不同\n",
|
| 375 |
+
" if self.direction == 'U':\n",
|
| 376 |
+
" self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2\n",
|
| 377 |
+
" self.rect.top = tank.rect.top - self.rect.height\n",
|
| 378 |
+
"\n",
|
| 379 |
+
" elif self.direction == 'D':\n",
|
| 380 |
+
" self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2\n",
|
| 381 |
+
" self.rect.top = tank.rect.top + tank.rect.height\n",
|
| 382 |
+
"\n",
|
| 383 |
+
" elif self.direction == 'L':\n",
|
| 384 |
+
" self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2\n",
|
| 385 |
+
" self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2\n",
|
| 386 |
+
"\n",
|
| 387 |
+
" elif self.direction == 'R':\n",
|
| 388 |
+
" self.rect.left = tank.rect.left + tank.rect.width\n",
|
| 389 |
+
" self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2\n",
|
| 390 |
+
"\n",
|
| 391 |
+
" # 子弹的速度\n",
|
| 392 |
+
" self.speed = 6\n",
|
| 393 |
+
"\n",
|
| 394 |
+
" # 子弹的状态 -- 是否存在\n",
|
| 395 |
+
" self.live = True\n",
|
| 396 |
+
"\n",
|
| 397 |
+
" def move(self):\n",
|
| 398 |
+
" \"\"\"移动函数\"\"\"\n",
|
| 399 |
+
"\n",
|
| 400 |
+
" if self.direction == 'U':\n",
|
| 401 |
+
" if self.rect.top > 0:\n",
|
| 402 |
+
" self.rect.top -= self.speed\n",
|
| 403 |
+
" else:\n",
|
| 404 |
+
" # 修改子弹的状态\n",
|
| 405 |
+
" self.live = False\n",
|
| 406 |
+
"\n",
|
| 407 |
+
" elif self.direction == 'R':\n",
|
| 408 |
+
" if self.rect.left+self.rect.width < SCREEN_WIDTH:\n",
|
| 409 |
+
" self.rect.left += self.speed\n",
|
| 410 |
+
" else:\n",
|
| 411 |
+
" # 修改子弹的状态\n",
|
| 412 |
+
" self.live = False\n",
|
| 413 |
+
"\n",
|
| 414 |
+
" elif self.direction == 'D':\n",
|
| 415 |
+
" if self.rect.top+self.rect.height < SCREEN_HEIGHT:\n",
|
| 416 |
+
" self.rect.top += self.speed\n",
|
| 417 |
+
" else:\n",
|
| 418 |
+
" # 修改子弹的状态\n",
|
| 419 |
+
" self.live = False\n",
|
| 420 |
+
" \n",
|
| 421 |
+
" elif self.direction == 'L':\n",
|
| 422 |
+
" if self.rect.left > 0:\n",
|
| 423 |
+
" self.rect.left -= self.speed\n",
|
| 424 |
+
" else:\n",
|
| 425 |
+
" # 修改子弹的状态\n",
|
| 426 |
+
" self.live = False\n",
|
| 427 |
+
"\n",
|
| 428 |
+
" \n",
|
| 429 |
+
" def hitWall(self):\n",
|
| 430 |
+
" \"\"\"子弹碰到墙体\"\"\"\n",
|
| 431 |
+
" \n",
|
| 432 |
+
" # 循环遍历墙壁列表\n",
|
| 433 |
+
" for wall in MainGame.wallList:\n",
|
| 434 |
+
" \n",
|
| 435 |
+
" # 如果相撞\n",
|
| 436 |
+
" if pygame.sprite.collide_rect(self, wall):\n",
|
| 437 |
+
" \n",
|
| 438 |
+
" # 修改子弹的生存状态,让子弹消失\n",
|
| 439 |
+
" self.live = False\n",
|
| 440 |
+
" \n",
|
| 441 |
+
" # 墙壁的生命值减小\n",
|
| 442 |
+
" wall.hp -= 1\n",
|
| 443 |
+
" \n",
|
| 444 |
+
" # 墙壁被破坏严重时,则消失\n",
|
| 445 |
+
" if wall.hp <= 0:\n",
|
| 446 |
+
" \n",
|
| 447 |
+
" # 修改墙壁的生存状态\n",
|
| 448 |
+
" wall.live = False\n",
|
| 449 |
+
"\n",
|
| 450 |
+
"\n",
|
| 451 |
+
" def displayBullet(self):\n",
|
| 452 |
+
" \"\"\"展示子弹\"\"\"\n",
|
| 453 |
+
" # 将图片surface加载到窗口\n",
|
| 454 |
+
" MainGame.window.blit(self.image, self.rect)\n",
|
| 455 |
+
"\n",
|
| 456 |
+
"\n",
|
| 457 |
+
" def myBullet_hit_enemyTank(self):\n",
|
| 458 |
+
" \"\"\"我方子弹与敌方坦克的碰撞\"\"\"\n",
|
| 459 |
+
" \n",
|
| 460 |
+
" # 循环遍历敌方坦克列表\n",
|
| 461 |
+
" for enemyTank in MainGame.enemyTankList:\n",
|
| 462 |
+
" \n",
|
| 463 |
+
" # 如果相撞\n",
|
| 464 |
+
" if pygame.sprite.collide_rect(enemyTank, self):\n",
|
| 465 |
+
" \n",
|
| 466 |
+
" # 修改敌方坦克和我方子弹的状态\n",
|
| 467 |
+
" enemyTank.live = False\n",
|
| 468 |
+
" self.live = False\n",
|
| 469 |
+
" \n",
|
| 470 |
+
" # 创建爆炸对象\n",
|
| 471 |
+
" explode = Explode(enemyTank)\n",
|
| 472 |
+
" \n",
|
| 473 |
+
" # 将爆炸对象添加到爆炸列表中\n",
|
| 474 |
+
" MainGame.explodeList.append(explode)\n",
|
| 475 |
+
" \n",
|
| 476 |
+
"\n",
|
| 477 |
+
" def enemyBullet_hit_myTank(self):\n",
|
| 478 |
+
" \"\"\"敌方子弹与我方坦克的碰撞\"\"\"\n",
|
| 479 |
+
" if MainGame.my_tank and MainGame.my_tank.live:\n",
|
| 480 |
+
" if pygame.sprite.collide_rect(MainGame.my_tank, self):\n",
|
| 481 |
+
" \n",
|
| 482 |
+
" # 产生爆炸对象\n",
|
| 483 |
+
" explode = Explode(MainGame.my_tank)\n",
|
| 484 |
+
" \n",
|
| 485 |
+
" # 将爆炸对象添加到爆炸列表中\n",
|
| 486 |
+
" MainGame.explodeList.append(explode)\n",
|
| 487 |
+
" \n",
|
| 488 |
+
" # 修改敌方子弹与我方坦克的状态\n",
|
| 489 |
+
" self.live = False\n",
|
| 490 |
+
" MainGame.my_tank.live = False"
|
| 491 |
+
]
|
| 492 |
+
},
|
| 493 |
+
{
|
| 494 |
+
"cell_type": "markdown",
|
| 495 |
+
"id": "11a80705",
|
| 496 |
+
"metadata": {},
|
| 497 |
+
"source": [
|
| 498 |
+
"## 墙体类"
|
| 499 |
+
]
|
| 500 |
+
},
|
| 501 |
+
{
|
| 502 |
+
"cell_type": "code",
|
| 503 |
+
"execution_count": 8,
|
| 504 |
+
"id": "881b05ec",
|
| 505 |
+
"metadata": {
|
| 506 |
+
"ExecuteTime": {
|
| 507 |
+
"end_time": "2023-10-05T17:25:00.294896Z",
|
| 508 |
+
"start_time": "2023-10-05T17:25:00.290645Z"
|
| 509 |
+
}
|
| 510 |
+
},
|
| 511 |
+
"outputs": [],
|
| 512 |
+
"source": [
|
| 513 |
+
"class Wall():\n",
|
| 514 |
+
" def __init__(self, left, top):\n",
|
| 515 |
+
" \n",
|
| 516 |
+
" # 加载墙壁图片\n",
|
| 517 |
+
" self.image = pygame.image.load('img/steels.gif')\n",
|
| 518 |
+
" \n",
|
| 519 |
+
" # 获取墙壁的区域\n",
|
| 520 |
+
" self.rect = self.image.get_rect()\n",
|
| 521 |
+
" \n",
|
| 522 |
+
" # 初始化墙体位置\n",
|
| 523 |
+
" self.rect.left = left\n",
|
| 524 |
+
" self.rect.top = top\n",
|
| 525 |
+
" \n",
|
| 526 |
+
" # 标记是否存活\n",
|
| 527 |
+
" self.live = True\n",
|
| 528 |
+
" \n",
|
| 529 |
+
" # 设置生命值\n",
|
| 530 |
+
" self.hp = 3\n",
|
| 531 |
+
"\n",
|
| 532 |
+
" def displayWall(self):\n",
|
| 533 |
+
" \"\"\"展示墙壁\"\"\"\n",
|
| 534 |
+
" MainGame.window.blit(self.image, self.rect)"
|
| 535 |
+
]
|
| 536 |
+
},
|
| 537 |
+
{
|
| 538 |
+
"cell_type": "markdown",
|
| 539 |
+
"id": "86515d54",
|
| 540 |
+
"metadata": {},
|
| 541 |
+
"source": [
|
| 542 |
+
"## 爆炸类"
|
| 543 |
+
]
|
| 544 |
+
},
|
| 545 |
+
{
|
| 546 |
+
"cell_type": "code",
|
| 547 |
+
"execution_count": 9,
|
| 548 |
+
"id": "c60e6eaa",
|
| 549 |
+
"metadata": {
|
| 550 |
+
"ExecuteTime": {
|
| 551 |
+
"end_time": "2023-10-05T17:25:00.305090Z",
|
| 552 |
+
"start_time": "2023-10-05T17:25:00.298733Z"
|
| 553 |
+
}
|
| 554 |
+
},
|
| 555 |
+
"outputs": [],
|
| 556 |
+
"source": [
|
| 557 |
+
"class Explode():\n",
|
| 558 |
+
" def __init__(self, tank):\n",
|
| 559 |
+
" \"\"\"初始化函数:传入爆炸的坦克\"\"\"\n",
|
| 560 |
+
" \n",
|
| 561 |
+
" # 获取爆炸位置\n",
|
| 562 |
+
" self.rect = tank.rect\n",
|
| 563 |
+
" \n",
|
| 564 |
+
" # 爆炸的图片\n",
|
| 565 |
+
" self.images = [\n",
|
| 566 |
+
" pygame.image.load('img/blast0.gif'),\n",
|
| 567 |
+
" pygame.image.load('img/blast1.gif'),\n",
|
| 568 |
+
" pygame.image.load('img/blast2.gif'),\n",
|
| 569 |
+
" pygame.image.load('img/blast3.gif'),\n",
|
| 570 |
+
" pygame.image.load('img/blast4.gif'),\n",
|
| 571 |
+
" ]\n",
|
| 572 |
+
" \n",
|
| 573 |
+
" # 索引 -- 依次使用不同的爆炸图片\n",
|
| 574 |
+
" self.step = 0\n",
|
| 575 |
+
" \n",
|
| 576 |
+
" self.image = self.images[self.step]\n",
|
| 577 |
+
" \n",
|
| 578 |
+
" # 是否进行爆炸\n",
|
| 579 |
+
" self.live = True\n",
|
| 580 |
+
"\n",
|
| 581 |
+
"\n",
|
| 582 |
+
" def displayExplode(self):\n",
|
| 583 |
+
" \"\"\"展示爆炸\"\"\"\n",
|
| 584 |
+
" if self.step < len(self.images):\n",
|
| 585 |
+
" \n",
|
| 586 |
+
" # 根据索引获取爆炸图片\n",
|
| 587 |
+
" self.image = self.images[self.step]\n",
|
| 588 |
+
" self.step += 1\n",
|
| 589 |
+
" \n",
|
| 590 |
+
" # 展示爆炸图片\n",
|
| 591 |
+
" MainGame.window.blit(self.image, self.rect)\n",
|
| 592 |
+
" \n",
|
| 593 |
+
" else:\n",
|
| 594 |
+
" # 修改爆炸对象的状态\n",
|
| 595 |
+
" self.live = False\n",
|
| 596 |
+
" self.step = 0\n"
|
| 597 |
+
]
|
| 598 |
+
},
|
| 599 |
+
{
|
| 600 |
+
"cell_type": "markdown",
|
| 601 |
+
"id": "4acda6df",
|
| 602 |
+
"metadata": {},
|
| 603 |
+
"source": [
|
| 604 |
+
"## 音乐类"
|
| 605 |
+
]
|
| 606 |
+
},
|
| 607 |
+
{
|
| 608 |
+
"cell_type": "code",
|
| 609 |
+
"execution_count": 10,
|
| 610 |
+
"id": "5943ae85",
|
| 611 |
+
"metadata": {
|
| 612 |
+
"ExecuteTime": {
|
| 613 |
+
"end_time": "2023-10-05T17:25:00.310602Z",
|
| 614 |
+
"start_time": "2023-10-05T17:25:00.306990Z"
|
| 615 |
+
}
|
| 616 |
+
},
|
| 617 |
+
"outputs": [],
|
| 618 |
+
"source": [
|
| 619 |
+
"class Music():\n",
|
| 620 |
+
" def __init__(self, filename):\n",
|
| 621 |
+
" \"\"\"初始化函数\"\"\"\n",
|
| 622 |
+
" \n",
|
| 623 |
+
" # 获取音乐名称\n",
|
| 624 |
+
" self.filename = filename\n",
|
| 625 |
+
" \n",
|
| 626 |
+
" # 初始化背景音乐\n",
|
| 627 |
+
" pygame.mixer.init()\n",
|
| 628 |
+
" \n",
|
| 629 |
+
" # 加载背景音乐\n",
|
| 630 |
+
" pygame.mixer.music.load(self.filename)\n",
|
| 631 |
+
"\n",
|
| 632 |
+
" \n",
|
| 633 |
+
" def play(self):\n",
|
| 634 |
+
" \"\"\"播放音乐\"\"\"\n",
|
| 635 |
+
" pygame.mixer.music.play()\n"
|
| 636 |
+
]
|
| 637 |
+
},
|
| 638 |
+
{
|
| 639 |
+
"cell_type": "markdown",
|
| 640 |
+
"id": "b0a5fb3d",
|
| 641 |
+
"metadata": {},
|
| 642 |
+
"source": [
|
| 643 |
+
"## 主游戏类"
|
| 644 |
+
]
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"cell_type": "code",
|
| 648 |
+
"execution_count": 11,
|
| 649 |
+
"id": "f524cd94",
|
| 650 |
+
"metadata": {
|
| 651 |
+
"ExecuteTime": {
|
| 652 |
+
"end_time": "2023-10-05T17:25:00.354619Z",
|
| 653 |
+
"start_time": "2023-10-05T17:25:00.312692Z"
|
| 654 |
+
}
|
| 655 |
+
},
|
| 656 |
+
"outputs": [],
|
| 657 |
+
"source": [
|
| 658 |
+
"class MainGame():\n",
|
| 659 |
+
" \"\"\"\n",
|
| 660 |
+
" 主游戏类:\n",
|
| 661 |
+
" 游戏整体运行的逻辑\n",
|
| 662 |
+
" \"\"\"\n",
|
| 663 |
+
" \n",
|
| 664 |
+
" # 窗口\n",
|
| 665 |
+
" window = None\n",
|
| 666 |
+
" \n",
|
| 667 |
+
" # 我方坦克\n",
|
| 668 |
+
" my_tank = None\n",
|
| 669 |
+
" \n",
|
| 670 |
+
" # 存储敌方坦克的列表\n",
|
| 671 |
+
" enemyTankList = []\n",
|
| 672 |
+
" \n",
|
| 673 |
+
" # 定义敌方坦克的数量\n",
|
| 674 |
+
" enemyTankCount = 5\n",
|
| 675 |
+
" \n",
|
| 676 |
+
" # 存储我方子弹的列表\n",
|
| 677 |
+
" myBulletList = []\n",
|
| 678 |
+
" \n",
|
| 679 |
+
" # 存储敌方子弹的列表\n",
|
| 680 |
+
" enemyBulletList = []\n",
|
| 681 |
+
" \n",
|
| 682 |
+
" # 存储爆炸效果的列表\n",
|
| 683 |
+
" explodeList = []\n",
|
| 684 |
+
" \n",
|
| 685 |
+
" # 存储墙壁的列表\n",
|
| 686 |
+
" wallList = []\n",
|
| 687 |
+
"\n",
|
| 688 |
+
" def __init__(self):\n",
|
| 689 |
+
" \"\"\"初始化\"\"\"\n",
|
| 690 |
+
" pass\n",
|
| 691 |
+
" \n",
|
| 692 |
+
"\n",
|
| 693 |
+
" def startGame(self):\n",
|
| 694 |
+
" \"\"\"开始游戏\"\"\"\n",
|
| 695 |
+
" \n",
|
| 696 |
+
" # 初始化 pygame\n",
|
| 697 |
+
" pygame.display.init()\n",
|
| 698 |
+
" \n",
|
| 699 |
+
" # 设置窗口的大小及显示\n",
|
| 700 |
+
" MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])\n",
|
| 701 |
+
" \n",
|
| 702 |
+
" # 初始化 我方坦克\n",
|
| 703 |
+
" self.createMytank()\n",
|
| 704 |
+
" \n",
|
| 705 |
+
" # 初始化敌方坦克,并将敌方坦克添加到列表中\n",
|
| 706 |
+
" self.createEnemyTank()\n",
|
| 707 |
+
" \n",
|
| 708 |
+
" # 初始化墙壁\n",
|
| 709 |
+
" self.createWall()\n",
|
| 710 |
+
" \n",
|
| 711 |
+
" # 设置窗口的标题\n",
|
| 712 |
+
" pygame.display.set_caption('坦克大战1.03')\n",
|
| 713 |
+
" \n",
|
| 714 |
+
" while True:\n",
|
| 715 |
+
" \n",
|
| 716 |
+
" # 让坦克移动的速度慢一点\n",
|
| 717 |
+
" time.sleep(0.02)\n",
|
| 718 |
+
" \n",
|
| 719 |
+
" # 给窗口设置背景色\n",
|
| 720 |
+
" MainGame.window.fill(BG_COLOR)\n",
|
| 721 |
+
" \n",
|
| 722 |
+
" # 获取事件\n",
|
| 723 |
+
" self.getEvent()\n",
|
| 724 |
+
" \n",
|
| 725 |
+
" # 绘制文字\n",
|
| 726 |
+
" MainGame.window.blit(self.getTextSuface(\n",
|
| 727 |
+
" '敌方坦克剩余数量%d' % len(MainGame.enemyTankList)), (10, 10))\n",
|
| 728 |
+
" \n",
|
| 729 |
+
" ## 调用坦克显示的方法\n",
|
| 730 |
+
" if MainGame.my_tank and MainGame.my_tank.live:\n",
|
| 731 |
+
" # 我方坦克存活\n",
|
| 732 |
+
" MainGame.my_tank.displayTank()\n",
|
| 733 |
+
" else:\n",
|
| 734 |
+
" # 我方坦克死亡,删除我方坦克\n",
|
| 735 |
+
" del MainGame.my_tank\n",
|
| 736 |
+
" MainGame.my_tank = None\n",
|
| 737 |
+
" \n",
|
| 738 |
+
" # 循环遍历敌方坦克列表,展示敌方坦克\n",
|
| 739 |
+
" self.blitEnemyTank()\n",
|
| 740 |
+
" \n",
|
| 741 |
+
" # 循环遍历显示我方坦克的子弹\n",
|
| 742 |
+
" self.blitMyBullet()\n",
|
| 743 |
+
" \n",
|
| 744 |
+
" # 循环遍历敌方子弹列表,展示敌方子弹\n",
|
| 745 |
+
" self.blitEnemyBullet()\n",
|
| 746 |
+
" \n",
|
| 747 |
+
" # 循环遍历爆炸列表,展示爆炸效果\n",
|
| 748 |
+
" self.blitExplode()\n",
|
| 749 |
+
" \n",
|
| 750 |
+
" # 循环遍历墙壁列表,展示墙壁\n",
|
| 751 |
+
" self.blitWall()\n",
|
| 752 |
+
" \n",
|
| 753 |
+
" # 调用移动方法\n",
|
| 754 |
+
" if MainGame.my_tank and MainGame.my_tank.live:\n",
|
| 755 |
+
" # 如果坦克的开关是开启,才可以移动\n",
|
| 756 |
+
" if not MainGame.my_tank.stop:\n",
|
| 757 |
+
" MainGame.my_tank.move()\n",
|
| 758 |
+
" \n",
|
| 759 |
+
" # 检测我方坦克是否与墙壁发生碰撞\n",
|
| 760 |
+
" MainGame.my_tank.hitWall()\n",
|
| 761 |
+
" \n",
|
| 762 |
+
" # 检测我方坦克是否与敌方坦克发生碰撞\n",
|
| 763 |
+
" MainGame.my_tank.myTank_hit_enemyTank()\n",
|
| 764 |
+
"\n",
|
| 765 |
+
" # 更新屏幕\n",
|
| 766 |
+
" pygame.display.update()\n",
|
| 767 |
+
" \n",
|
| 768 |
+
" \n",
|
| 769 |
+
" def blitWall(self):\n",
|
| 770 |
+
" \"\"\"循环遍历墙壁列表,展示墙壁\"\"\"\n",
|
| 771 |
+
" for wall in MainGame.wallList:\n",
|
| 772 |
+
" # 判断墙壁是否存活\n",
|
| 773 |
+
" if wall.live:\n",
|
| 774 |
+
" # 调用墙壁的显示方法\n",
|
| 775 |
+
" wall.displayWall()\n",
|
| 776 |
+
" else:\n",
|
| 777 |
+
" # 从墙壁列表移出\n",
|
| 778 |
+
" MainGame.wallList.remove(wall)\n",
|
| 779 |
+
" \n",
|
| 780 |
+
"\n",
|
| 781 |
+
" def createWall(self):\n",
|
| 782 |
+
" \"\"\"初始化墙壁\"\"\"\n",
|
| 783 |
+
" for i in range(6):\n",
|
| 784 |
+
" \n",
|
| 785 |
+
" # 创建墙壁\n",
|
| 786 |
+
" wall = Wall(i*130, 220)\n",
|
| 787 |
+
" # 将墙壁添加到列表中\n",
|
| 788 |
+
" MainGame.wallList.append(wall)\n",
|
| 789 |
+
" \n",
|
| 790 |
+
"\n",
|
| 791 |
+
" def createMytank(self):\n",
|
| 792 |
+
" \"\"\"创建我方坦克\"\"\"\n",
|
| 793 |
+
" MainGame.my_tank = MyTank(350, 300)\n",
|
| 794 |
+
" \n",
|
| 795 |
+
" # 创建 Music对象\n",
|
| 796 |
+
" music = Music('img/start.wav')\n",
|
| 797 |
+
" \n",
|
| 798 |
+
" # 播放音乐\n",
|
| 799 |
+
" music.play()\n",
|
| 800 |
+
" \n",
|
| 801 |
+
"\n",
|
| 802 |
+
" def createEnemyTank(self):\n",
|
| 803 |
+
" \"\"\"创建敌方坦克\"\"\"\n",
|
| 804 |
+
" top = 100\n",
|
| 805 |
+
" \n",
|
| 806 |
+
" # 循环生成敌方坦克\n",
|
| 807 |
+
" for i in range(MainGame.enemyTankCount):\n",
|
| 808 |
+
" left = random.randint(0, 600)\n",
|
| 809 |
+
" speed = random.randint(1, 4)\n",
|
| 810 |
+
" enemy = EnemyTank(left, top, speed)\n",
|
| 811 |
+
" MainGame.enemyTankList.append(enemy)\n",
|
| 812 |
+
" \n",
|
| 813 |
+
"\n",
|
| 814 |
+
" def blitExplode(self):\n",
|
| 815 |
+
" \"\"\"展示爆炸效果\"\"\"\n",
|
| 816 |
+
" \n",
|
| 817 |
+
" # 遍历爆炸列表\n",
|
| 818 |
+
" for explode in MainGame.explodeList:\n",
|
| 819 |
+
" if explode.live:\n",
|
| 820 |
+
" # 展示爆炸效果\n",
|
| 821 |
+
" explode.displayExplode()\n",
|
| 822 |
+
" else:\n",
|
| 823 |
+
" # 在爆炸列表中移除\n",
|
| 824 |
+
" MainGame.explodeList.remove(explode)\n",
|
| 825 |
+
" \n",
|
| 826 |
+
"\n",
|
| 827 |
+
" def blitEnemyTank(self):\n",
|
| 828 |
+
" \"\"\"展示敌方坦克\"\"\"\n",
|
| 829 |
+
" for enemyTank in MainGame.enemyTankList:\n",
|
| 830 |
+
" \n",
|
| 831 |
+
" # 如果当前敌方坦克还活着\n",
|
| 832 |
+
" if enemyTank.live:\n",
|
| 833 |
+
" \n",
|
| 834 |
+
" # 展示\n",
|
| 835 |
+
" enemyTank.displayTank()\n",
|
| 836 |
+
" \n",
|
| 837 |
+
" # 移动\n",
|
| 838 |
+
" enemyTank.randMove()\n",
|
| 839 |
+
" \n",
|
| 840 |
+
" # 调用检测是否与墙壁碰撞\n",
|
| 841 |
+
" enemyTank.hitWall()\n",
|
| 842 |
+
" \n",
|
| 843 |
+
" # 检测敌方坦克是否与我方坦克发生碰撞\n",
|
| 844 |
+
" if MainGame.my_tank and MainGame.my_tank.live:\n",
|
| 845 |
+
" enemyTank.enemyTank_hit_myTank()\n",
|
| 846 |
+
" \n",
|
| 847 |
+
" # 发射子弹\n",
|
| 848 |
+
" enemyBullet = enemyTank.shot()\n",
|
| 849 |
+
" \n",
|
| 850 |
+
" # 敌方子弹是否是None,如果不为None则添加到敌方子弹列表中\n",
|
| 851 |
+
" if enemyBullet:\n",
|
| 852 |
+
" # 将敌方子弹存储到敌方子弹列表中\n",
|
| 853 |
+
" MainGame.enemyBulletList.append(enemyBullet)\n",
|
| 854 |
+
" \n",
|
| 855 |
+
" # 如果死亡,则从敌方坦克列表中移除 \n",
|
| 856 |
+
" else: \n",
|
| 857 |
+
" MainGame.enemyTankList.remove(enemyTank)\n",
|
| 858 |
+
"\n",
|
| 859 |
+
"\n",
|
| 860 |
+
" def blitMyBullet(self):\n",
|
| 861 |
+
" \"\"\"展示我方子弹\"\"\"\n",
|
| 862 |
+
" \n",
|
| 863 |
+
" # 遍历子弹列表\n",
|
| 864 |
+
" for myBullet in MainGame.myBulletList:\n",
|
| 865 |
+
" \n",
|
| 866 |
+
" # 子弹如果存在,则展示\n",
|
| 867 |
+
" if myBullet.live:\n",
|
| 868 |
+
" \n",
|
| 869 |
+
" # 展示子弹\n",
|
| 870 |
+
" myBullet.displayBullet()\n",
|
| 871 |
+
" \n",
|
| 872 |
+
" # 移动子弹\n",
|
| 873 |
+
" myBullet.move()\n",
|
| 874 |
+
" \n",
|
| 875 |
+
" # 判断我方子弹是否击中敌方\n",
|
| 876 |
+
" myBullet.myBullet_hit_enemyTank()\n",
|
| 877 |
+
" \n",
|
| 878 |
+
" # 判断我方子弹是否击中墙壁\n",
|
| 879 |
+
" myBullet.hitWall()\n",
|
| 880 |
+
" \n",
|
| 881 |
+
" # 子弹如果不存在,则从列表中删除\n",
|
| 882 |
+
" else:\n",
|
| 883 |
+
" MainGame.myBulletList.remove(myBullet)\n",
|
| 884 |
+
"\n",
|
| 885 |
+
" def blitEnemyBullet(self):\n",
|
| 886 |
+
" \"\"\"展示敌方子弹\"\"\"\n",
|
| 887 |
+
" \n",
|
| 888 |
+
" # 遍历敌方子弹列表\n",
|
| 889 |
+
" for enemyBullet in MainGame.enemyBulletList:\n",
|
| 890 |
+
" \n",
|
| 891 |
+
" # 如果敌方子弹存在\n",
|
| 892 |
+
" if enemyBullet.live: \n",
|
| 893 |
+
" \n",
|
| 894 |
+
" # 展示敌方子弹\n",
|
| 895 |
+
" enemyBullet.displayBullet()\n",
|
| 896 |
+
" \n",
|
| 897 |
+
" # 移动子弹\n",
|
| 898 |
+
" enemyBullet.move()\n",
|
| 899 |
+
" \n",
|
| 900 |
+
" # 敌方子弹 是否击中 我方坦克\n",
|
| 901 |
+
" enemyBullet.enemyBullet_hit_myTank()\n",
|
| 902 |
+
" \n",
|
| 903 |
+
" # 敌方子弹是否击中墙壁\n",
|
| 904 |
+
" enemyBullet.hitWall()\n",
|
| 905 |
+
" \n",
|
| 906 |
+
" # 如果子弹不存在,则从列表中移除\n",
|
| 907 |
+
" else:\n",
|
| 908 |
+
" MainGame.enemyBulletList.remove(enemyBullet)\n",
|
| 909 |
+
"\n",
|
| 910 |
+
" \n",
|
| 911 |
+
"\n",
|
| 912 |
+
" def endGame(self):\n",
|
| 913 |
+
" \"\"\"结束游戏\"\"\"\n",
|
| 914 |
+
" \n",
|
| 915 |
+
" print('谢谢使用,欢迎再次使用')\n",
|
| 916 |
+
" pygame.quit()\n",
|
| 917 |
+
" exit()\n",
|
| 918 |
+
" \n",
|
| 919 |
+
"\n",
|
| 920 |
+
" def getTextSuface(self, text):\n",
|
| 921 |
+
" \"\"\"左上角添加文字\"\"\"\n",
|
| 922 |
+
" \n",
|
| 923 |
+
" # 初始化字体模块\n",
|
| 924 |
+
" pygame.font.init()\n",
|
| 925 |
+
" \n",
|
| 926 |
+
" # 获取字体Font对象\n",
|
| 927 |
+
" font = pygame.font.SysFont('ヒラキノ角コシックw8', 18)\n",
|
| 928 |
+
" \n",
|
| 929 |
+
" # 绘制文字信息\n",
|
| 930 |
+
" textSurface = font.render(text, True, TEXT_COLOR)\n",
|
| 931 |
+
" \n",
|
| 932 |
+
" return textSurface\n",
|
| 933 |
+
" \n",
|
| 934 |
+
"\n",
|
| 935 |
+
" def getEvent(self):\n",
|
| 936 |
+
" \"\"\"获取事件\"\"\"\n",
|
| 937 |
+
" \n",
|
| 938 |
+
" # 获取所有事件\n",
|
| 939 |
+
" eventList = pygame.event.get()\n",
|
| 940 |
+
" \n",
|
| 941 |
+
" # 遍历事件\n",
|
| 942 |
+
" for event in eventList:\n",
|
| 943 |
+
" \n",
|
| 944 |
+
" # 鼠标点击退出,则结束游戏\n",
|
| 945 |
+
" if event.type == pygame.QUIT:\n",
|
| 946 |
+
" self.endGame()\n",
|
| 947 |
+
" \n",
|
| 948 |
+
" # 如果是键盘事件\n",
|
| 949 |
+
" if event.type == pygame.KEYDOWN:\n",
|
| 950 |
+
" \n",
|
| 951 |
+
" # 当我方坦克死亡\n",
|
| 952 |
+
" if not MainGame.my_tank:\n",
|
| 953 |
+
" \n",
|
| 954 |
+
" # 如果按下 Esc键\n",
|
| 955 |
+
" if event.key == pygame.K_ESCAPE:\n",
|
| 956 |
+
" # 我方坦克重生\n",
|
| 957 |
+
" self.createMytank()\n",
|
| 958 |
+
" \n",
|
| 959 |
+
" # 如果我方坦克存活\n",
|
| 960 |
+
" if MainGame.my_tank and MainGame.my_tank.live:\n",
|
| 961 |
+
" \n",
|
| 962 |
+
" # 按左键\n",
|
| 963 |
+
" if event.key == pygame.K_LEFT:\n",
|
| 964 |
+
" # 切换方向\n",
|
| 965 |
+
" MainGame.my_tank.direction = 'L'\n",
|
| 966 |
+
" \n",
|
| 967 |
+
" # 修改坦克的开关状态\n",
|
| 968 |
+
" MainGame.my_tank.stop = False\n",
|
| 969 |
+
" \n",
|
| 970 |
+
" \n",
|
| 971 |
+
" # 按右键\n",
|
| 972 |
+
" elif event.key == pygame.K_RIGHT:\n",
|
| 973 |
+
" # 切换方向\n",
|
| 974 |
+
" MainGame.my_tank.direction = 'R'\n",
|
| 975 |
+
" \n",
|
| 976 |
+
" # 修改坦克的开关状态\n",
|
| 977 |
+
" MainGame.my_tank.stop = False\n",
|
| 978 |
+
" \n",
|
| 979 |
+
" \n",
|
| 980 |
+
" # 按上键\n",
|
| 981 |
+
" elif event.key == pygame.K_UP:\n",
|
| 982 |
+
" # 切换方向\n",
|
| 983 |
+
" MainGame.my_tank.direction = 'U'\n",
|
| 984 |
+
" \n",
|
| 985 |
+
" # 修改坦克的开关状态\n",
|
| 986 |
+
" MainGame.my_tank.stop = False\n",
|
| 987 |
+
" \n",
|
| 988 |
+
" \n",
|
| 989 |
+
" # 按下键\n",
|
| 990 |
+
" elif event.key == pygame.K_DOWN:\n",
|
| 991 |
+
" # 切换方向\n",
|
| 992 |
+
" MainGame.my_tank.direction = 'D'\n",
|
| 993 |
+
" \n",
|
| 994 |
+
" # 修改坦克的开关状态\n",
|
| 995 |
+
" MainGame.my_tank.stop = False\n",
|
| 996 |
+
" \n",
|
| 997 |
+
" \n",
|
| 998 |
+
" # 按空格\n",
|
| 999 |
+
" elif event.key == pygame.K_SPACE:\n",
|
| 1000 |
+
" \"\"\"发射子弹\"\"\"\n",
|
| 1001 |
+
" \n",
|
| 1002 |
+
" # 最多发射 3发子弹\n",
|
| 1003 |
+
" if len(MainGame.myBulletList) < 3:\n",
|
| 1004 |
+
" # 创建子弹\n",
|
| 1005 |
+
" myBullet = Bullet(MainGame.my_tank)\n",
|
| 1006 |
+
" \n",
|
| 1007 |
+
" # 将子弹添加进列表\n",
|
| 1008 |
+
" MainGame.myBulletList.append(myBullet)\n",
|
| 1009 |
+
" \n",
|
| 1010 |
+
" # 添加音效\n",
|
| 1011 |
+
" music = Music('img/hit.wav')\n",
|
| 1012 |
+
" music.play()\n",
|
| 1013 |
+
"\n",
|
| 1014 |
+
" # 松开方向键\n",
|
| 1015 |
+
" if event.type == pygame.KEYUP:\n",
|
| 1016 |
+
" \"\"\"坦克停止移动,修改坦克的开关状态\"\"\"\n",
|
| 1017 |
+
" \n",
|
| 1018 |
+
" # 判断松开的键是上、下、左、右时候才停止坦克移动\n",
|
| 1019 |
+
" if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:\n",
|
| 1020 |
+
" if MainGame.my_tank and MainGame.my_tank.live:\n",
|
| 1021 |
+
" MainGame.my_tank.stop = True"
|
| 1022 |
+
]
|
| 1023 |
+
},
|
| 1024 |
+
{
|
| 1025 |
+
"cell_type": "markdown",
|
| 1026 |
+
"id": "c153a418",
|
| 1027 |
+
"metadata": {},
|
| 1028 |
+
"source": [
|
| 1029 |
+
"## main函数"
|
| 1030 |
+
]
|
| 1031 |
+
},
|
| 1032 |
+
{
|
| 1033 |
+
"cell_type": "code",
|
| 1034 |
+
"execution_count": 12,
|
| 1035 |
+
"id": "f9ba8d23",
|
| 1036 |
+
"metadata": {
|
| 1037 |
+
"ExecuteTime": {
|
| 1038 |
+
"end_time": "2023-10-05T17:25:45.036981Z",
|
| 1039 |
+
"start_time": "2023-10-05T17:25:00.355339Z"
|
| 1040 |
+
},
|
| 1041 |
+
"collapsed": true
|
| 1042 |
+
},
|
| 1043 |
+
"outputs": [
|
| 1044 |
+
{
|
| 1045 |
+
"name": "stderr",
|
| 1046 |
+
"output_type": "stream",
|
| 1047 |
+
"text": [
|
| 1048 |
+
"2023-10-06 01:25:02.476 python[85798:5756894] TSM AdjustCapsLockLEDForKeyTransitionHandling - _ISSetPhysicalKeyboardCapsLockLED Inhibit\n"
|
| 1049 |
+
]
|
| 1050 |
+
},
|
| 1051 |
+
{
|
| 1052 |
+
"name": "stdout",
|
| 1053 |
+
"output_type": "stream",
|
| 1054 |
+
"text": [
|
| 1055 |
+
"谢谢使用,欢迎再次使用\n"
|
| 1056 |
+
]
|
| 1057 |
+
},
|
| 1058 |
+
{
|
| 1059 |
+
"ename": "error",
|
| 1060 |
+
"evalue": "display Surface quit",
|
| 1061 |
+
"output_type": "error",
|
| 1062 |
+
"traceback": [
|
| 1063 |
+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
| 1064 |
+
"\u001b[0;31merror\u001b[0m Traceback (most recent call last)",
|
| 1065 |
+
"Input \u001b[0;32mIn [12]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[0;32m----> 2\u001b[0m \u001b[43mMainGame\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstartGame\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
|
| 1066 |
+
"Input \u001b[0;32mIn [11]\u001b[0m, in \u001b[0;36mMainGame.startGame\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgetEvent()\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# 绘制文字\u001b[39;00m\n\u001b[0;32m---> 69\u001b[0m \u001b[43mMainGame\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwindow\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mblit\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetTextSuface\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 70\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m敌方坦克剩余数量\u001b[39;49m\u001b[38;5;132;43;01m%d\u001b[39;49;00m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m%\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mMainGame\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43menemyTankList\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m10\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m10\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;66;03m## 调用坦克显示的方法\u001b[39;00m\n\u001b[1;32m 73\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m MainGame\u001b[38;5;241m.\u001b[39mmy_tank \u001b[38;5;129;01mand\u001b[39;00m MainGame\u001b[38;5;241m.\u001b[39mmy_tank\u001b[38;5;241m.\u001b[39mlive:\n\u001b[1;32m 74\u001b[0m \u001b[38;5;66;03m# 我方坦克存活\u001b[39;00m\n",
|
| 1067 |
+
"\u001b[0;31merror\u001b[0m: display Surface quit"
|
| 1068 |
+
]
|
| 1069 |
+
}
|
| 1070 |
+
],
|
| 1071 |
+
"source": [
|
| 1072 |
+
"if __name__ == '__main__':\n",
|
| 1073 |
+
" MainGame().startGame()"
|
| 1074 |
+
]
|
| 1075 |
+
},
|
| 1076 |
+
{
|
| 1077 |
+
"cell_type": "code",
|
| 1078 |
+
"execution_count": null,
|
| 1079 |
+
"id": "4c763c1a",
|
| 1080 |
+
"metadata": {},
|
| 1081 |
+
"outputs": [],
|
| 1082 |
+
"source": []
|
| 1083 |
+
}
|
| 1084 |
+
],
|
| 1085 |
+
"metadata": {
|
| 1086 |
+
"kernelspec": {
|
| 1087 |
+
"display_name": "Python 3 (ipykernel)",
|
| 1088 |
+
"language": "python",
|
| 1089 |
+
"name": "python3"
|
| 1090 |
+
},
|
| 1091 |
+
"language_info": {
|
| 1092 |
+
"codemirror_mode": {
|
| 1093 |
+
"name": "ipython",
|
| 1094 |
+
"version": 3
|
| 1095 |
+
},
|
| 1096 |
+
"file_extension": ".py",
|
| 1097 |
+
"mimetype": "text/x-python",
|
| 1098 |
+
"name": "python",
|
| 1099 |
+
"nbconvert_exporter": "python",
|
| 1100 |
+
"pygments_lexer": "ipython3",
|
| 1101 |
+
"version": "3.9.12"
|
| 1102 |
+
},
|
| 1103 |
+
"toc": {
|
| 1104 |
+
"base_numbering": 1,
|
| 1105 |
+
"nav_menu": {},
|
| 1106 |
+
"number_sections": true,
|
| 1107 |
+
"sideBar": true,
|
| 1108 |
+
"skip_h1_title": false,
|
| 1109 |
+
"title_cell": "Table of Contents",
|
| 1110 |
+
"title_sidebar": "Contents",
|
| 1111 |
+
"toc_cell": false,
|
| 1112 |
+
"toc_position": {
|
| 1113 |
+
"height": "calc(100% - 180px)",
|
| 1114 |
+
"left": "10px",
|
| 1115 |
+
"top": "150px",
|
| 1116 |
+
"width": "248.1875px"
|
| 1117 |
+
},
|
| 1118 |
+
"toc_section_display": true,
|
| 1119 |
+
"toc_window_display": true
|
| 1120 |
+
}
|
| 1121 |
+
},
|
| 1122 |
+
"nbformat": 4,
|
| 1123 |
+
"nbformat_minor": 5
|
| 1124 |
+
}
|
05_Pygame实战:坦克大战游戏.py
ADDED
|
@@ -0,0 +1,760 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pygame
|
| 2 |
+
import time
|
| 3 |
+
import random
|
| 4 |
+
from pygame.sprite import Sprite
|
| 5 |
+
|
| 6 |
+
SCREEN_WIDTH = 800
|
| 7 |
+
SCREEN_HEIGHT = 500
|
| 8 |
+
BG_COLOR = pygame.Color(0, 0, 0)
|
| 9 |
+
TEXT_COLOR = pygame.Color(255, 0, 0)
|
| 10 |
+
|
| 11 |
+
# 定义一个基类
|
| 12 |
+
class BaseItem(Sprite):
|
| 13 |
+
def __init__(self, color, width, height):
|
| 14 |
+
pygame.sprite.Sprite.__init__(self)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class Tank(BaseItem):
|
| 18 |
+
def __init__(self, left, top):
|
| 19 |
+
"""初始化方法:添加距离左边left 距离上边top"""
|
| 20 |
+
|
| 21 |
+
# 创建字典 -- 朝不同的方向走,坦克也不尽相同
|
| 22 |
+
self.images = {
|
| 23 |
+
'U': pygame.image.load('img/p1tankU.gif'),
|
| 24 |
+
'D': pygame.image.load('img/p1tankD.gif'),
|
| 25 |
+
'L': pygame.image.load('img/p1tankL.gif'),
|
| 26 |
+
'R': pygame.image.load('img/p1tankR.gif'),
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
# 默认方向
|
| 30 |
+
self.direction = 'L'
|
| 31 |
+
|
| 32 |
+
# 根据当前方向,获取图片
|
| 33 |
+
self.image = self.images[self.direction]
|
| 34 |
+
|
| 35 |
+
# 根据图片,获取坦克所在区域
|
| 36 |
+
self.rect = self.image.get_rect()
|
| 37 |
+
|
| 38 |
+
# 调整坦克所在区域
|
| 39 |
+
self.rect.left = left
|
| 40 |
+
self.rect.top = top
|
| 41 |
+
|
| 42 |
+
# 设置速度
|
| 43 |
+
self.speed = 5
|
| 44 |
+
|
| 45 |
+
# 坦克移动的开关
|
| 46 |
+
self.stop = True
|
| 47 |
+
|
| 48 |
+
# 是否活着
|
| 49 |
+
self.live = True
|
| 50 |
+
|
| 51 |
+
# 记录坦克上一时刻的坐标
|
| 52 |
+
self.oldLeft = self.rect.left
|
| 53 |
+
self.oldTop = self.rect.top
|
| 54 |
+
|
| 55 |
+
def move(self):
|
| 56 |
+
"""移动函数"""
|
| 57 |
+
|
| 58 |
+
# 记录坦克上一时刻的坐标
|
| 59 |
+
self.oldLeft = self.rect.left
|
| 60 |
+
self.oldTop = self.rect.top
|
| 61 |
+
|
| 62 |
+
# 判断坦克的方向,根据一定的速度,进行移动
|
| 63 |
+
if self.direction == 'L':
|
| 64 |
+
if self.rect.left > 0:
|
| 65 |
+
self.rect.left -= self.speed
|
| 66 |
+
|
| 67 |
+
elif self.direction == 'U':
|
| 68 |
+
if self.rect.top > 0:
|
| 69 |
+
self.rect.top -= self.speed
|
| 70 |
+
|
| 71 |
+
elif self.direction == 'D':
|
| 72 |
+
if self.rect.top + self.rect.height < SCREEN_HEIGHT:
|
| 73 |
+
self.rect.top += self.speed
|
| 74 |
+
|
| 75 |
+
elif self.direction == 'R':
|
| 76 |
+
if self.rect.left + self.rect.height < SCREEN_WIDTH:
|
| 77 |
+
self.rect.left += self.speed
|
| 78 |
+
|
| 79 |
+
def shot(self):
|
| 80 |
+
"""射击函数"""
|
| 81 |
+
return Bullet(self) # 返回子弹对象
|
| 82 |
+
|
| 83 |
+
def stay(self):
|
| 84 |
+
"""暂停"""
|
| 85 |
+
self.rect.left = self.oldLeft
|
| 86 |
+
self.rect.top = self.oldTop
|
| 87 |
+
|
| 88 |
+
def hitWall(self):
|
| 89 |
+
"""撞到墙体"""
|
| 90 |
+
for wall in MainGame.wallList:
|
| 91 |
+
if pygame.sprite.collide_rect(self, wall):
|
| 92 |
+
self.stay()
|
| 93 |
+
|
| 94 |
+
def displayTank(self):
|
| 95 |
+
"""展示坦克"""
|
| 96 |
+
# 获取展示的对象
|
| 97 |
+
self.image = self.images[self.direction]
|
| 98 |
+
|
| 99 |
+
# 调用blit方法展示
|
| 100 |
+
MainGame.window.blit(self.image, self.rect)
|
| 101 |
+
|
| 102 |
+
# 我方坦克
|
| 103 |
+
class MyTank(Tank):
|
| 104 |
+
def __init__(self, left, top):
|
| 105 |
+
super(MyTank, self).__init__(left, top)
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def myTank_hit_enemyTank(self):
|
| 109 |
+
"""撞到敌方坦克"""
|
| 110 |
+
# 循环遍历敌方坦克列表
|
| 111 |
+
for enemyTank in MainGame.enemyTankList:
|
| 112 |
+
if pygame.sprite.collide_rect(self, enemyTank):
|
| 113 |
+
# 暂停
|
| 114 |
+
self.stay()
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
# 敌方坦克
|
| 118 |
+
class EnemyTank(Tank):
|
| 119 |
+
def __init__(self, left, top, speed):
|
| 120 |
+
# 调用父类的初始化方法
|
| 121 |
+
super(EnemyTank, self).__init__(left, top)
|
| 122 |
+
|
| 123 |
+
# 加载敌方坦克图片集
|
| 124 |
+
self.images = {
|
| 125 |
+
'U': pygame.image.load('img/enemy1U.gif'),
|
| 126 |
+
'D': pygame.image.load('img/enemy1D.gif'),
|
| 127 |
+
'L': pygame.image.load('img/enemy1L.gif'),
|
| 128 |
+
'R': pygame.image.load('img/enemy1R.gif')
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
# 随机生成敌方坦克的方向
|
| 132 |
+
self.direction = self.randDirection()
|
| 133 |
+
|
| 134 |
+
# 根据方向获取图片
|
| 135 |
+
self.image = self.images[self.direction]
|
| 136 |
+
|
| 137 |
+
# 获取敌方坦克区域
|
| 138 |
+
self.rect = self.image.get_rect()
|
| 139 |
+
|
| 140 |
+
# 更改敌方坦克位置
|
| 141 |
+
self.rect.left = left
|
| 142 |
+
self.rect.top = top
|
| 143 |
+
|
| 144 |
+
# 速度
|
| 145 |
+
self.speed = speed
|
| 146 |
+
|
| 147 |
+
# 移动开关键
|
| 148 |
+
self.flag = True
|
| 149 |
+
|
| 150 |
+
# 增加一个步数变量 step -- 每移动 step步,改变一次方向
|
| 151 |
+
self.step = 60
|
| 152 |
+
|
| 153 |
+
def enemyTank_hit_myTank(self):
|
| 154 |
+
"""撞到我方坦克"""
|
| 155 |
+
if pygame.sprite.collide_rect(self, MainGame.my_tank):
|
| 156 |
+
# 停止
|
| 157 |
+
self.stay()
|
| 158 |
+
|
| 159 |
+
def randDirection(self):
|
| 160 |
+
"""随机生成敌方坦克的方向"""
|
| 161 |
+
num = random.randint(1, 4)
|
| 162 |
+
|
| 163 |
+
if num == 1:
|
| 164 |
+
return 'U'
|
| 165 |
+
elif num == 2:
|
| 166 |
+
return 'D'
|
| 167 |
+
elif num == 3:
|
| 168 |
+
return "L"
|
| 169 |
+
elif num == 4:
|
| 170 |
+
return 'R'
|
| 171 |
+
|
| 172 |
+
def randMove(self):
|
| 173 |
+
"""敌方坦克随机移动"""
|
| 174 |
+
|
| 175 |
+
if self.step <= 0:
|
| 176 |
+
# 修改方向
|
| 177 |
+
self.direction = self.randDirection()
|
| 178 |
+
|
| 179 |
+
# 让步数复位
|
| 180 |
+
self.step = 60
|
| 181 |
+
|
| 182 |
+
else:
|
| 183 |
+
# 移动
|
| 184 |
+
self.move()
|
| 185 |
+
|
| 186 |
+
# 让步数递减
|
| 187 |
+
self.step -= 1
|
| 188 |
+
|
| 189 |
+
def shot(self):
|
| 190 |
+
"""重写 发射函数"""
|
| 191 |
+
|
| 192 |
+
# 10% 的概率,发射子弹
|
| 193 |
+
num = random.randint(1, 100)
|
| 194 |
+
if num < 10:
|
| 195 |
+
return Bullet(self)
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
class Bullet(BaseItem):
|
| 199 |
+
"""子弹类"""
|
| 200 |
+
|
| 201 |
+
def __init__(self, tank):
|
| 202 |
+
"""初始化函数"""
|
| 203 |
+
|
| 204 |
+
# 加载子弹图片
|
| 205 |
+
self.image = pygame.image.load('img/enemymissile.gif')
|
| 206 |
+
|
| 207 |
+
# 坦克的方向决定子弹的方向
|
| 208 |
+
self.direction = tank.direction
|
| 209 |
+
|
| 210 |
+
# 获取子弹区域
|
| 211 |
+
self.rect = self.image.get_rect()
|
| 212 |
+
|
| 213 |
+
# 初始化子弹的位置 -- 不同的方向,初始化的位置也不同
|
| 214 |
+
if self.direction == 'U':
|
| 215 |
+
self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
|
| 216 |
+
self.rect.top = tank.rect.top - self.rect.height
|
| 217 |
+
|
| 218 |
+
elif self.direction == 'D':
|
| 219 |
+
self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
|
| 220 |
+
self.rect.top = tank.rect.top + tank.rect.height
|
| 221 |
+
|
| 222 |
+
elif self.direction == 'L':
|
| 223 |
+
self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2
|
| 224 |
+
self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
|
| 225 |
+
|
| 226 |
+
elif self.direction == 'R':
|
| 227 |
+
self.rect.left = tank.rect.left + tank.rect.width
|
| 228 |
+
self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
|
| 229 |
+
|
| 230 |
+
# 子弹的速度
|
| 231 |
+
self.speed = 6
|
| 232 |
+
|
| 233 |
+
# 子弹的状态 -- 是否存在
|
| 234 |
+
self.live = True
|
| 235 |
+
|
| 236 |
+
def move(self):
|
| 237 |
+
"""移动函数"""
|
| 238 |
+
|
| 239 |
+
if self.direction == 'U':
|
| 240 |
+
if self.rect.top > 0:
|
| 241 |
+
self.rect.top -= self.speed
|
| 242 |
+
else:
|
| 243 |
+
# 修改子弹的状态
|
| 244 |
+
self.live = False
|
| 245 |
+
|
| 246 |
+
elif self.direction == 'R':
|
| 247 |
+
if self.rect.left + self.rect.width < SCREEN_WIDTH:
|
| 248 |
+
self.rect.left += self.speed
|
| 249 |
+
else:
|
| 250 |
+
# 修改子弹的状态
|
| 251 |
+
self.live = False
|
| 252 |
+
|
| 253 |
+
elif self.direction == 'D':
|
| 254 |
+
if self.rect.top + self.rect.height < SCREEN_HEIGHT:
|
| 255 |
+
self.rect.top += self.speed
|
| 256 |
+
else:
|
| 257 |
+
# 修改子弹的状态
|
| 258 |
+
self.live = False
|
| 259 |
+
|
| 260 |
+
elif self.direction == 'L':
|
| 261 |
+
if self.rect.left > 0:
|
| 262 |
+
self.rect.left -= self.speed
|
| 263 |
+
else:
|
| 264 |
+
# 修改子弹的状态
|
| 265 |
+
self.live = False
|
| 266 |
+
|
| 267 |
+
def hitWall(self):
|
| 268 |
+
"""子弹碰到墙体"""
|
| 269 |
+
|
| 270 |
+
# 循环遍历墙壁列表
|
| 271 |
+
for wall in MainGame.wallList:
|
| 272 |
+
|
| 273 |
+
# 如果相撞
|
| 274 |
+
if pygame.sprite.collide_rect(self, wall):
|
| 275 |
+
|
| 276 |
+
# 修改子弹的生存状态,让子弹消失
|
| 277 |
+
self.live = False
|
| 278 |
+
|
| 279 |
+
# 墙壁的生命值减小
|
| 280 |
+
wall.hp -= 1
|
| 281 |
+
|
| 282 |
+
# 墙壁被破坏严重时,则消失
|
| 283 |
+
if wall.hp <= 0:
|
| 284 |
+
# 修改墙壁的生存状态
|
| 285 |
+
wall.live = False
|
| 286 |
+
|
| 287 |
+
def displayBullet(self):
|
| 288 |
+
"""展示子弹"""
|
| 289 |
+
# 将图片surface加载到窗口
|
| 290 |
+
MainGame.window.blit(self.image, self.rect)
|
| 291 |
+
|
| 292 |
+
def myBullet_hit_enemyTank(self):
|
| 293 |
+
"""我方子弹与敌方坦克的碰撞"""
|
| 294 |
+
|
| 295 |
+
# 循环遍历敌方坦克列表
|
| 296 |
+
for enemyTank in MainGame.enemyTankList:
|
| 297 |
+
|
| 298 |
+
# 如果相撞
|
| 299 |
+
if pygame.sprite.collide_rect(enemyTank, self):
|
| 300 |
+
# 修改敌方坦克和我方子弹的状态
|
| 301 |
+
enemyTank.live = False
|
| 302 |
+
self.live = False
|
| 303 |
+
|
| 304 |
+
# 创建爆炸对象
|
| 305 |
+
explode = Explode(enemyTank)
|
| 306 |
+
|
| 307 |
+
# 将爆炸对象添加到爆炸列表中
|
| 308 |
+
MainGame.explodeList.append(explode)
|
| 309 |
+
|
| 310 |
+
def enemyBullet_hit_myTank(self):
|
| 311 |
+
"""敌方子弹与我方坦克的碰撞"""
|
| 312 |
+
if MainGame.my_tank and MainGame.my_tank.live:
|
| 313 |
+
if pygame.sprite.collide_rect(MainGame.my_tank, self):
|
| 314 |
+
# 产生爆炸对象
|
| 315 |
+
explode = Explode(MainGame.my_tank)
|
| 316 |
+
|
| 317 |
+
# 将爆炸对象添加到爆炸列表中
|
| 318 |
+
MainGame.explodeList.append(explode)
|
| 319 |
+
|
| 320 |
+
# 修改敌方子弹与我方坦克的状态
|
| 321 |
+
self.live = False
|
| 322 |
+
MainGame.my_tank.live = False
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
class Wall():
|
| 326 |
+
def __init__(self, left, top):
|
| 327 |
+
# 加载墙壁图片
|
| 328 |
+
self.image = pygame.image.load('img/steels.gif')
|
| 329 |
+
|
| 330 |
+
# 获取墙壁的区域
|
| 331 |
+
self.rect = self.image.get_rect()
|
| 332 |
+
|
| 333 |
+
# 初始化墙体位置
|
| 334 |
+
self.rect.left = left
|
| 335 |
+
self.rect.top = top
|
| 336 |
+
|
| 337 |
+
# 标记是否存活
|
| 338 |
+
self.live = True
|
| 339 |
+
|
| 340 |
+
# 设置生命值
|
| 341 |
+
self.hp = 3
|
| 342 |
+
|
| 343 |
+
def displayWall(self):
|
| 344 |
+
"""展示墙壁"""
|
| 345 |
+
MainGame.window.blit(self.image, self.rect)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
class Explode():
|
| 349 |
+
def __init__(self, tank):
|
| 350 |
+
"""初始化函数:传入爆炸的坦克"""
|
| 351 |
+
|
| 352 |
+
# 获取爆炸位置
|
| 353 |
+
self.rect = tank.rect
|
| 354 |
+
|
| 355 |
+
# 爆炸的图片
|
| 356 |
+
self.images = [
|
| 357 |
+
pygame.image.load('img/blast0.gif'),
|
| 358 |
+
pygame.image.load('img/blast1.gif'),
|
| 359 |
+
pygame.image.load('img/blast2.gif'),
|
| 360 |
+
pygame.image.load('img/blast3.gif'),
|
| 361 |
+
pygame.image.load('img/blast4.gif'),
|
| 362 |
+
]
|
| 363 |
+
|
| 364 |
+
# 索引 -- 依次使用不同的爆炸图片
|
| 365 |
+
self.step = 0
|
| 366 |
+
|
| 367 |
+
self.image = self.images[self.step]
|
| 368 |
+
|
| 369 |
+
# 是否进行爆炸
|
| 370 |
+
self.live = True
|
| 371 |
+
|
| 372 |
+
def displayExplode(self):
|
| 373 |
+
"""展示爆炸"""
|
| 374 |
+
if self.step < len(self.images):
|
| 375 |
+
|
| 376 |
+
# 根据索引获取爆炸图片
|
| 377 |
+
self.image = self.images[self.step]
|
| 378 |
+
self.step += 1
|
| 379 |
+
|
| 380 |
+
# 展示爆炸图片
|
| 381 |
+
MainGame.window.blit(self.image, self.rect)
|
| 382 |
+
|
| 383 |
+
else:
|
| 384 |
+
# 修改爆炸对象的状态
|
| 385 |
+
self.live = False
|
| 386 |
+
self.step = 0
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
class Music():
|
| 390 |
+
def __init__(self, filename):
|
| 391 |
+
"""初始化函数"""
|
| 392 |
+
|
| 393 |
+
# 获取音乐名称
|
| 394 |
+
self.filename = filename
|
| 395 |
+
|
| 396 |
+
# 初始化背景音乐
|
| 397 |
+
pygame.mixer.init()
|
| 398 |
+
|
| 399 |
+
# 加载背景音乐
|
| 400 |
+
pygame.mixer.music.load(self.filename)
|
| 401 |
+
|
| 402 |
+
def play(self):
|
| 403 |
+
"""播放音乐"""
|
| 404 |
+
pygame.mixer.music.play()
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
class MainGame():
|
| 408 |
+
"""
|
| 409 |
+
主游戏类:
|
| 410 |
+
游戏整体运行的逻辑
|
| 411 |
+
"""
|
| 412 |
+
|
| 413 |
+
# 窗口
|
| 414 |
+
window = None
|
| 415 |
+
|
| 416 |
+
# 我方坦克
|
| 417 |
+
my_tank = None
|
| 418 |
+
|
| 419 |
+
# 存储敌方坦克的列表
|
| 420 |
+
enemyTankList = []
|
| 421 |
+
|
| 422 |
+
# 定义敌方坦克的数量
|
| 423 |
+
enemyTankCount = 5
|
| 424 |
+
|
| 425 |
+
# 存储我方子弹的列表
|
| 426 |
+
myBulletList = []
|
| 427 |
+
|
| 428 |
+
# 存储敌方子弹的列表
|
| 429 |
+
enemyBulletList = []
|
| 430 |
+
|
| 431 |
+
# 存储爆炸效果的列表
|
| 432 |
+
explodeList = []
|
| 433 |
+
|
| 434 |
+
# 存储墙壁的列表
|
| 435 |
+
wallList = []
|
| 436 |
+
|
| 437 |
+
def __init__(self):
|
| 438 |
+
"""初始化"""
|
| 439 |
+
pass
|
| 440 |
+
|
| 441 |
+
def startGame(self):
|
| 442 |
+
"""开始游戏"""
|
| 443 |
+
|
| 444 |
+
# 初始化 pygame
|
| 445 |
+
pygame.display.init()
|
| 446 |
+
|
| 447 |
+
# 设置窗口的大小及显示
|
| 448 |
+
MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
|
| 449 |
+
|
| 450 |
+
# 初始化 我方坦克
|
| 451 |
+
self.createMytank()
|
| 452 |
+
|
| 453 |
+
# 初始化敌方坦克,并将敌方坦克添加到列表中
|
| 454 |
+
self.createEnemyTank()
|
| 455 |
+
|
| 456 |
+
# 初始化墙壁
|
| 457 |
+
self.createWall()
|
| 458 |
+
|
| 459 |
+
# 设置窗口的标题
|
| 460 |
+
pygame.display.set_caption('坦克大战1.03')
|
| 461 |
+
|
| 462 |
+
while True:
|
| 463 |
+
|
| 464 |
+
# 让坦克移动的速度慢一点
|
| 465 |
+
time.sleep(0.02)
|
| 466 |
+
|
| 467 |
+
# 清空主窗口
|
| 468 |
+
MainGame.window.fill(BG_COLOR)
|
| 469 |
+
|
| 470 |
+
# 获取事件
|
| 471 |
+
self.getEvent()
|
| 472 |
+
|
| 473 |
+
# 绘制文字
|
| 474 |
+
MainGame.window.blit(self.getTextSuface(
|
| 475 |
+
'敌方坦克剩余数量%d' % len(MainGame.enemyTankList)), (10, 10))
|
| 476 |
+
|
| 477 |
+
## 调用坦克显示的方法
|
| 478 |
+
if MainGame.my_tank and MainGame.my_tank.live:
|
| 479 |
+
# 我方坦克存活
|
| 480 |
+
MainGame.my_tank.displayTank()
|
| 481 |
+
else:
|
| 482 |
+
# 我方坦克死亡,删除我方坦克
|
| 483 |
+
del MainGame.my_tank
|
| 484 |
+
MainGame.my_tank = None
|
| 485 |
+
|
| 486 |
+
# 循环遍历敌方坦克列表,展示敌方坦克
|
| 487 |
+
self.blitEnemyTank()
|
| 488 |
+
|
| 489 |
+
# 循环遍历显示我方坦克的子弹
|
| 490 |
+
self.blitMyBullet()
|
| 491 |
+
|
| 492 |
+
# 循环遍历敌方子弹列表,展示敌方子弹
|
| 493 |
+
self.blitEnemyBullet()
|
| 494 |
+
|
| 495 |
+
# 循环遍历爆炸列表,展示爆炸效果
|
| 496 |
+
self.blitExplode()
|
| 497 |
+
|
| 498 |
+
# 循环遍历墙壁列表,展示墙壁
|
| 499 |
+
self.blitWall()
|
| 500 |
+
|
| 501 |
+
# 调用移动方法
|
| 502 |
+
if MainGame.my_tank and MainGame.my_tank.live:
|
| 503 |
+
# 如果坦克的开关是开启,才可以移动
|
| 504 |
+
if not MainGame.my_tank.stop:
|
| 505 |
+
MainGame.my_tank.move()
|
| 506 |
+
|
| 507 |
+
# 检测我方坦克是否与墙壁发生碰撞
|
| 508 |
+
MainGame.my_tank.hitWall()
|
| 509 |
+
|
| 510 |
+
# 检测我方坦克是否与敌方坦克发生碰撞
|
| 511 |
+
MainGame.my_tank.myTank_hit_enemyTank()
|
| 512 |
+
|
| 513 |
+
# 更新屏幕
|
| 514 |
+
pygame.display.update()
|
| 515 |
+
|
| 516 |
+
def blitWall(self):
|
| 517 |
+
"""循环遍历墙壁列表,展示墙壁"""
|
| 518 |
+
for wall in MainGame.wallList:
|
| 519 |
+
# 判断墙壁是否存活
|
| 520 |
+
if wall.live:
|
| 521 |
+
# 调用墙壁的显示方法
|
| 522 |
+
wall.displayWall()
|
| 523 |
+
else:
|
| 524 |
+
# 从墙壁列表移出
|
| 525 |
+
MainGame.wallList.remove(wall)
|
| 526 |
+
|
| 527 |
+
def createWall(self):
|
| 528 |
+
"""初始化墙壁"""
|
| 529 |
+
for i in range(6):
|
| 530 |
+
# 创建墙壁
|
| 531 |
+
wall = Wall(i * 130, 220)
|
| 532 |
+
# 将墙壁添加到列表中
|
| 533 |
+
MainGame.wallList.append(wall)
|
| 534 |
+
|
| 535 |
+
def createMytank(self):
|
| 536 |
+
"""创建我方坦克"""
|
| 537 |
+
MainGame.my_tank = MyTank(350, 300)
|
| 538 |
+
|
| 539 |
+
# 创建 Music对象
|
| 540 |
+
music = Music('img/start.wav')
|
| 541 |
+
|
| 542 |
+
# 播放音乐
|
| 543 |
+
music.play()
|
| 544 |
+
|
| 545 |
+
def createEnemyTank(self):
|
| 546 |
+
"""创建敌方坦克"""
|
| 547 |
+
top = 100
|
| 548 |
+
|
| 549 |
+
# 循环生成敌方坦克
|
| 550 |
+
for i in range(MainGame.enemyTankCount):
|
| 551 |
+
left = random.randint(0, 600)
|
| 552 |
+
speed = random.randint(1, 4)
|
| 553 |
+
enemy = EnemyTank(left, top, speed)
|
| 554 |
+
MainGame.enemyTankList.append(enemy)
|
| 555 |
+
|
| 556 |
+
def blitExplode(self):
|
| 557 |
+
"""展示爆炸效果"""
|
| 558 |
+
|
| 559 |
+
# 遍历爆炸列表
|
| 560 |
+
for explode in MainGame.explodeList:
|
| 561 |
+
if explode.live:
|
| 562 |
+
# 展示爆炸效果
|
| 563 |
+
explode.displayExplode()
|
| 564 |
+
else:
|
| 565 |
+
# 在爆炸列表中移除
|
| 566 |
+
MainGame.explodeList.remove(explode)
|
| 567 |
+
|
| 568 |
+
def blitEnemyTank(self):
|
| 569 |
+
"""展示敌方坦克"""
|
| 570 |
+
for enemyTank in MainGame.enemyTankList:
|
| 571 |
+
|
| 572 |
+
# 如果当前敌方坦克还活着
|
| 573 |
+
if enemyTank.live:
|
| 574 |
+
|
| 575 |
+
# 展示
|
| 576 |
+
enemyTank.displayTank()
|
| 577 |
+
|
| 578 |
+
# 移动
|
| 579 |
+
enemyTank.randMove()
|
| 580 |
+
|
| 581 |
+
# 调用检测是否与墙壁碰撞
|
| 582 |
+
enemyTank.hitWall()
|
| 583 |
+
|
| 584 |
+
# 检测敌方坦克是否与我方坦克发生碰撞
|
| 585 |
+
if MainGame.my_tank and MainGame.my_tank.live:
|
| 586 |
+
enemyTank.enemyTank_hit_myTank()
|
| 587 |
+
|
| 588 |
+
# 发射子弹
|
| 589 |
+
enemyBullet = enemyTank.shot()
|
| 590 |
+
|
| 591 |
+
# 敌方子弹是否是None,如果不为None则添加到敌方子弹列表中
|
| 592 |
+
if enemyBullet:
|
| 593 |
+
# 将敌方子弹存储到敌方子弹列表中
|
| 594 |
+
MainGame.enemyBulletList.append(enemyBullet)
|
| 595 |
+
|
| 596 |
+
# 如果死亡,则从敌方坦克列表中移除
|
| 597 |
+
else:
|
| 598 |
+
MainGame.enemyTankList.remove(enemyTank)
|
| 599 |
+
|
| 600 |
+
def blitMyBullet(self):
|
| 601 |
+
"""展示我方子弹"""
|
| 602 |
+
|
| 603 |
+
# 遍历子弹列表
|
| 604 |
+
for myBullet in MainGame.myBulletList:
|
| 605 |
+
|
| 606 |
+
# 子弹如果存在,则展示
|
| 607 |
+
if myBullet.live:
|
| 608 |
+
|
| 609 |
+
# 展示子弹
|
| 610 |
+
myBullet.displayBullet()
|
| 611 |
+
|
| 612 |
+
# 移动子弹
|
| 613 |
+
myBullet.move()
|
| 614 |
+
|
| 615 |
+
# 判断我方子弹是否击中敌方
|
| 616 |
+
myBullet.myBullet_hit_enemyTank()
|
| 617 |
+
|
| 618 |
+
# 判断我方子弹是否击中墙壁
|
| 619 |
+
myBullet.hitWall()
|
| 620 |
+
|
| 621 |
+
# 子弹如果不存在,则从列表中删除
|
| 622 |
+
else:
|
| 623 |
+
MainGame.myBulletList.remove(myBullet)
|
| 624 |
+
|
| 625 |
+
def blitEnemyBullet(self):
|
| 626 |
+
"""展示敌方子弹"""
|
| 627 |
+
|
| 628 |
+
# 遍历敌方子弹列表
|
| 629 |
+
for enemyBullet in MainGame.enemyBulletList:
|
| 630 |
+
|
| 631 |
+
# 如果敌方子弹存在
|
| 632 |
+
if enemyBullet.live:
|
| 633 |
+
|
| 634 |
+
# 展示敌方子弹
|
| 635 |
+
enemyBullet.displayBullet()
|
| 636 |
+
|
| 637 |
+
# 移动子弹
|
| 638 |
+
enemyBullet.move()
|
| 639 |
+
|
| 640 |
+
# 敌方子弹 是否击中 我方坦克
|
| 641 |
+
enemyBullet.enemyBullet_hit_myTank()
|
| 642 |
+
|
| 643 |
+
# 敌方子弹是否击中墙壁
|
| 644 |
+
enemyBullet.hitWall()
|
| 645 |
+
|
| 646 |
+
# 如果子弹不存在,则从列表中移除
|
| 647 |
+
else:
|
| 648 |
+
MainGame.enemyBulletList.remove(enemyBullet)
|
| 649 |
+
|
| 650 |
+
def endGame(self):
|
| 651 |
+
"""结束游戏"""
|
| 652 |
+
|
| 653 |
+
print('谢谢使用,欢迎再次使用')
|
| 654 |
+
pygame.quit()
|
| 655 |
+
exit()
|
| 656 |
+
|
| 657 |
+
def getTextSuface(self, text):
|
| 658 |
+
"""左上角添加文字"""
|
| 659 |
+
|
| 660 |
+
# 初始化字体模块
|
| 661 |
+
pygame.font.init()
|
| 662 |
+
|
| 663 |
+
# 获取字体Font对象
|
| 664 |
+
font = pygame.font.SysFont('ヒラキノ角コシックw8', 18)
|
| 665 |
+
|
| 666 |
+
# 绘制文字信息
|
| 667 |
+
textSurface = font.render(text, True, TEXT_COLOR)
|
| 668 |
+
|
| 669 |
+
return textSurface
|
| 670 |
+
|
| 671 |
+
def getEvent(self):
|
| 672 |
+
"""获取事件"""
|
| 673 |
+
|
| 674 |
+
# 获取所有事件
|
| 675 |
+
eventList = pygame.event.get()
|
| 676 |
+
|
| 677 |
+
# 遍历事件
|
| 678 |
+
for event in eventList:
|
| 679 |
+
|
| 680 |
+
# 鼠标点击退出,则结束游戏
|
| 681 |
+
if event.type == pygame.QUIT:
|
| 682 |
+
self.endGame()
|
| 683 |
+
|
| 684 |
+
# 如果是键盘事件
|
| 685 |
+
if event.type == pygame.KEYDOWN:
|
| 686 |
+
|
| 687 |
+
# 当我方坦克死亡
|
| 688 |
+
if not MainGame.my_tank:
|
| 689 |
+
|
| 690 |
+
# 如果按下 Esc键
|
| 691 |
+
if event.key == pygame.K_ESCAPE:
|
| 692 |
+
# 我方坦克重生
|
| 693 |
+
self.createMytank()
|
| 694 |
+
|
| 695 |
+
# 如果我方坦克存活
|
| 696 |
+
if MainGame.my_tank and MainGame.my_tank.live:
|
| 697 |
+
|
| 698 |
+
# 按左键
|
| 699 |
+
if event.key == pygame.K_LEFT:
|
| 700 |
+
# 切换方向
|
| 701 |
+
MainGame.my_tank.direction = 'L'
|
| 702 |
+
|
| 703 |
+
# 修改坦克的开关状态
|
| 704 |
+
MainGame.my_tank.stop = False
|
| 705 |
+
|
| 706 |
+
|
| 707 |
+
# 按右键
|
| 708 |
+
elif event.key == pygame.K_RIGHT:
|
| 709 |
+
# 切换方向
|
| 710 |
+
MainGame.my_tank.direction = 'R'
|
| 711 |
+
|
| 712 |
+
# 修改坦克的开关状态
|
| 713 |
+
MainGame.my_tank.stop = False
|
| 714 |
+
|
| 715 |
+
|
| 716 |
+
# 按上键
|
| 717 |
+
elif event.key == pygame.K_UP:
|
| 718 |
+
# 切换方向
|
| 719 |
+
MainGame.my_tank.direction = 'U'
|
| 720 |
+
|
| 721 |
+
# 修改坦克的开关状态
|
| 722 |
+
MainGame.my_tank.stop = False
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
# 按下键
|
| 726 |
+
elif event.key == pygame.K_DOWN:
|
| 727 |
+
# 切换方向
|
| 728 |
+
MainGame.my_tank.direction = 'D'
|
| 729 |
+
|
| 730 |
+
# 修改坦克的开关状态
|
| 731 |
+
MainGame.my_tank.stop = False
|
| 732 |
+
|
| 733 |
+
|
| 734 |
+
# 按空格
|
| 735 |
+
elif event.key == pygame.K_SPACE:
|
| 736 |
+
"""发射子弹"""
|
| 737 |
+
|
| 738 |
+
# 最多发射 3发子弹
|
| 739 |
+
if len(MainGame.myBulletList) < 3:
|
| 740 |
+
# 创建子弹
|
| 741 |
+
myBullet = Bullet(MainGame.my_tank)
|
| 742 |
+
|
| 743 |
+
# 将子弹添加进列表
|
| 744 |
+
MainGame.myBulletList.append(myBullet)
|
| 745 |
+
|
| 746 |
+
# 添加音效
|
| 747 |
+
music = Music('img/hit.wav')
|
| 748 |
+
music.play()
|
| 749 |
+
|
| 750 |
+
# 松开方向键
|
| 751 |
+
if event.type == pygame.KEYUP:
|
| 752 |
+
"""坦克停止移动,修改坦克的开关状态"""
|
| 753 |
+
|
| 754 |
+
# 判断松开的键是上、下、左、右时候才停止坦克移动
|
| 755 |
+
if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
|
| 756 |
+
if MainGame.my_tank and MainGame.my_tank.live:
|
| 757 |
+
MainGame.my_tank.stop = True
|
| 758 |
+
|
| 759 |
+
if __name__ == '__main__':
|
| 760 |
+
MainGame().startGame()
|
06_PyQt5控件.ipynb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b5efa7da262aeda4dc2d5f5ddfebe2ded5ac6b1bcbd10b844630ded7afdba8d0
|
| 3 |
+
size 11522617
|
06_PyQt6-PySide6.ipynb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:79420cd37515a89456d24ac84cc59a3e74e4034cb84396b8d8af9123fdc22707
|
| 3 |
+
size 118934552
|
06_Pygame实战:AI贪吃蛇.ipynb
ADDED
|
@@ -0,0 +1,942 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": 1,
|
| 6 |
+
"id": "bc8cda21",
|
| 7 |
+
"metadata": {
|
| 8 |
+
"ExecuteTime": {
|
| 9 |
+
"end_time": "2023-10-05T14:06:32.358450Z",
|
| 10 |
+
"start_time": "2023-10-05T14:06:09.861617Z"
|
| 11 |
+
}
|
| 12 |
+
},
|
| 13 |
+
"outputs": [
|
| 14 |
+
{
|
| 15 |
+
"name": "stdout",
|
| 16 |
+
"output_type": "stream",
|
| 17 |
+
"text": [
|
| 18 |
+
"pygame 2.1.0 (SDL 2.0.16, Python 3.9.12)\n",
|
| 19 |
+
"Hello from the pygame community. https://www.pygame.org/contribute.html\n",
|
| 20 |
+
"安全路径吃食物\n",
|
| 21 |
+
"安全路径吃食物\n",
|
| 22 |
+
"安全路径吃食物\n",
|
| 23 |
+
"安全路径吃食物\n",
|
| 24 |
+
"安全路径吃食物\n",
|
| 25 |
+
"安全路径吃食物\n",
|
| 26 |
+
"安全路径吃食物\n",
|
| 27 |
+
"安全路径吃食物\n",
|
| 28 |
+
"安全路径吃食物\n",
|
| 29 |
+
"安全路径吃食物\n",
|
| 30 |
+
"安全路径吃食物\n",
|
| 31 |
+
"安全路径吃食物\n",
|
| 32 |
+
"安全路径吃食物\n",
|
| 33 |
+
"安全路径吃食物\n",
|
| 34 |
+
"安全路径吃食物\n",
|
| 35 |
+
"安全路径吃食物\n",
|
| 36 |
+
"安全路径吃食物\n",
|
| 37 |
+
"安全路径吃食物\n",
|
| 38 |
+
"安全路径吃食物\n",
|
| 39 |
+
"安全路径吃食物\n",
|
| 40 |
+
"安全路径吃食物\n",
|
| 41 |
+
"安全路径吃食物\n",
|
| 42 |
+
"安全路径吃食物\n",
|
| 43 |
+
"安全路径吃食物\n",
|
| 44 |
+
"安全路径吃食物\n",
|
| 45 |
+
"安全路径吃食物\n",
|
| 46 |
+
"安全路径吃食物\n",
|
| 47 |
+
"安全路径吃食物\n",
|
| 48 |
+
"安全路径吃食物\n",
|
| 49 |
+
"安全路径吃食物\n",
|
| 50 |
+
"安全路径吃食物\n",
|
| 51 |
+
"安全路径吃食物\n",
|
| 52 |
+
"安全路径吃食物\n",
|
| 53 |
+
"安全路径吃食物\n",
|
| 54 |
+
"安全路径吃食物\n",
|
| 55 |
+
"安全路径吃食物\n",
|
| 56 |
+
"安全路径吃食物\n",
|
| 57 |
+
"安全路径吃食物\n",
|
| 58 |
+
"安全路径吃食物\n",
|
| 59 |
+
"安全路径吃食物\n",
|
| 60 |
+
"安全路径吃食物\n",
|
| 61 |
+
"安全路径吃食物\n",
|
| 62 |
+
"安全路径吃食物\n",
|
| 63 |
+
"安全路径吃食物\n",
|
| 64 |
+
"安全路径吃食物\n",
|
| 65 |
+
"安全路径吃食物\n",
|
| 66 |
+
"安全路径吃食物\n",
|
| 67 |
+
"安全路径吃食物\n",
|
| 68 |
+
"安全路径吃食物\n",
|
| 69 |
+
"安全路径吃食物\n",
|
| 70 |
+
"安全路径吃食物\n",
|
| 71 |
+
"安全路径吃食物\n",
|
| 72 |
+
"安全路径吃食物\n",
|
| 73 |
+
"安全路径吃食物\n",
|
| 74 |
+
"安全路径吃食物\n",
|
| 75 |
+
"安全路径吃食物\n",
|
| 76 |
+
"安全路径吃食物\n",
|
| 77 |
+
"安全路径吃食物\n",
|
| 78 |
+
"安全路径吃食物\n",
|
| 79 |
+
"安全路径吃食物\n",
|
| 80 |
+
"安全路径吃食物\n",
|
| 81 |
+
"安全路径吃食物\n",
|
| 82 |
+
"安全路径吃食物\n",
|
| 83 |
+
"安全路径吃食物\n",
|
| 84 |
+
"安全路径吃食物\n",
|
| 85 |
+
"安全路径吃食物\n",
|
| 86 |
+
"安全路径吃食物\n",
|
| 87 |
+
"安全路径吃食物\n",
|
| 88 |
+
"安全路径吃食物\n",
|
| 89 |
+
"安全路径吃食物\n",
|
| 90 |
+
"安全路径吃食物\n",
|
| 91 |
+
"安全路径吃食物\n",
|
| 92 |
+
"安全路径吃食物\n",
|
| 93 |
+
"安全路径吃食物\n",
|
| 94 |
+
"安全路径吃食物\n",
|
| 95 |
+
"安全路径吃食物\n",
|
| 96 |
+
"安全路径吃食物\n",
|
| 97 |
+
"安全路径吃食物\n",
|
| 98 |
+
"安全路径吃食物\n",
|
| 99 |
+
"安全路径吃食物\n",
|
| 100 |
+
"安全路径吃食物\n",
|
| 101 |
+
"安全路径吃食物\n",
|
| 102 |
+
"安全路径吃食物\n",
|
| 103 |
+
"安全路径吃食物\n",
|
| 104 |
+
"安全路径吃食物\n",
|
| 105 |
+
"安全路径吃食物\n",
|
| 106 |
+
"安全路径吃食物\n",
|
| 107 |
+
"安全路径吃食物\n",
|
| 108 |
+
"安全路径吃食物\n",
|
| 109 |
+
"安全路径吃食物\n",
|
| 110 |
+
"安全路径吃食物\n",
|
| 111 |
+
"安全路径吃食物\n",
|
| 112 |
+
"安全路径吃食物\n",
|
| 113 |
+
"安全路径吃食物\n",
|
| 114 |
+
"安全路径吃食物\n",
|
| 115 |
+
"安全路径吃食物\n",
|
| 116 |
+
"安全路径吃食物\n",
|
| 117 |
+
"安全路径吃食物\n",
|
| 118 |
+
"安全路径吃食物\n",
|
| 119 |
+
"安全路径吃食物\n",
|
| 120 |
+
"安全路径吃食物\n",
|
| 121 |
+
"安全路径吃食物\n",
|
| 122 |
+
"安全路径吃食物\n",
|
| 123 |
+
"安全路径吃食物\n",
|
| 124 |
+
"安全路径吃食物\n",
|
| 125 |
+
"安全路径吃食物\n",
|
| 126 |
+
"安全路径吃食物\n",
|
| 127 |
+
"安全路径吃食物\n",
|
| 128 |
+
"安全路径吃食物\n",
|
| 129 |
+
"安全路径吃食物\n",
|
| 130 |
+
"安全路径吃食物\n",
|
| 131 |
+
"安全路径吃食物\n",
|
| 132 |
+
"安全路径吃食物\n",
|
| 133 |
+
"安全路径吃食物\n",
|
| 134 |
+
"安全路径吃食物\n",
|
| 135 |
+
"安全路径吃食物\n",
|
| 136 |
+
"安全路径吃食物\n",
|
| 137 |
+
"安全路径吃食物\n",
|
| 138 |
+
"安全路径吃食物\n",
|
| 139 |
+
"安全路径吃食物\n",
|
| 140 |
+
"安全路径吃食物\n",
|
| 141 |
+
"安全路径吃食物\n",
|
| 142 |
+
"安全路径吃食物\n",
|
| 143 |
+
"安全路径吃食物\n",
|
| 144 |
+
"安全路径吃食物\n",
|
| 145 |
+
"安全路径吃食物\n",
|
| 146 |
+
"安全路径吃食物\n",
|
| 147 |
+
"安全路径吃食物\n",
|
| 148 |
+
"安全路径吃食物\n",
|
| 149 |
+
"安全路径吃食物\n",
|
| 150 |
+
"安全路径吃食物\n",
|
| 151 |
+
"安全路径吃食物\n",
|
| 152 |
+
"安全路径吃食物\n",
|
| 153 |
+
"安全路径吃食物\n",
|
| 154 |
+
"安全路径吃食物\n",
|
| 155 |
+
"安全路径吃食物\n",
|
| 156 |
+
"安全路径吃食物\n",
|
| 157 |
+
"安全路径吃食物\n",
|
| 158 |
+
"安全路径吃食物\n",
|
| 159 |
+
"安全路径吃食物\n",
|
| 160 |
+
"安全路径吃食物\n",
|
| 161 |
+
"安全路径吃食物\n",
|
| 162 |
+
"安全路径吃食物\n",
|
| 163 |
+
"安全路径吃食物\n",
|
| 164 |
+
"安全路径吃食物\n",
|
| 165 |
+
"安全路径吃食物\n",
|
| 166 |
+
"安全路径吃食物\n",
|
| 167 |
+
"安全路径吃食物\n",
|
| 168 |
+
"安全路径吃食物\n",
|
| 169 |
+
"安全路径吃食物\n",
|
| 170 |
+
"安全路径吃食物\n",
|
| 171 |
+
"安全路径吃食物\n",
|
| 172 |
+
"安全路径吃食物\n",
|
| 173 |
+
"安全路径吃食物\n",
|
| 174 |
+
"安全路径吃食物\n",
|
| 175 |
+
"安全路径吃食物\n",
|
| 176 |
+
"安全路径吃食物\n",
|
| 177 |
+
"安全路径吃食物\n",
|
| 178 |
+
"安全路径吃食物\n",
|
| 179 |
+
"安全路径吃食物\n",
|
| 180 |
+
"安全路径吃食物\n",
|
| 181 |
+
"安全路径吃食物\n",
|
| 182 |
+
"安全路径吃食物\n",
|
| 183 |
+
"安全路径吃食物\n",
|
| 184 |
+
"安全路径吃食物\n",
|
| 185 |
+
"安全路径吃食物\n",
|
| 186 |
+
"安全路径吃食物\n",
|
| 187 |
+
"安全路径吃食物\n",
|
| 188 |
+
"安全路径吃食物\n",
|
| 189 |
+
"安全路径吃食物\n",
|
| 190 |
+
"安全路径吃食物\n",
|
| 191 |
+
"安全路径吃食物\n",
|
| 192 |
+
"安全路径吃食物\n",
|
| 193 |
+
"安全路径吃食物\n",
|
| 194 |
+
"安全路径吃食物\n",
|
| 195 |
+
"安全路径吃食物\n",
|
| 196 |
+
"安全路径吃食物\n",
|
| 197 |
+
"安全路径吃食物\n",
|
| 198 |
+
"安全路径吃食物\n",
|
| 199 |
+
"安全路径吃食物\n",
|
| 200 |
+
"安全路径吃食物\n",
|
| 201 |
+
"安全路径吃食物\n",
|
| 202 |
+
"安全路径吃食物\n",
|
| 203 |
+
"安全路径吃食物\n",
|
| 204 |
+
"安全路径吃食物\n",
|
| 205 |
+
"安全路径吃食物\n",
|
| 206 |
+
"安全路径吃食物\n",
|
| 207 |
+
"安全路径吃食物\n",
|
| 208 |
+
"安全路径吃食物\n",
|
| 209 |
+
"安全路径吃食物\n",
|
| 210 |
+
"安全路径吃食物\n",
|
| 211 |
+
"安全路径吃食物\n",
|
| 212 |
+
"安全路径吃食物\n",
|
| 213 |
+
"安全路径吃食物\n",
|
| 214 |
+
"安全路径吃食物\n",
|
| 215 |
+
"安全路径吃食物\n",
|
| 216 |
+
"安全路径吃食物\n",
|
| 217 |
+
"安全路径吃食物\n",
|
| 218 |
+
"安全路径吃食物\n",
|
| 219 |
+
"安全路径吃食物\n",
|
| 220 |
+
"安全路径吃食物\n",
|
| 221 |
+
"安全路径吃食物\n",
|
| 222 |
+
"安全路径吃食物\n",
|
| 223 |
+
"安全路径吃食物\n",
|
| 224 |
+
"安全路径吃食物\n",
|
| 225 |
+
"安全路径吃食物\n",
|
| 226 |
+
"安全路径吃食物\n",
|
| 227 |
+
"安全路径吃食物\n",
|
| 228 |
+
"安全路径吃食物\n",
|
| 229 |
+
"安全路径吃食物\n",
|
| 230 |
+
"安全路径吃食物\n",
|
| 231 |
+
"安全路径吃食物\n",
|
| 232 |
+
"安全路径吃食物\n",
|
| 233 |
+
"安全路径吃食物\n",
|
| 234 |
+
"安全路径吃食物\n",
|
| 235 |
+
"安全路径吃食物\n",
|
| 236 |
+
"安全路径吃食物\n",
|
| 237 |
+
"安全路径吃食物\n",
|
| 238 |
+
"安全路径吃食物\n",
|
| 239 |
+
"安全路径吃食物\n",
|
| 240 |
+
"安全路径吃食物\n",
|
| 241 |
+
"安全路径吃食物\n",
|
| 242 |
+
"安全路径吃食物\n",
|
| 243 |
+
"安全路径吃食物\n",
|
| 244 |
+
"安全路径吃食物\n",
|
| 245 |
+
"安全路径吃食物\n",
|
| 246 |
+
"安全路径吃食物\n",
|
| 247 |
+
"安全路径吃食物\n",
|
| 248 |
+
"安全路径吃食物\n",
|
| 249 |
+
"安全路径吃食物\n",
|
| 250 |
+
"安全路径吃食物\n",
|
| 251 |
+
"安全路径吃食物\n",
|
| 252 |
+
"安全路径吃食物\n",
|
| 253 |
+
"安全路径吃食物\n",
|
| 254 |
+
"安全路径吃食物\n",
|
| 255 |
+
"安全路径吃食物\n",
|
| 256 |
+
"安全路径吃食物\n",
|
| 257 |
+
"安全路径吃食物\n",
|
| 258 |
+
"安全路径吃食物\n",
|
| 259 |
+
"安全路径吃食物\n",
|
| 260 |
+
"安全路径吃食物\n",
|
| 261 |
+
"安全路径吃食物\n",
|
| 262 |
+
"安全路径吃食物\n",
|
| 263 |
+
"安全路径吃食物\n",
|
| 264 |
+
"安全路径吃食物\n",
|
| 265 |
+
"安全路径吃食物\n",
|
| 266 |
+
"安全路径吃食物\n",
|
| 267 |
+
"安全路径吃食物\n",
|
| 268 |
+
"安全路径吃食物\n",
|
| 269 |
+
"安全路径吃食物\n",
|
| 270 |
+
"安全路径吃食物\n",
|
| 271 |
+
"安全路径吃食物\n",
|
| 272 |
+
"安全路径吃食物\n",
|
| 273 |
+
"安全路径吃食物\n",
|
| 274 |
+
"安全路径吃食物\n",
|
| 275 |
+
"安全路径吃食物\n",
|
| 276 |
+
"安全路径吃食物\n",
|
| 277 |
+
"安全路径吃食物\n",
|
| 278 |
+
"安全路径吃食物\n",
|
| 279 |
+
"安全路径吃食物\n",
|
| 280 |
+
"安全路径吃食物\n",
|
| 281 |
+
"安全路径吃食物\n",
|
| 282 |
+
"安全路径吃食物\n",
|
| 283 |
+
"安全路径吃食物\n",
|
| 284 |
+
"安全路径吃食物\n",
|
| 285 |
+
"安全路径吃食物\n",
|
| 286 |
+
"安全路径吃食物\n",
|
| 287 |
+
"安全路径吃食物\n",
|
| 288 |
+
"安全路径吃食物\n",
|
| 289 |
+
"安全路径吃食物\n",
|
| 290 |
+
"安全路径吃食物\n",
|
| 291 |
+
"安全路径吃食物\n",
|
| 292 |
+
"安全路径吃食物\n",
|
| 293 |
+
"安全路径吃食物\n",
|
| 294 |
+
"安全路径吃食物\n",
|
| 295 |
+
"安全路径吃食物\n",
|
| 296 |
+
"安全路径吃食物\n",
|
| 297 |
+
"安全路径吃食物\n",
|
| 298 |
+
"安全路径吃食物\n",
|
| 299 |
+
"安全路径吃食物\n",
|
| 300 |
+
"安全路径吃食物\n",
|
| 301 |
+
"安全路径吃食物\n",
|
| 302 |
+
"安全路径吃食物\n",
|
| 303 |
+
"安全路径吃食物\n",
|
| 304 |
+
"安全路径吃食物\n",
|
| 305 |
+
"安全路径吃食物\n",
|
| 306 |
+
"安全路��吃食物\n",
|
| 307 |
+
"安全路径吃食物\n",
|
| 308 |
+
"安全路径吃食物\n",
|
| 309 |
+
"安全路径吃食物\n",
|
| 310 |
+
"安全路径吃食物\n",
|
| 311 |
+
"安全路径吃食物\n",
|
| 312 |
+
"安全路径吃食物\n",
|
| 313 |
+
"安全路径吃食物\n",
|
| 314 |
+
"安全路径吃食物\n",
|
| 315 |
+
"安全路径吃食物\n",
|
| 316 |
+
"安全路径吃食物\n",
|
| 317 |
+
"安全路径吃食物\n",
|
| 318 |
+
"安全路径吃食物\n",
|
| 319 |
+
"安全路径吃食物\n",
|
| 320 |
+
"安全路径吃食物\n",
|
| 321 |
+
"安全路径吃食物\n",
|
| 322 |
+
"安全路径吃食物\n",
|
| 323 |
+
"安全路径吃食物\n",
|
| 324 |
+
"安全路径吃食物\n",
|
| 325 |
+
"安全路径吃食物\n",
|
| 326 |
+
"安全路径吃食物\n",
|
| 327 |
+
"安全路径吃食物\n",
|
| 328 |
+
"安全路径吃食物\n",
|
| 329 |
+
"安全路径吃食物\n",
|
| 330 |
+
"安全路径吃食物\n",
|
| 331 |
+
"安全路径吃食物\n",
|
| 332 |
+
"安全路径吃食物\n",
|
| 333 |
+
"安全路径吃食物\n",
|
| 334 |
+
"安全路径吃食物\n",
|
| 335 |
+
"安全路径吃食物\n",
|
| 336 |
+
"安全路径吃食物\n",
|
| 337 |
+
"安全路径吃食物\n",
|
| 338 |
+
"安全路径吃食物\n",
|
| 339 |
+
"安全路径吃食物\n",
|
| 340 |
+
"安全路径吃食物\n",
|
| 341 |
+
"安全路径吃食物\n",
|
| 342 |
+
"安全路径吃食物\n",
|
| 343 |
+
"安全路径吃食物\n",
|
| 344 |
+
"安全路径吃食物\n",
|
| 345 |
+
"安全路径吃食物\n",
|
| 346 |
+
"安全路径吃食物\n",
|
| 347 |
+
"安全路径吃食物\n",
|
| 348 |
+
"安全路径吃食物\n",
|
| 349 |
+
"安全路径吃食物\n",
|
| 350 |
+
"安全路径吃食物\n",
|
| 351 |
+
"安全路径吃食物\n",
|
| 352 |
+
"安全路径吃食物\n",
|
| 353 |
+
"安全路径吃食物\n",
|
| 354 |
+
"安全路径吃食物\n",
|
| 355 |
+
"安全路径吃食物\n",
|
| 356 |
+
"安全路径吃食物\n",
|
| 357 |
+
"安全路径吃食物\n",
|
| 358 |
+
"安全路径吃食物\n",
|
| 359 |
+
"安全路径吃食物\n",
|
| 360 |
+
"安全路径吃食物\n",
|
| 361 |
+
"安全路径吃食物\n",
|
| 362 |
+
"安全路径吃食物\n",
|
| 363 |
+
"安全路径吃食物\n",
|
| 364 |
+
"安全路径吃食物\n",
|
| 365 |
+
"安全路径吃食物\n",
|
| 366 |
+
"安全路径吃食物\n",
|
| 367 |
+
"安全路径吃食物\n",
|
| 368 |
+
"安全路径吃食物\n",
|
| 369 |
+
"安全路径吃食物\n",
|
| 370 |
+
"安全路径吃食物\n",
|
| 371 |
+
"安全路径吃食物\n",
|
| 372 |
+
"安全路径吃食物\n",
|
| 373 |
+
"安全路径吃食物\n",
|
| 374 |
+
"安全路径吃食物\n",
|
| 375 |
+
"安全路径吃食物\n",
|
| 376 |
+
"安全路径吃食物\n",
|
| 377 |
+
"安全路径吃食物\n",
|
| 378 |
+
"安全路径吃食物\n",
|
| 379 |
+
"安全路径吃食物\n",
|
| 380 |
+
"安全路径吃食物\n",
|
| 381 |
+
"安全路径吃食物\n",
|
| 382 |
+
"安全路径吃食物\n",
|
| 383 |
+
"安全路径吃食物\n",
|
| 384 |
+
"安全路径吃食物\n",
|
| 385 |
+
"安全路径吃食物\n",
|
| 386 |
+
"安全路径吃食物\n",
|
| 387 |
+
"安全路径吃食物\n",
|
| 388 |
+
"安全路径吃食物\n",
|
| 389 |
+
"安全路径吃食物\n",
|
| 390 |
+
"安全路径吃食物\n",
|
| 391 |
+
"安全路径吃食物\n",
|
| 392 |
+
"安全路径吃食物\n",
|
| 393 |
+
"安全路径吃食物\n",
|
| 394 |
+
"安全路径吃食物\n",
|
| 395 |
+
"安全路径吃食物\n",
|
| 396 |
+
"安全路径吃食物\n",
|
| 397 |
+
"安全路径吃食物\n",
|
| 398 |
+
"安全路径吃食物\n",
|
| 399 |
+
"安全路径吃食物\n",
|
| 400 |
+
"安全路径吃食物\n",
|
| 401 |
+
"安全路径吃食物\n",
|
| 402 |
+
"安全路径吃食物\n",
|
| 403 |
+
"安全路径吃食物\n",
|
| 404 |
+
"安全路径吃食物\n",
|
| 405 |
+
"安全路径吃食物\n",
|
| 406 |
+
"安全路径吃食物\n",
|
| 407 |
+
"安全路径吃食物\n",
|
| 408 |
+
"安全路径吃食物\n",
|
| 409 |
+
"安全路径吃食物\n",
|
| 410 |
+
"安全路径吃食物\n",
|
| 411 |
+
"安全路径吃食物\n",
|
| 412 |
+
"安全路径吃食物\n",
|
| 413 |
+
"安全路径吃食物\n",
|
| 414 |
+
"安全路径吃食物\n",
|
| 415 |
+
"安全路径吃食物\n",
|
| 416 |
+
"安全路径吃食物\n",
|
| 417 |
+
"安全路径吃食物\n",
|
| 418 |
+
"安全路径吃食物\n",
|
| 419 |
+
"安全路径吃食物\n",
|
| 420 |
+
"安全路径吃食物\n",
|
| 421 |
+
"安全路径吃食物\n"
|
| 422 |
+
]
|
| 423 |
+
},
|
| 424 |
+
{
|
| 425 |
+
"ename": "KeyboardInterrupt",
|
| 426 |
+
"evalue": "",
|
| 427 |
+
"output_type": "error",
|
| 428 |
+
"traceback": [
|
| 429 |
+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
| 430 |
+
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
|
| 431 |
+
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 369>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 374\u001b[0m \u001b[38;5;66;03m# 当前布局能找到吃food_path\u001b[39;00m\n\u001b[1;32m 375\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m food_flag \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 376\u001b[0m \u001b[38;5;66;03m# 虚拟蛇探路,吃到食物后如果能找到tail_path则返回1\u001b[39;00m\n\u001b[0;32m--> 377\u001b[0m virtual_tail_flag \u001b[38;5;241m=\u001b[39m \u001b[43mexploretheway\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfood_Position\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msnake_Body\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 379\u001b[0m \u001b[38;5;66;03m# 虚拟蛇吃完食物后找得到tail_path\u001b[39;00m\n\u001b[1;32m 380\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m virtual_tail_flag \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m1\u001b[39m:\n",
|
| 432 |
+
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36mexploretheway\u001b[0;34m(food_position0, snake_body0)\u001b[0m\n\u001b[1;32m 229\u001b[0m food_position \u001b[38;5;241m=\u001b[39m food_position0\u001b[38;5;241m.\u001b[39mcopy()\n\u001b[1;32m 231\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 232\u001b[0m \u001b[38;5;66;03m# 获取觅食路径\u001b[39;00m\n\u001b[0;32m--> 233\u001b[0m path, flag1 \u001b[38;5;241m=\u001b[39m \u001b[43mBFS\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfood_position\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msnake_body\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 235\u001b[0m \u001b[38;5;66;03m# 更新蛇头\u001b[39;00m\n\u001b[1;32m 236\u001b[0m snake_body\u001b[38;5;241m.\u001b[39minsert(\u001b[38;5;241m0\u001b[39m, path[\u001b[38;5;241m1\u001b[39m])\n",
|
| 433 |
+
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36mBFS\u001b[0;34m(food_position0, snake_body0)\u001b[0m\n\u001b[1;32m 149\u001b[0m \u001b[38;5;66;03m# 如果当前没有吃到食物\u001b[39;00m\n\u001b[1;32m 150\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m currentlocation \u001b[38;5;241m!=\u001b[39m food_position:\n\u001b[1;32m 151\u001b[0m \n\u001b[1;32m 152\u001b[0m \u001b[38;5;66;03m# 记录下一步可以走到的位置,不考虑蛇身更新情况\u001b[39;00m\n\u001b[0;32m--> 153\u001b[0m l1 \u001b[38;5;241m=\u001b[39m \u001b[43mwalkable\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcurrentlocation\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msnake_body\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 155\u001b[0m \u001b[38;5;66;03m# 遍历下一步的所有可能\u001b[39;00m\n\u001b[1;32m 156\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m l1:\n",
|
| 434 |
+
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36mwalkable\u001b[0;34m(location0, snake_body0)\u001b[0m\n\u001b[1;32m 103\u001b[0m \u001b[38;5;66;03m# 向左\u001b[39;00m\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m location0[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m20\u001b[39m \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m [location0[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m20\u001b[39m, location0[\u001b[38;5;241m1\u001b[39m]] \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m snake_body0:\n\u001b[0;32m--> 105\u001b[0m \u001b[43ml\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mappend\u001b[49m([location0[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m20\u001b[39m, location0[\u001b[38;5;241m1\u001b[39m]])\n\u001b[1;32m 107\u001b[0m \u001b[38;5;66;03m# 向下\u001b[39;00m\n\u001b[1;32m 108\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m location0[\u001b[38;5;241m1\u001b[39m] \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m20\u001b[39m \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m300\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m [location0[\u001b[38;5;241m0\u001b[39m], location0[\u001b[38;5;241m1\u001b[39m] \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m20\u001b[39m] \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m snake_body0:\n",
|
| 435 |
+
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
|
| 436 |
+
]
|
| 437 |
+
}
|
| 438 |
+
],
|
| 439 |
+
"source": [
|
| 440 |
+
"import pygame\n",
|
| 441 |
+
"import sys\n",
|
| 442 |
+
"import random\n",
|
| 443 |
+
"import time\n",
|
| 444 |
+
"from pygame.locals import *\n",
|
| 445 |
+
"\n",
|
| 446 |
+
"# 初始化Pygame库\n",
|
| 447 |
+
"pygame.init()\n",
|
| 448 |
+
"\n",
|
| 449 |
+
"# 初始化一个游戏界面窗口\n",
|
| 450 |
+
"DISPLAY = pygame.display.set_mode((300, 300))\n",
|
| 451 |
+
"\n",
|
| 452 |
+
"# 设置游戏窗口的标题\n",
|
| 453 |
+
"pygame.display.set_caption('贪吃蛇')\n",
|
| 454 |
+
"\n",
|
| 455 |
+
"# 定义一个变量来控制游戏速度\n",
|
| 456 |
+
"FPSCLOCK = pygame.time.Clock()\n",
|
| 457 |
+
"\n",
|
| 458 |
+
"# 初始化游戏界面内使用的字体\n",
|
| 459 |
+
"BASICFONT = pygame.font.SysFont(\"SIMYOU.TTF\", 80)\n",
|
| 460 |
+
"font = pygame.font.SysFont('simsunnsimsun', 80)\n",
|
| 461 |
+
"\n",
|
| 462 |
+
"# 设置颜色\n",
|
| 463 |
+
"BLACK = pygame.Color(0, 0, 0)\n",
|
| 464 |
+
"WHITE = pygame.Color(255, 255, 255)\n",
|
| 465 |
+
"RED = pygame.Color(255, 0, 0)\n",
|
| 466 |
+
"GREY = pygame.Color(150, 150, 150)\n",
|
| 467 |
+
"GREEN = pygame.Color(0, 255, 255)\n",
|
| 468 |
+
"YELLOW = pygame.Color(255, 255, 0)\n",
|
| 469 |
+
"FORESTGREEN = pygame.Color(34, 139, 34)\n",
|
| 470 |
+
"Purple3 = pygame.Color(125, 38, 205)\n",
|
| 471 |
+
"\n",
|
| 472 |
+
"# 贪吃蛇头的初始位置\n",
|
| 473 |
+
"snake_Head = [100, 100]\n",
|
| 474 |
+
"\n",
|
| 475 |
+
"# 初始化贪吃蛇的身体 (注:这里以20*20为一个标准小格子)\n",
|
| 476 |
+
"snake_Body = [[80, 100], [60, 100], [40, 100]]\n",
|
| 477 |
+
"\n",
|
| 478 |
+
"# 指定蛇初始前进的方向 -- 向右\n",
|
| 479 |
+
"direction = \"RIGHT\"\n",
|
| 480 |
+
"\n",
|
| 481 |
+
"\n",
|
| 482 |
+
"def randomfood(snake_Body):\n",
|
| 483 |
+
" \"\"\"随机生成食物\"\"\"\n",
|
| 484 |
+
"\n",
|
| 485 |
+
" # 随机生���食物的位置\n",
|
| 486 |
+
" x = random.randrange(1, 15)\n",
|
| 487 |
+
" y = random.randrange(1, 15)\n",
|
| 488 |
+
" Position = [int(x * 20), int(y * 20)]\n",
|
| 489 |
+
"\n",
|
| 490 |
+
" # 如果食物在贪吃蛇的身体里,则重新随机\n",
|
| 491 |
+
" while Position in snake_Body:\n",
|
| 492 |
+
" x = random.randrange(1, 15)\n",
|
| 493 |
+
" y = random.randrange(1, 15)\n",
|
| 494 |
+
" Position = [int(x * 20), int(y * 20)]\n",
|
| 495 |
+
" return Position\n",
|
| 496 |
+
"\n",
|
| 497 |
+
"\n",
|
| 498 |
+
"# 随机出现第一个食物\n",
|
| 499 |
+
"food_Position = randomfood(snake_Body)\n",
|
| 500 |
+
"\n",
|
| 501 |
+
"# 标记食物\n",
|
| 502 |
+
"food_flag = 1\n",
|
| 503 |
+
"\n",
|
| 504 |
+
"\n",
|
| 505 |
+
"def GameOver():\n",
|
| 506 |
+
" \"\"\"游戏结束\"\"\"\n",
|
| 507 |
+
"\n",
|
| 508 |
+
" # 设置GameOver的显示颜色与文字\n",
|
| 509 |
+
" if (len(snake_Body) - 3) <= 10:\n",
|
| 510 |
+
" GameOver_Surf = font.render('太菜了', True, GREY)\n",
|
| 511 |
+
" elif 10 <= (len(snake_Body) - 3) <= 20:\n",
|
| 512 |
+
" GameOver_Surf = font.render('一般般', True, GREY)\n",
|
| 513 |
+
" else:\n",
|
| 514 |
+
" GameOver_Surf = font.render('很棒!', True, GREY)\n",
|
| 515 |
+
"\n",
|
| 516 |
+
" # 设置GameOver的位置\n",
|
| 517 |
+
" GameOver_Rect = GameOver_Surf.get_rect()\n",
|
| 518 |
+
" GameOver_Rect.midtop = (320, 200)\n",
|
| 519 |
+
"\n",
|
| 520 |
+
" # 绑定以上设置到句柄\n",
|
| 521 |
+
" DISPLAY.blit(GameOver_Surf, GameOver_Rect)\n",
|
| 522 |
+
"\n",
|
| 523 |
+
" # 刷新画面\n",
|
| 524 |
+
" pygame.display.flip()\n",
|
| 525 |
+
"\n",
|
| 526 |
+
" # 等待3秒\n",
|
| 527 |
+
" time.sleep(3)\n",
|
| 528 |
+
" # 退出游戏\n",
|
| 529 |
+
" pygame.quit()\n",
|
| 530 |
+
" # 退出程序\n",
|
| 531 |
+
" sys.exit()\n",
|
| 532 |
+
"\n",
|
| 533 |
+
"\n",
|
| 534 |
+
"def walkable(location0, snake_body0):\n",
|
| 535 |
+
" \"\"\"返回下一步可以到达的位置\"\"\"\n",
|
| 536 |
+
" l = []\n",
|
| 537 |
+
"\n",
|
| 538 |
+
" # 向右\n",
|
| 539 |
+
" if location0[0] + 20 < 300 and [location0[0] + 20, location0[1]] not in snake_body0:\n",
|
| 540 |
+
" l.append([location0[0] + 20, location0[1]])\n",
|
| 541 |
+
"\n",
|
| 542 |
+
" # 向左\n",
|
| 543 |
+
" if location0[0] - 20 >= 0 and [location0[0] - 20, location0[1]] not in snake_body0:\n",
|
| 544 |
+
" l.append([location0[0] - 20, location0[1]])\n",
|
| 545 |
+
"\n",
|
| 546 |
+
" # 向下\n",
|
| 547 |
+
" if location0[1] + 20 < 300 and [location0[0], location0[1] + 20] not in snake_body0:\n",
|
| 548 |
+
" l.append([location0[0], location0[1] + 20])\n",
|
| 549 |
+
"\n",
|
| 550 |
+
" # 向上\n",
|
| 551 |
+
" if location0[1] - 20 >= 0 and [location0[0], location0[1] - 20] not in snake_body0:\n",
|
| 552 |
+
" l.append([location0[0], location0[1] - 20])\n",
|
| 553 |
+
"\n",
|
| 554 |
+
" return l\n",
|
| 555 |
+
"\n",
|
| 556 |
+
"\n",
|
| 557 |
+
"def changexy(position0):\n",
|
| 558 |
+
" \"\"\"改变位置\"\"\"\n",
|
| 559 |
+
" position = position0.copy()\n",
|
| 560 |
+
" return position[1] * 15 + position[0]\n",
|
| 561 |
+
"\n",
|
| 562 |
+
"\n",
|
| 563 |
+
"def BFS(food_position0, snake_body0):\n",
|
| 564 |
+
" # 获取食物的位置\n",
|
| 565 |
+
" food_position = food_position0.copy()\n",
|
| 566 |
+
" # 获取贪吃蛇的身体信息\n",
|
| 567 |
+
" snake_body = snake_body0.copy()\n",
|
| 568 |
+
"\n",
|
| 569 |
+
" # 是否可以吃到食物\n",
|
| 570 |
+
" flag = 0\n",
|
| 571 |
+
"\n",
|
| 572 |
+
" # 存储路径\n",
|
| 573 |
+
" path = []\n",
|
| 574 |
+
"\n",
|
| 575 |
+
" # 搜索栈,广度优先搜索\n",
|
| 576 |
+
" search_stack = []\n",
|
| 577 |
+
"\n",
|
| 578 |
+
" # {下一个位置:当前位置}\n",
|
| 579 |
+
" visited_dict = {}\n",
|
| 580 |
+
" search_stack.append([snake_body[0][0], snake_body[0][1]])\n",
|
| 581 |
+
" visited_dict[changexy([snake_body[0][0], snake_body[0][1]])] = -1\n",
|
| 582 |
+
"\n",
|
| 583 |
+
" # 进行广度优先遍历\n",
|
| 584 |
+
" while len(search_stack) > 0:\n",
|
| 585 |
+
" # 获取贪吃蛇头当前位置\n",
|
| 586 |
+
" currentlocation = search_stack.pop(0)\n",
|
| 587 |
+
"\n",
|
| 588 |
+
" # 如果当前没有吃到食物\n",
|
| 589 |
+
" if currentlocation != food_position:\n",
|
| 590 |
+
"\n",
|
| 591 |
+
" # 记录下一步可以走到的位置,不考虑蛇身更新情况\n",
|
| 592 |
+
" l1 = walkable(currentlocation, snake_body)\n",
|
| 593 |
+
"\n",
|
| 594 |
+
" # 遍历下一步的所有可能\n",
|
| 595 |
+
" for i in l1:\n",
|
| 596 |
+
" if visited_dict.get(changexy(i)) == None:\n",
|
| 597 |
+
" search_stack.append(i)\n",
|
| 598 |
+
" visited_dict[changexy(i)] = currentlocation\n",
|
| 599 |
+
"\n",
|
| 600 |
+
" # 如果吃到该食物\n",
|
| 601 |
+
" else:\n",
|
| 602 |
+
" flag = 1\n",
|
| 603 |
+
" break\n",
|
| 604 |
+
"\n",
|
| 605 |
+
" # 添加食物位置进路径\n",
|
| 606 |
+
" path.append(currentlocation)\n",
|
| 607 |
+
"\n",
|
| 608 |
+
" # 不断将前一个位置添加进路径\n",
|
| 609 |
+
" while visited_dict[changexy(currentlocation)] != -1:\n",
|
| 610 |
+
" currentlocation = visited_dict[changexy(currentlocation)]\n",
|
| 611 |
+
" path.append(currentlocation)\n",
|
| 612 |
+
"\n",
|
| 613 |
+
" # 反转 --> 贪吃蛇的头到食物的路径\n",
|
| 614 |
+
" path.reverse()\n",
|
| 615 |
+
"\n",
|
| 616 |
+
" return path, flag\n",
|
| 617 |
+
"\n",
|
| 618 |
+
"\n",
|
| 619 |
+
"def tailBFS(tail_position0, snake_body0):\n",
|
| 620 |
+
" # 蛇尾、蛇身\n",
|
| 621 |
+
" tail_position = tail_position0.copy()\n",
|
| 622 |
+
" snake_body = snake_body0.copy()\n",
|
| 623 |
+
"\n",
|
| 624 |
+
" # 记录是否能到蛇尾\n",
|
| 625 |
+
" flag = 0\n",
|
| 626 |
+
"\n",
|
| 627 |
+
" # 记录到蛇尾的路径\n",
|
| 628 |
+
" path = []\n",
|
| 629 |
+
"\n",
|
| 630 |
+
" # 搜索栈\n",
|
| 631 |
+
" search_stack = []\n",
|
| 632 |
+
"\n",
|
| 633 |
+
" # {下一个位置:当前位置}\n",
|
| 634 |
+
" visited_dict = {}\n",
|
| 635 |
+
"\n",
|
| 636 |
+
" # 初始化\n",
|
| 637 |
+
" search_stack.append([snake_body[0][0], snake_body[0][1]])\n",
|
| 638 |
+
" visited_dict[changexy([snake_body[0][0], snake_body[0][1]])] = -1\n",
|
| 639 |
+
"\n",
|
| 640 |
+
" # 开始广度优先遍历\n",
|
| 641 |
+
" while len(search_stack) > 0:\n",
|
| 642 |
+
" # 获取当前位置\n",
|
| 643 |
+
" currentlocation = search_stack.pop(0)\n",
|
| 644 |
+
"\n",
|
| 645 |
+
" if currentlocation != tail_position:\n",
|
| 646 |
+
" # l1存储下一步可走的位置,蛇尾是可到达的\n",
|
| 647 |
+
" tail = snake_body.pop()\n",
|
| 648 |
+
" l1 = walkable(currentlocation, snake_body)\n",
|
| 649 |
+
" snake_body.append(tail)\n",
|
| 650 |
+
"\n",
|
| 651 |
+
" # 遍历各个可走位置\n",
|
| 652 |
+
" for i1 in l1:\n",
|
| 653 |
+
" if visited_dict.get(changexy(i1)) == None:\n",
|
| 654 |
+
" # 更新搜索栈\n",
|
| 655 |
+
" search_stack.append(i1)\n",
|
| 656 |
+
" # 记录位置点间的关系\n",
|
| 657 |
+
" visited_dict[changexy(i1)] = currentlocation\n",
|
| 658 |
+
" else:\n",
|
| 659 |
+
" flag = 1\n",
|
| 660 |
+
" break\n",
|
| 661 |
+
"\n",
|
| 662 |
+
" return flag\n",
|
| 663 |
+
"\n",
|
| 664 |
+
"\n",
|
| 665 |
+
"def exploretheway(food_position0, snake_body0):\n",
|
| 666 |
+
" # 获取蛇身与食物位置\n",
|
| 667 |
+
" snake_body = snake_body0.copy()\n",
|
| 668 |
+
" food_position = food_position0.copy()\n",
|
| 669 |
+
"\n",
|
| 670 |
+
" while True:\n",
|
| 671 |
+
" # 获取觅食路径\n",
|
| 672 |
+
" path, flag1 = BFS(food_position, snake_body)\n",
|
| 673 |
+
"\n",
|
| 674 |
+
" # 更新蛇头\n",
|
| 675 |
+
" snake_body.insert(0, path[1])\n",
|
| 676 |
+
"\n",
|
| 677 |
+
" # 如果吃到食物\n",
|
| 678 |
+
" if snake_body[0][0] == food_position[0] and snake_body[0][1] == food_position[1]:\n",
|
| 679 |
+
"\n",
|
| 680 |
+
" # 当前位置是否能找到尾巴\n",
|
| 681 |
+
" flag2 = tailBFS(snake_body[-1], snake_body)\n",
|
| 682 |
+
"\n",
|
| 683 |
+
" break\n",
|
| 684 |
+
" # 未吃到食物,则更新蛇尾\n",
|
| 685 |
+
" else:\n",
|
| 686 |
+
" snake_body.pop()\n",
|
| 687 |
+
" return flag2\n",
|
| 688 |
+
"\n",
|
| 689 |
+
"\n",
|
| 690 |
+
"def longest_tail_path(snake_body0):\n",
|
| 691 |
+
" \"\"\"返回最长的蛇尾路径\"\"\"\n",
|
| 692 |
+
"\n",
|
| 693 |
+
" # 获取蛇身\n",
|
| 694 |
+
" snake_body = snake_body0.copy()\n",
|
| 695 |
+
"\n",
|
| 696 |
+
" # 获取下一步可以走的路,蛇尾是可以走的\n",
|
| 697 |
+
" tail = snake_body.pop()\n",
|
| 698 |
+
" l0 = walkable(snake_body[0], snake_body)\n",
|
| 699 |
+
" snake_body.append(tail)\n",
|
| 700 |
+
"\n",
|
| 701 |
+
" longest = -1\n",
|
| 702 |
+
"\n",
|
| 703 |
+
" # 遍历下一步可能的情况,如A\\B\\C\n",
|
| 704 |
+
" # 再分别利用广度优先搜索,在A\\B\\C的情况下,找出到蛇尾的最短路径\n",
|
| 705 |
+
" # 如果A情况下最短路径是最长的,则下一步往A处走\n",
|
| 706 |
+
" for i0 in l0:\n",
|
| 707 |
+
" flag = 0\n",
|
| 708 |
+
" path = []\n",
|
| 709 |
+
" search_stack = []\n",
|
| 710 |
+
" visited_dict = {}\n",
|
| 711 |
+
"\n",
|
| 712 |
+
" # 搜索栈 -- 广度优先遍历\n",
|
| 713 |
+
" search_stack.append(i0)\n",
|
| 714 |
+
"\n",
|
| 715 |
+
" # {下一个位置:当前位置}\n",
|
| 716 |
+
" visited_dict[changexy(i0)] = -1\n",
|
| 717 |
+
"\n",
|
| 718 |
+
" # 广度搜索\n",
|
| 719 |
+
" while len(search_stack) > 0:\n",
|
| 720 |
+
"\n",
|
| 721 |
+
" # 更新当前位置\n",
|
| 722 |
+
" currentlocation = search_stack.pop(0)\n",
|
| 723 |
+
"\n",
|
| 724 |
+
" # 如果不在蛇尾\n",
|
| 725 |
+
" if currentlocation != snake_body[-1]:\n",
|
| 726 |
+
"\n",
|
| 727 |
+
" # l1记录所有下一位置的可能\n",
|
| 728 |
+
" tail = snake_body.pop()\n",
|
| 729 |
+
" l1 = walkable(currentlocation, snake_body)\n",
|
| 730 |
+
" snake_body.append(tail)\n",
|
| 731 |
+
"\n",
|
| 732 |
+
" # 遍历下一位置的可能\n",
|
| 733 |
+
" for j in l1:\n",
|
| 734 |
+
" if visited_dict.get(changexy(j)) == None:\n",
|
| 735 |
+
"\n",
|
| 736 |
+
" # 更新搜索栈\n",
|
| 737 |
+
" search_stack.append(j)\n",
|
| 738 |
+
"\n",
|
| 739 |
+
" # 更新各位置的先后关系\n",
|
| 740 |
+
" visited_dict[changexy(j)] = currentlocation\n",
|
| 741 |
+
"\n",
|
| 742 |
+
" else:\n",
|
| 743 |
+
" # 找到了一条到达蛇尾的路径\n",
|
| 744 |
+
" flag = 1\n",
|
| 745 |
+
" break\n",
|
| 746 |
+
"\n",
|
| 747 |
+
" # 记录路径信息\n",
|
| 748 |
+
" path.append(currentlocation)\n",
|
| 749 |
+
" while visited_dict[changexy(currentlocation)] != -1:\n",
|
| 750 |
+
" currentlocation = visited_dict[changexy(currentlocation)]\n",
|
| 751 |
+
" path.append(currentlocation)\n",
|
| 752 |
+
" path.reverse()\n",
|
| 753 |
+
"\n",
|
| 754 |
+
" # 如果有更长的��径,则更新最长路径\n",
|
| 755 |
+
" if flag == 1:\n",
|
| 756 |
+
" if len(path) > longest:\n",
|
| 757 |
+
" longest = len(path)\n",
|
| 758 |
+
" longest_path = path\n",
|
| 759 |
+
"\n",
|
| 760 |
+
" return longest_path\n",
|
| 761 |
+
"\n",
|
| 762 |
+
"\n",
|
| 763 |
+
"# 漫步函数,随机选择蛇头周围四个方向中可走的方向走一步\n",
|
| 764 |
+
"def wander(snake_body0):\n",
|
| 765 |
+
" # 获取下一步可以走的路径\n",
|
| 766 |
+
" l = walkable(snake_body0[0], snake_body0)\n",
|
| 767 |
+
"\n",
|
| 768 |
+
" # 随机走一步\n",
|
| 769 |
+
" if len(l) > 1:\n",
|
| 770 |
+
" x = random.randrange(0, len(l))\n",
|
| 771 |
+
" elif len(l) == 1:\n",
|
| 772 |
+
" x = 0\n",
|
| 773 |
+
" else:\n",
|
| 774 |
+
" return l\n",
|
| 775 |
+
" return l[x]\n",
|
| 776 |
+
"\n",
|
| 777 |
+
"def drawSnake(snake_body0):\n",
|
| 778 |
+
"\n",
|
| 779 |
+
" # 画蛇头(x, y, width, length)\n",
|
| 780 |
+
" pygame.draw.rect(DISPLAY, Purple3, Rect(\n",
|
| 781 |
+
" snake_body0[0][0], snake_body0[0][1], 20, 20))\n",
|
| 782 |
+
"\n",
|
| 783 |
+
" # 画蛇身\n",
|
| 784 |
+
" for j in range(1, len(snake_body0)-1):\n",
|
| 785 |
+
" pygame.draw.rect(DISPLAY, FORESTGREEN, Rect(\n",
|
| 786 |
+
" snake_body0[j][0], snake_body0[j][1], 20, 20))\n",
|
| 787 |
+
"\n",
|
| 788 |
+
" # 画蛇尾\n",
|
| 789 |
+
" pygame.draw.rect(DISPLAY, GREEN, Rect(\n",
|
| 790 |
+
" snake_body0[-1][0], snake_body0[-1][1], 20, 20))\n",
|
| 791 |
+
"\n",
|
| 792 |
+
"def drawFood(food_position0):\n",
|
| 793 |
+
" # 画食物\n",
|
| 794 |
+
" pygame.draw.rect(DISPLAY, RED, Rect(\n",
|
| 795 |
+
" food_position0[0], food_position0[1], 20, 20))\n",
|
| 796 |
+
"\n",
|
| 797 |
+
"def drawScore(score):\n",
|
| 798 |
+
" # 设置分数的显示颜色\n",
|
| 799 |
+
" score_Surf = BASICFONT.render('%s' % (score), True, GREY)\n",
|
| 800 |
+
" # 设置分数的位置\n",
|
| 801 |
+
" score_Rect = score_Surf.get_rect()\n",
|
| 802 |
+
" score_Rect.midtop = (50, 20)\n",
|
| 803 |
+
" # 绑定以上设置到句柄\n",
|
| 804 |
+
" DISPLAY.blit(score_Surf, score_Rect)\n",
|
| 805 |
+
"\n",
|
| 806 |
+
"while True:\n",
|
| 807 |
+
" # 蛇身不动,蛇头动,是否可以吃到食物,返回最短路径\n",
|
| 808 |
+
" food_path, food_flag = BFS(food_Position, snake_Body)\n",
|
| 809 |
+
"\n",
|
| 810 |
+
" # 蛇身不动,蛇头动,尾巴是否可到达\n",
|
| 811 |
+
" tail_flag = tailBFS(snake_Body[-1], snake_Body)\n",
|
| 812 |
+
"\n",
|
| 813 |
+
" # 当前布局能找到吃food_path\n",
|
| 814 |
+
" if food_flag == 1:\n",
|
| 815 |
+
" # 虚拟蛇探路,吃到食物后如果能找到tail_path则返回1\n",
|
| 816 |
+
" virtual_tail_flag = exploretheway(food_Position, snake_Body)\n",
|
| 817 |
+
"\n",
|
| 818 |
+
" # 虚拟蛇吃完食物后找得到tail_path\n",
|
| 819 |
+
" if virtual_tail_flag == 1:\n",
|
| 820 |
+
" print(\"安全路径吃食物\")\n",
|
| 821 |
+
"\n",
|
| 822 |
+
" # 真实的蛇沿最短路径向食物走一步\n",
|
| 823 |
+
" snake_Body.insert(0, food_path[1])\n",
|
| 824 |
+
"\n",
|
| 825 |
+
" # 吃到食物,则重新随机食物位置\n",
|
| 826 |
+
" if snake_Body[0][0] == food_Position[0] and snake_Body[0][1] == food_Position[1]:\n",
|
| 827 |
+
" food_Position = randomfood(snake_Body)\n",
|
| 828 |
+
"\n",
|
| 829 |
+
" # 未吃到食物,则更新蛇尾\n",
|
| 830 |
+
" else:\n",
|
| 831 |
+
" snake_Body.pop()\n",
|
| 832 |
+
"\n",
|
| 833 |
+
" # 虚拟蛇吃完食物后找不到tail_path\n",
|
| 834 |
+
" else:\n",
|
| 835 |
+
" print(\"直接吃不安全,找蛇尾\")\n",
|
| 836 |
+
"\n",
|
| 837 |
+
" # 真实的蛇沿最长路径向蛇尾走一步\n",
|
| 838 |
+
" longest_path = longest_tail_path(snake_Body)\n",
|
| 839 |
+
"\n",
|
| 840 |
+
" # 更新蛇身\n",
|
| 841 |
+
" snake_Body.insert(0, longest_path[0])\n",
|
| 842 |
+
" if snake_Body[0][0] == food_Position[0] and snake_Body[0][1] == food_Position[1]:\n",
|
| 843 |
+
" food_Position = randomfood(snake_Body)\n",
|
| 844 |
+
" else:\n",
|
| 845 |
+
" snake_Body.pop()\n",
|
| 846 |
+
"\n",
|
| 847 |
+
" # 当前布局能找到tail_path(找不到food_path)\n",
|
| 848 |
+
" elif tail_flag == 1:\n",
|
| 849 |
+
" print(\"找到蛇尾\")\n",
|
| 850 |
+
" # 真实的蛇沿最长路径向蛇尾走一步\n",
|
| 851 |
+
" longest_path = longest_tail_path(snake_Body)\n",
|
| 852 |
+
"\n",
|
| 853 |
+
" # 更新蛇身\n",
|
| 854 |
+
" snake_Body.insert(0, longest_path[0])\n",
|
| 855 |
+
" snake_Body.pop()\n",
|
| 856 |
+
"\n",
|
| 857 |
+
" # 找不到food_path也找不到tail_path时。随机走一步\n",
|
| 858 |
+
" elif food_flag != 1 and tail_flag != 1:\n",
|
| 859 |
+
" print(\"找不到食物也找不到蛇尾\")\n",
|
| 860 |
+
"\n",
|
| 861 |
+
" # 无路可走\n",
|
| 862 |
+
" if len(wander(snake_Body)) == 0:\n",
|
| 863 |
+
" print(\"走投无路\")\n",
|
| 864 |
+
" GameOver()\n",
|
| 865 |
+
" break\n",
|
| 866 |
+
"\n",
|
| 867 |
+
" # 有路可走\n",
|
| 868 |
+
" else:\n",
|
| 869 |
+
" snake_Body.insert(0, wander(snake_Body))\n",
|
| 870 |
+
" snake_Body.pop()\n",
|
| 871 |
+
"\n",
|
| 872 |
+
" # 画布为黑色\n",
|
| 873 |
+
" DISPLAY.fill(BLACK)\n",
|
| 874 |
+
"\n",
|
| 875 |
+
" # 画出贪吃蛇\n",
|
| 876 |
+
" drawSnake(snake_Body)\n",
|
| 877 |
+
"\n",
|
| 878 |
+
" # 画出食物的位置\n",
|
| 879 |
+
" drawFood(food_Position)\n",
|
| 880 |
+
"\n",
|
| 881 |
+
" # 打印出玩家的分数\n",
|
| 882 |
+
" drawScore(len(snake_Body) - 3)\n",
|
| 883 |
+
"\n",
|
| 884 |
+
" # 刷新Pygame的显示层,贪吃蛇与食物的每一次移动,都会进行刷新显示层的操作来显示。\n",
|
| 885 |
+
" pygame.display.flip()\n",
|
| 886 |
+
"\n",
|
| 887 |
+
" # 控制游戏速度\n",
|
| 888 |
+
" FPSCLOCK.tick(20)\n",
|
| 889 |
+
"\n",
|
| 890 |
+
" # 蛇碰到边缘,游戏结束\n",
|
| 891 |
+
" if snake_Body[0][0] < 0 or snake_Body[0][0] > 300:\n",
|
| 892 |
+
" GameOver()\n",
|
| 893 |
+
" if snake_Body[0][1] < 0 or snake_Body[0][1] > 300:\n",
|
| 894 |
+
" GameOver()\n",
|
| 895 |
+
"\n",
|
| 896 |
+
" # 贪吃蛇头触碰到自己,游戏结束\n",
|
| 897 |
+
" for i in snake_Body[1:]:\n",
|
| 898 |
+
" if snake_Body[0][0] == i[0] and snake_Body[0][1] == i[1]:\n",
|
| 899 |
+
" GameOver()"
|
| 900 |
+
]
|
| 901 |
+
}
|
| 902 |
+
],
|
| 903 |
+
"metadata": {
|
| 904 |
+
"kernelspec": {
|
| 905 |
+
"display_name": "Python 3 (ipykernel)",
|
| 906 |
+
"language": "python",
|
| 907 |
+
"name": "python3"
|
| 908 |
+
},
|
| 909 |
+
"language_info": {
|
| 910 |
+
"codemirror_mode": {
|
| 911 |
+
"name": "ipython",
|
| 912 |
+
"version": 3
|
| 913 |
+
},
|
| 914 |
+
"file_extension": ".py",
|
| 915 |
+
"mimetype": "text/x-python",
|
| 916 |
+
"name": "python",
|
| 917 |
+
"nbconvert_exporter": "python",
|
| 918 |
+
"pygments_lexer": "ipython3",
|
| 919 |
+
"version": "3.9.12"
|
| 920 |
+
},
|
| 921 |
+
"toc": {
|
| 922 |
+
"base_numbering": 1,
|
| 923 |
+
"nav_menu": {},
|
| 924 |
+
"number_sections": true,
|
| 925 |
+
"sideBar": true,
|
| 926 |
+
"skip_h1_title": false,
|
| 927 |
+
"title_cell": "Table of Contents",
|
| 928 |
+
"title_sidebar": "Contents",
|
| 929 |
+
"toc_cell": false,
|
| 930 |
+
"toc_position": {
|
| 931 |
+
"height": "calc(100% - 180px)",
|
| 932 |
+
"left": "10px",
|
| 933 |
+
"top": "150px",
|
| 934 |
+
"width": "248.1875px"
|
| 935 |
+
},
|
| 936 |
+
"toc_section_display": true,
|
| 937 |
+
"toc_window_display": true
|
| 938 |
+
}
|
| 939 |
+
},
|
| 940 |
+
"nbformat": 4,
|
| 941 |
+
"nbformat_minor": 5
|
| 942 |
+
}
|
data/QObject.qss
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
QLabel#notice {
|
| 2 |
+
font-size: 20px;
|
| 3 |
+
color: gray;
|
| 4 |
+
border: 1px solid gray;
|
| 5 |
+
border-radius: 8px;
|
| 6 |
+
}
|
| 7 |
+
QLabel#notice[notice_level="normal"] {
|
| 8 |
+
color: green;
|
| 9 |
+
border-color: green;
|
| 10 |
+
}
|
| 11 |
+
QLabel#notice[notice_level="warning"] {
|
| 12 |
+
color: yellow;
|
| 13 |
+
border-color: yellow;
|
| 14 |
+
}
|
| 15 |
+
QLabel#notice[notice_level="error"] {
|
| 16 |
+
color: red;
|
| 17 |
+
border-color: red;
|
| 18 |
+
}
|
data/style.qss
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
QMainWindow{
|
| 2 |
+
background-color: yellow
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
QToolTip{
|
| 6 |
+
border: 1px solid rgb(45, 45, 45);
|
| 7 |
+
background: white;
|
| 8 |
+
color: red;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
QPushButton#btnID{
|
| 14 |
+
border-radius: 30px;
|
| 15 |
+
background-image: url('./images/left.png');
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
#btnID:hover{
|
| 19 |
+
border-radius: 30px;
|
| 20 |
+
background-image: url('./images/leftHover.png');
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
QPushButton#btnID:Pressed{
|
| 24 |
+
border-radius: 30px;
|
| 25 |
+
background-image: url('./images/leftPressed.png');
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
QPushButton {
|
| 29 |
+
background-color: red
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
QPushButton[name="btnProperty"] {
|
| 33 |
+
background-color: blue
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
QGroupBox {
|
| 37 |
+
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #E0E0E0, stop: 1 #FFFFFF);
|
| 38 |
+
border: 2px solid gray;
|
| 39 |
+
border-radius: 5px;
|
| 40 |
+
margin-top: 1ex; /* leave space at the top for the title */
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
QGroupBox::title {
|
| 44 |
+
subcontrol-origin: margin;
|
| 45 |
+
subcontrol-position: top center; /* position at the top center */
|
| 46 |
+
padding: 0 3px;
|
| 47 |
+
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #FF0ECE, stop: 1 #FFFFFF);
|
| 48 |
+
}
|
| 49 |
+
QGroupBox>QCheckBox{
|
| 50 |
+
background-color: yellow
|
| 51 |
+
}
|
| 52 |
+
QGroupBox>QPushButton{
|
| 53 |
+
border: 2px solid #8f8f91;
|
| 54 |
+
border-radius: 6px;
|
| 55 |
+
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
| 56 |
+
stop: 0 #f6f7fa, stop: 1 #dadbde);
|
| 57 |
+
min-width: 80px;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
QGroupBox>QPushButton:pressed {
|
| 61 |
+
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
| 62 |
+
stop: 0 #dadbde, stop: 1 #f6f7fa);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
QGroupBox>QPushButton:flat {
|
| 66 |
+
border: none; /* no border for a flat push button */
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
QGroupBox>QPushButton:default {
|
| 70 |
+
border-color: navy; /* make the default button prominent */
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
QComboBox {
|
| 75 |
+
border: 1px solid gray;
|
| 76 |
+
border-radius: 3px;
|
| 77 |
+
padding: 1px 18px 1px 3px;
|
| 78 |
+
min-width: 6em;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
QComboBox::drop-down {
|
| 82 |
+
subcontrol-origin: padding;
|
| 83 |
+
subcontrol-position: top right;
|
| 84 |
+
width: 25px;
|
| 85 |
+
background: red;
|
| 86 |
+
border-left-width: 1px;
|
| 87 |
+
border-left-color: darkgray;
|
| 88 |
+
border-left-style: solid; /* just a single line */
|
| 89 |
+
border-top-right-radius: 3px; /* same radius as the QComboBox */
|
| 90 |
+
border-bottom-right-radius: 3px;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
QComboBox::down-arrow {
|
| 94 |
+
image: url(./images/dropdown.png);
|
| 95 |
+
}
|
| 96 |
+
|
data/xxx.png
ADDED
|
data//344/272/213/344/273/266/346/234/272/345/210/266/345/233/276/350/247/243.png
ADDED
|
images/.DS_Store
ADDED
|
Binary file (10.2 kB). View file
|
|
|
images/Bold.png
ADDED
|
images/IOS.png
ADDED
|
images/Italic.png
ADDED
|
images/android.png
ADDED
|
images/bao0.png
ADDED
|
images/bao1.png
ADDED
|
images/bao10.png
ADDED
|
images/bao11.png
ADDED
|
images/bao12.png
ADDED
|
images/bao13.png
ADDED
|
images/bao14.png
ADDED
|
images/bao2.png
ADDED
|
images/bao3.png
ADDED
|
images/bao4.png
ADDED
|
images/bao5.png
ADDED
|
images/bao6.png
ADDED
|
images/bao7.png
ADDED
|
images/bao8.png
ADDED
|
images/bao9.png
ADDED
|
images/boy.png
ADDED
|
images/cartoon1.ico
ADDED
|
|
images/cartoon2.ico
ADDED
|
|
images/cartoon3.ico
ADDED
|
|
images/cartoon4.ico
ADDED
|
|
images/cartoon5.ico
ADDED
|
|
images/cartoon6.ico
ADDED
|
|
images/cartoon7.ico
ADDED
|
|
images/cartoon8.ico
ADDED
|
|
images/close.ico
ADDED
|
|
images/close.png
ADDED
|
images/copy.png
ADDED
|
images/cut.png
ADDED
|
images/doc.ico
ADDED
|
|
images/down3.png
ADDED
|
images/dropdown.png
ADDED
|