在迷宫算法总结篇中我总结了生成迷宫的四种算法,在这一篇文章里面我侧重迷宫游戏的实现以及可视化。

使用python3中的GUI绘图库tkinter实现了一个简陋版的迷宫游戏,地图截图如下图所示。

为了降低游戏的难度,在寻找路径的过程中你可以通过点击图中的空白点,生成从起点到你点击位置的路径。迷宫的难度主要由以下几个参数决定:

  • 迷宫的长和宽:尺寸越大,生成的地图越难
  • 迷宫生成算法:地图难度:kruskal算法 > 随机深度优先算法 > prim算法 > 递归分割算法。

目前已经开发到版本1.0.7,已经实现的功能有:

当前版本代码在Maze-game-v1.0.7.

  • 游戏背景音乐
  • 游戏难度递增
  • 增加状态栏显示状态信息
  • 作弊(查看提示)增加惩罚分数(当前作弊一次惩罚20分)
  • 保存读取地图
  • 菜单栏,可用于设置地图生成算法,地图尺寸等
  • 增加迷雾模式
  • 增加生存模式,参考Roguelike Vision Algorithms丰富可玩性
  • 显示等级以及当前移动步数
  • 随机生成游戏地图
  • 按方向键后自动前进倒退(到分岔路停止)
  • 起点到任意位置辅助路径显示(鼠标左键单击空白地方显示路线) 移动次数计数
  • 到达终点后通关,按任意键进入下一关(目前没有难度设置,难度相同)

出现过的bug列表:

  • 到达终点后上下左右键仍然可用且不会进入到下一关
    已解决:修改进入下一关的逻辑
  • 画图很慢,不知道是我代码写的垃圾还是这个python的tkinter库本身的问题[狗头]
    已解决:刷新也面前调用Canvas.delete(“all”)清除之前绘制的所有内容再画新的页面即可。
  • 通关后生成的地图绘制的就更慢了,按一次方向键后要等一年[狗头]
    已解决:同上

最新版本截图

1 简单模式

2 迷雾模式

详细的介绍以及说明后续补充。现在提供1.0.3版本源码清单如下,为了方便代码管理,后续版本代码将会直接上传到Github,目前已经更新到v1.0.7,最新版本代码Maze-game-v1.0.7.

  • 迷宫类 Maze:
    ├ print_matrix
    ├ generate_matrix_dfs
    ├ generate_matrix_prim
    ├ generate_matrix_kruskal
    ├ generate_matrix_split
    ├ find_path_dfs
    └ find_path_bfs (TODO)
  • 并查集类 UnionSet:
    ├ find
    └ union
  • 可视化:
    ├ draw_cell
    ├ draw_path
    ├ draw_maze
    ├ check_reach
    ├ _eventHandler
    ├ _paint
    ├ _reset
    └ update_maze

迷宫算法源码 mazeGenerator.py

import numpy as np
import time
import random
import copyclass UnionSet(object):"""并查集实现,构造函数中的matrix是一个numpy类型"""def __init__(self, arr):self.parent = {pos: pos for pos in arr}self.count = len(arr)def find(self, root):if root == self.parent[root]:return rootreturn self.find(self.parent[root])def union(self, root1, root2):self.parent[self.find(root1)] = self.find(root2)class Maze(object):"""迷宫生成类"""def __init__(self, width = 11, height = 11):assert width >= 5 and height >= 5, "Length of width or height must be larger than 5."self.width = (width // 2) * 2 + 1self.height = (height // 2) * 2 + 1self.start = [1, 0]self.destination = [self.height - 2, self.width - 1]self.matrix = Noneself.path = []def print_matrix(self):matrix = copy.deepcopy(self.matrix)for p in self.path:matrix[p[0]][p[1]] = 1for i in range(self.height):for j in range(self.width):if matrix[i][j] == -1:print('□', end = '')elif matrix[i][j] == 0:print('  ', end = '')elif matrix[i][j] == 1:print('■', end = '')print('')def generate_matrix_dfs(self):# 地图初始化,并将出口和入口处的值设置为0self.matrix = -np.ones((self.height, self.width))self.matrix[self.start[0], self.start[1]] = 0self.matrix[self.destination[0], self.destination[1]] = 0visit_flag = [[0 for i in range(self.width)] for j in range(self.height)]def check(row, col, row_, col_):temp_sum = 0for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]:temp_sum += self.matrix[row_ + d[0]][col_ + d[1]]return temp_sum <= -3def dfs(row, col):visit_flag[row][col] = 1self.matrix[row][col] = 0if row == self.start[0] and col == self.start[1] + 1:returndirections = [[0, 2], [0, -2], [2, 0], [-2, 0]]random.shuffle(directions)for d in directions:row_, col_ = row + d[0], col + d[1]if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width - 1 and visit_flag[row_][col_] == 0 and check(row, col, row_, col_):if row == row_:visit_flag[row][min(col, col_) + 1] = 1self.matrix[row][min(col, col_) + 1] = 0else:visit_flag[min(row, row_) + 1][col] = 1self.matrix[min(row, row_) + 1][col] = 0dfs(row_, col_)dfs(self.destination[0], self.destination[1] - 1)self.matrix[self.start[0], self.start[1] + 1] = 0# 虽然说是prim算法,但是我感觉更像随机广度优先算法def generate_matrix_prim(self):# 地图初始化,并将出口和入口处的值设置为0self.matrix = -np.ones((self.height, self.width))def check(row, col):temp_sum = 0for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]:temp_sum += self.matrix[row + d[0]][col + d[1]]return temp_sum < -3queue = []row, col = (np.random.randint(1, self.height - 1) // 2) * 2 + 1, (np.random.randint(1, self.width - 1) // 2) * 2 + 1queue.append((row, col, -1, -1))while len(queue) != 0:row, col, r_, c_ = queue.pop(np.random.randint(0, len(queue)))if check(row, col):self.matrix[row, col] = 0if r_ != -1 and row == r_:self.matrix[row][min(col, c_) + 1] = 0elif r_ != -1 and col == c_:self.matrix[min(row, r_) + 1][col] = 0for d in [[0, 2], [0, -2], [2, 0], [-2, 0]]:row_, col_ = row + d[0], col + d[1]if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width - 1 and self.matrix[row_][col_] == -1:queue.append((row_, col_, row, col))self.matrix[self.start[0], self.start[1]] = 0self.matrix[self.destination[0], self.destination[1]] = 0# 递归切分算法,还有问题,现在不可用def generate_matrix_split(self):# 地图初始化,并将出口和入口处的值设置为0self.matrix = -np.zeros((self.height, self.width))self.matrix[0, :] = -1self.matrix[self.height - 1, :] = -1self.matrix[:, 0] = -1self.matrix[:, self.width - 1] = -1# 随机生成位于(start, end)之间的偶数def get_random(start, end):rand = np.random.randint(start, end)if rand & 0x1 ==  0:return randreturn get_random(start, end)# split函数的四个参数分别是左上角的行数、列数,右下角的行数、列数,墙壁只能在偶数行,偶数列def split(lr, lc, rr, rc):if rr - lr < 2 or rc - lc < 2:return# 生成墙壁,墙壁只能是偶数点cur_row, cur_col = get_random(lr, rr), get_random(lc, rc)for i in range(lc, rc + 1):self.matrix[cur_row][i] = -1for i in range(lr, rr + 1):self.matrix[i][cur_col] = -1# 挖穿三面墙得到连通图,挖孔的点只能是偶数点wall_list = [("left", cur_row, [lc + 1, cur_col - 1]),("right", cur_row, [cur_col + 1, rc - 1]), ("top", cur_col, [lr + 1, cur_row - 1]),("down", cur_col, [cur_row +  1, rr - 1])]random.shuffle(wall_list)for wall in wall_list[:-1]:if wall[2][1] - wall[2][0] < 1:continueif wall[0] in ["left", "right"]:self.matrix[wall[1], get_random(wall[2][0], wall[2][1] + 1) + 1] = 0else:self.matrix[get_random(wall[2][0], wall[2][1] + 1), wall[1] + 1] = 0# self.print_matrix()# time.sleep(1)# 递归split(lr + 2, lc + 2, cur_row - 2, cur_col - 2)split(lr + 2, cur_col + 2, cur_row - 2, rc - 2)split(cur_row + 2, lc + 2, rr - 2, cur_col - 2)split(cur_row + 2, cur_col + 2, rr - 2, rc - 2) self.matrix[self.start[0], self.start[1]] = 0self.matrix[self.destination[0], self.destination[1]] = 0split(0, 0, self.height - 1, self.width - 1)# 最小生成树算法-kruskal(选边法)思想生成迷宫地图,这种实现方法最复杂。def generate_matrix_kruskal(self):# 地图初始化,并将出口和入口处的值设置为0self.matrix = -np.ones((self.height, self.width))def check(row, col):ans, counter = [], 0for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]:row_, col_ = row + d[0], col + d[1]if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width - 1 and self.matrix[row_, col_] == -1:ans.append([d[0] * 2, d[1] * 2])counter += 1if counter <= 1:return []return ansnodes = set()row = 1while row < self.height:col = 1while col < self.width:self.matrix[row, col] = 0nodes.add((row, col))col += 2row += 2unionset = UnionSet(nodes)while unionset.count > 1:row, col = nodes.pop()directions = check(row, col)if len(directions):random.shuffle(directions)for d in directions:row_, col_ = row + d[0], col + d[1]if unionset.find((row, col)) == unionset.find((row_, col_)):continuenodes.add((row, col))unionset.count -= 1unionset.union((row, col), (row_, col_))if row == row_:self.matrix[row][min(col, col_) + 1] = 0else:self.matrix[min(row, row_) + 1][col] = 0breakself.matrix[self.start[0], self.start[1]] = 0self.matrix[self.destination[0], self.destination[1]] = 0# 迷宫寻路算法dfsdef find_path_dfs(self, destination):visited = [[0 for i in range(self.width)] for j in range(self.height)]def dfs(path):visited[path[-1][0]][path[-1][1]] = 1if path[-1][0] == destination[0] and path[-1][1] == destination[1]:self.path = path[:]returnfor d in [[0, 1], [0, -1], [1, 0], [-1, 0]]:row_, col_ = path[-1][0] + d[0], path[-1][1] + d[1]if row_ > 0 and row_ < self.height - 1 and col_ > 0 and col_ < self.width and visited[row_][col_] == 0 and self.matrix[row_][col_] == 0:dfs(path + [[row_, col_]])dfs([[self.start[0], self.start[1]]])if __name__ == '__main__':maze = Maze(51, 51)maze.generate_matrix_kruskal()maze.print_matrix()maze.find_path_dfs(maze.destination)print("answer", maze.path)maze.print_matrix()

迷宫可视化源码 maze.py

import tkinter as tk
from mazeGenerator import Maze
import time
import copy
import numpy as np
import math
import threadingdef draw_cell(canvas, row, col, color="#F2F2F2"):x0, y0 = col * cell_width, row * cell_widthx1, y1 = x0 + cell_width, y0 + cell_widthcanvas.create_rectangle(x0, y0, x1, y1, fill = color, outline =color, width = 0)def draw_path(canvas, matrix, row, col, color, line_color):# 列if row + 1 < rows and matrix[row - 1][col] >= 1 and matrix[row + 1][col] >= 1:x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_widthx1, y1 = x0 + cell_width / 5, y0 + cell_width# 行elif col + 1 < cols and matrix[row][col - 1] >= 1 and matrix[row][col + 1] >= 1:x0, y0 = col * cell_width, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + cell_width, y0 + cell_width / 5# 左上角elif col + 1 < cols and row + 1 < rows and matrix[row][col + 1] >= 1 and matrix[row + 1][col] >= 1:x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5canvas.create_rectangle(x0, y0, x1, y1, fill = color, outline = line_color, width = 0)x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5# 右上角elif row + 1 < rows and matrix[row][col - 1] >= 1 and matrix[row + 1][col] >= 1:x0, y0 = col * cell_width, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5canvas.create_rectangle(x0, y0, x1, y1, fill = color, outline = line_color, width = 0)x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5# 左下角elif col + 1 < cols and matrix[row - 1][col] >= 1 and matrix[row][col + 1] >= 1:x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_widthx1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5canvas.create_rectangle(x0, y0, x1, y1, fill = color, outline = line_color, width = 0)x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5# 右下角elif matrix[row - 1][col] >= 1 and matrix[row][col - 1] >= 1:x0, y0 = col * cell_width, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + 3 * cell_width / 5, y0 + cell_width / 5canvas.create_rectangle(x0, y0, x1, y1, fill = color, outline = line_color, width = 0)x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_widthx1, y1 = x0 + cell_width / 5, y0 + 3 * cell_width / 5else:x0, y0 = col * cell_width + 2 * cell_width / 5, row * cell_width + 2 * cell_width / 5x1, y1 = x0 + cell_width / 5, y0 + cell_width / 5canvas.create_rectangle(x0, y0, x1, y1, fill = color, outline = line_color, width = 0)def draw_maze(canvas, matrix, path, moves):"""根据matrix中每个位置的值绘图:-1: 墙壁0: 空白1: 参考路径2: 移动过的位置"""for r in range(rows):for c in range(cols):if matrix[r][c] == 0:draw_cell(canvas, r, c)elif matrix[r][c] == -1:draw_cell(canvas, r, c, '#525288')elif matrix[r][c] == 1:draw_cell(canvas, r, c)draw_path(canvas, matrix, r, c, '#bc84a8', '#bc84a8')elif matrix[r][c] == 2:draw_cell(canvas, r, c)draw_path(canvas, matrix, r, c, '#ee3f4d', '#ee3f4d')for p in path:matrix[p[0]][p[1]] = 1for move in moves:matrix[move[0]][move[1]] = 2def update_maze(canvas, matrix, path, moves):canvas.delete("all")matrix = copy.copy(matrix)for p in path:matrix[p[0]][p[1]] = 1for move in moves:matrix[move[0]][move[1]] = 2row, col = movement_list[-1]colors = ['#525288', '#F2F2F2', '#525288', '#F2F2F2', '#525288', '#F2F2F2', '#525288', '#F2F2F2']if level > 2:colors = ['#232323', '#252525', '#2a2a32', '#424242', '#434368', '#b4b4b4', '#525288', '#F2F2F2']for r in range(rows):for c in range(cols):distance = (row - r) * (row - r) + (col - c) * (col - c)if distance >= 100:color = colors[0:2]elif distance >= 60:color = colors[2:4]elif distance >= 30:color = colors[4:6]else:color = colors[6:8]if matrix[r][c] == 0:draw_cell(canvas, r, c, color[1])elif matrix[r][c] == -1:draw_cell(canvas, r, c, color[0])elif matrix[r][c] == 1:draw_cell(canvas, r, c, color[1])draw_path(canvas, matrix, r, c, '#bc84a8', '#bc84a8')elif matrix[r][c] == 2:draw_cell(canvas, r, c, color[1])draw_path(canvas, matrix, r, c, '#ee3f4d', '#ee3f4d')def check_reach():global next_maze_flagif movement_list[-1] == maze.destination:print("Congratulations! You reach the goal! The step used: {}".format(click_counter))x0, y0 = width / 2 - 200, 30x1, y1 = x0 + 400, y0 + 40canvas.create_rectangle(x0, y0, x1, y1, fill = '#F2F2F2', outline ='#525288', width = 3)canvas.create_text(width / 2, y0 + 20, text = "Congratulations! You reach the goal! Steps used: {}".format(click_counter), fill = "#525288")next_maze_flag = Truedef _eventHandler(event):global movement_listglobal click_counterglobal next_maze_flagglobal levelif not next_maze_flag and event.keysym  in ['Left', 'Right', 'Up', 'Down']:click_counter += 1windows.title("Maze Level-{} Steps-{}".format(level, click_counter))cur_pos = movement_list[-1]ops = {'Left': [0, -1], 'Right': [0, 1], 'Up': [-1, 0], 'Down': [1, 0]}r_, c_ = cur_pos[0] + ops[event.keysym][0], cur_pos[1] + ops[event.keysym][1]if len(movement_list) > 1 and [r_, c_] == movement_list[-2]:movement_list.pop()while True:cur_pos = movement_list[-1]counter = 0for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]:r_, c_ = cur_pos[0] + d[0], cur_pos[1] + d[1]if c_ >= 0 and maze.matrix[r_][c_] == 0:counter += 1if counter != 2:breakmovement_list.pop()elif r_ < maze.height and c_ < maze.width and maze.matrix[r_][c_] == 0:while True:movement_list.append([r_, c_])temp_list = []for d in [[0, 1], [0, -1], [1, 0], [-1, 0]]:r__, c__ = r_ + d[0], c_ + d[1]if c__ < maze.width and maze.matrix[r__][c__] == 0 and [r__, c__] != cur_pos:temp_list.append([r__, c__])if len(temp_list) != 1:breakcur_pos = [r_, c_]r_, c_ = temp_list[0]update_maze(canvas, maze.matrix, maze.path, movement_list)check_reach()elif next_maze_flag:next_maze_flag = Falsemovement_list = [maze.start]click_counter = 0maze.generate_matrix_kruskal()maze.path = []draw_maze(canvas, maze.matrix, maze.path, movement_list)level += 1def _paint(event):x, y = math.floor((event.y - 1) / cell_width), math.floor((event.x - 1) / cell_width)if maze.matrix[x][y] == 0:maze.find_path_dfs([x, y])update_maze(canvas, maze.matrix, maze.path, movement_list)def _reset(event):maze.path = []update_maze(canvas, maze.matrix, maze.path, movement_list)if __name__ == '__main__':# 基础参数cell_width = 20rows = 37cols = 51height = cell_width * rowswidth = cell_width * colslevel = 1click_counter = 0next_maze_flag = Falsewindows = tk.Tk()windows.title("Maze")canvas = tk.Canvas(windows, background="#F2F2F2", width = width, height = height)canvas.pack()maze = Maze(cols, rows)movement_list = [maze.start]maze.generate_matrix_kruskal()draw_maze(canvas, maze.matrix, maze.path, movement_list)canvas.bind("<Button-1>", _paint)canvas.bind("<Button-3>", _reset)canvas.bind_all("<KeyPress>", _eventHandler)windows.mainloop()

将以上两个代码分别保存到mazeGenerator.py 和maze.py,确保两个py文件在同一文件夹下,运行maze.py即可。

(暂时 完)

迷宫游戏python实现相关推荐

  1. python迷宫小游戏代码_课内资源 - 基于python实现的迷宫游戏

    一.项目概述与编译环境 本次大作业选题为题目2,即小兔子找胡萝卜的迷宫问题,最终完成开发的游戏名为Caveman and Treasure(穴居人寻宝),游戏整体界面如下: 该项目在windows下编 ...

  2. Python实现迷宫游戏

    项目:迷宫游戏 摘要 1.引言 1.1研究的背景及意义 1.2研究的内容 2.系统结构 2.1系统的结构 2.2基本思路 3.实现代码 3.1Maze类 3.2Player类 3.3Controlle ...

  3. Python 用Ursina引擎制作一个3D迷宫游戏

    Ursina是一个3D引擎,初步使用方法,见以下文章: 手把手教你用Python编一个<我的世界> 1. 认识Ursina并学会绘制立体图形_Leleprogrammer的博客-CSDN博 ...

  4. Python迷宫游戏

    Python迷宫游戏 1. 简介 2. 实验环境 3. 各部分代码详解 (1) 定义迷宫关卡 (2) 利用海龟库建立迷宫背景 (3) 注册一下需要使用到的图片 (4)定义金币类和旗子类 (5)定义一个 ...

  5. python可视化迷宫求解_如何用 Python 制作一个迷宫游戏

    相信大家都玩过迷宫的游戏,对于简单的迷宫,我们可以一眼就看出通路,但是对于复杂的迷宫,可能要仔细寻找好久,甚至耗费数天,然后可能还要分别从入口和出口两头寻找才能找的到通路,甚至也可能找不到通路. 虽然 ...

  6. Python 制作迷宫游戏(二)——游戏窗口

    Python 制作迷宫游戏(二)--游戏窗口 上一节我们使用prime做了迷宫的底层数组,它的形式是一个二维数组. 这一节我们着手开始制作游戏窗口 使用模块 pygame 在这项迷宫游戏的制作当中需要 ...

  7. Python 制作迷宫游戏(三)——地图精灵

    Python 制作迷宫游戏(三)--地图精灵 上一节我们已经成功的生成了一个游戏窗口 这一节我们将试着把地图的瓦片与地图数组绑定并绘制到窗口中 当然,作为一个迷宫,地图的作用不仅仅是背景板,它最为重要 ...

  8. python文字游戏循环3次_如何停止迭代for循环以便玩家可以在Python迷宫游戏中移动?...

    我使用的是Python 3,而且我非常非常缺乏经验,所以请善待.我有一个迷宫游戏,也是一个语言词汇游戏.除了一件事之外,一切都像是应该的.当玩家滚过"黄金"并弹出问题时,for循环 ...

  9. 用Python编写迷宫游戏

    文章目录 1. 项目概述 1.1 项目目标和主要内容 1.2 项目的主要功能 2. 项目设计 2.1项目总体框架 2.2 关键算法分析 3.设计步骤 3.1导入模块 3.2生成迷宫 3.3定义走迷宫函 ...

最新文章

  1. 关于GridView手动绑定的一段代码,一切尽在不言中
  2. phpsso.php 注入漏洞,PHPCMS各种注入漏洞补丁
  3. Knockout应用开发指南 第六章:加载或保存JSON数据
  4. 【转】关于编译链接——gcc/g++
  5. 里程碑:DTrace 切换到 GPL 许可证
  6. EntityFramework Code-First 简易教程(三)-------数据库初始化
  7. iptables的地址取反操作
  8. 【Linux】一步一步学Linux系统编程教程汇总(暂时暂停更新......)
  9. 警示:强制关闭OGG进程触发bug致abended,详述处理过程
  10. php数组拆分的函数是,php基础之数组的合并、拆分、区别取值函数集
  11. 经纬张颖「炮轰」扫码点餐;淘宝特价版给拼多多送芒果;Firefox 87.0 发布|极客头条...
  12. 两个网卡做映射linux,linux多网卡的路由模式和桥接模式设置方法
  13. Cisco路由器VLan隔离局域网广播包的配置实验
  14. 【script】python 调用阿里云解析 DNS API 实现 DDNS(动态域名解析)
  15. IDC发布最新中国AI云服务市场报告,百度智能云排名第一
  16. 好用的web报表设计器(报表工具)
  17. 日期转换和日历的使用方法
  18. 廖雪峰的0Python教程
  19. 微博android升级7.000,华为 Android 7.0 升级计划曝光:G9 青春版 /Nova 也有份
  20. 【复盘】记录生产环境问题,因没有及时合并maser

热门文章

  1. 【安装软件】 win10安装iTunes报错:“此Windows Installer软件包有一个问题。完成此安装需要......”的解决方式
  2. 树莓派浏览网页,显示无法打开此网址
  3. 达索系统、西门子、PTC、欧特克、SAP的PLM系统优缺点比较?
  4. 如何用Qt绘制一颗好看的二叉树
  5. 局域网内配置可访问mysql数据库
  6. 数据库内容:园林中级支撑题库软件开发内容
  7. Linux主机Windows容器,了解用于Linux和 Windows容器的Docker“容器主机”与“容器操作系统”...
  8. QML 地图修改插件源码(三),Map在Plugin中设置加载地图类型
  9. 基于ARM核心板实现的BMS可行性方案
  10. 骑行318、 2016.7.30