作为一项古老的智力游戏,千百年来迷宫都散发着迷人的魅力。但是,手工设计迷宫费时又耗(脑)力,于是,我们有必要制作一个程序:迷宫生成器……

好吧,我编不下去了。但是,从上面的文字中,我们可以看出,我们此次的主题是:用Python实现一个迷宫生成器。

首先展示一下效果图:

我们先分析一下所需的库:

既然是生成器,每次生成的迷宫一模一样显然是说不过去的。因此,我们不可避免地要使用随机数(Random库)。迷宫一定是要绘制的,所以需要有一个GUI库或绘图库,这里我使用Pygame(Tkinter或Turtle其实都可以做到,但毕竟Pygame比较顺手)。与Pygame搭配,Sys似乎也是需要的(用于退出程序,但其实不使用似乎也无伤大雅)。然后是Tkinter.filedialog,主要用于询问保存路径(生成的迷宫总得保存吧)。当然,用Time加一个计时器似乎是锦上添花。

于是,就有:

#coding:utf-8
import contextlib
with contextlib.redirect_stdout(None):
import pygame
import random
import sys
import time
from tkinter.filedialog import *

这里要说明的是,由于导入Pygame时会输出版本信息等很多内容(这很影响美感),我们需要使用Contextlib阻止它输出。

接下来,我们需要询问一些参数:

a=int(input("列数:"))
b=int(input("行数:"))
l=int(input("大小:"))
saveit=input("是否保存:")

然后,就要运行生成迷宫的程序了。同时,我们有必要计录一下时间(相当于开启计时器):

print("生成中...")
e = time.time()

然后就是正式生成迷宫。在介绍这部分代码之前,我们需要了解一下算法:

第一步,生成一个由迷宫单元(白格)和墙(黑格)组成的网格。一行中迷宫单元的数量为迷宫的列数,一列找迷宫单元的数量为迷宫的行数。令左上角的迷宫单元为起点,右下角的迷宫单元为终点,打破起点左边与终点右边的墙,如图所示:

第二步,访问各迷宫单元。将起点标记为当前迷宫单元,当存在未被访问的迷宫单元(凡是曾经成为过当前迷宫单元的迷宫单元,都视为已访问)时,重复执行:

  • 将周围的未被访问的迷宫单元加入表格;
  • 如果表格中有迷宫单元:
    • 将当前迷宫单元入栈(可以理解为将其加入一个叫做栈的表格);
    • 从表格中随机选择一个迷宫单元;
    • 打破当前迷宫单元与选择的迷宫单元之间的墙;
    • 将选择的迷宫单元标记为当前迷宫单元;
  • 如果表格中没有迷宫单元:
    • 栈顶迷宫单元出栈(可以理解为将栈中的最后一个元素获取并删除);
    • 将出栈的迷宫单元设为当前迷宫单元;

在循环结束以后,就会出现像文章开头效果图一样的结果。

接下来,我们就要将文字化的算法转化为Python的代码。

首先,程序是不认识图片的,它认识的是数据。所以我们需要设置一个二维列表,以此来用一串数据表示当前的图像。当然,我们可以顺便将第一步的设置一起完成:

alist = []
aa=0
need=[]
for j in range(2*a+1):
if aa==0:
aa = 1
alistone = []
for i in range(2*b+1):
alistone.append(1)
alist.append(alistone)
else:
aa=0
alistone = []
bb=0
for i in range(2*b+1):
if bb==0:
bb=1
alistone.append(1)
else:
bb = 0
need.append((j,i))
alistone.append(0)
alist.append(alistone)
alist[0][1]=0
alist[-1][-2]=0

可以看到,除此以外我们还建立了一个列表need,里面存储了所有的迷宫单元。它的作用就是判断迷宫单元是否被访问,每次访问都会将迷宫单元从表格中删除,当表格中没有迷宫单元时,就说明所有迷宫单元都被访问了。

x=1
y=1
need.remove((1, 1))
listing=[]
while len(need)>0:
aroundit=[]
try:
if x-2<0:
print(1+"1")
alist[x-2][y]=0
if (x-2,y) in need:
aroundit.append("alist[x-1][y],x=(0,x-2)")
except:
while False:
print()
try:
alist[x+2][y]=0
if (x+2,y) in need:
aroundit.append("alist[x+1][y],x=(0,x+2)")
except:
while False:
print()
try:
alist[x][y+2]=0
if (x,y+2) in need:
aroundit.append("alist[x][y+1],y=(0,y+2)")
except:
while False:
print()
try:
if y-2<0:
print(1+"1")
alist[x][y-2]=0
if (x,y-2) in need:
aroundit.append("alist[x][y-1],y=(0,y-2)")
except:
while False:
print()
if len(aroundit)>0:
listing.append((x,y))
exec(random.choice(aroundit))
need.remove((x, y))
else:
x,y=listing[-1]
listing.pop()

而这些内容,就是第二步。其算法我已经解释过,唯一一个微小的不同是,在此处我们并没有在列表中加入相邻迷宫单元的坐标,而是将其对应的破墙和标记为当前迷宫单元的代码以字符串的形式存储在表格中,并在随机选择出某个迷宫单元所对应的字符串后,使用exec将其转换为代码并运行(这可以节省一些代码)。

print("完成!用时{}秒".format(time.time()-e))

打印完生成迷宫的用时后,我们需要将表格中的数据转化为图像了。当然,在此之前,我们要先确定图片保存的位置。

if saveit=="1":
ccc = askdirectory()
h=""
bbbbb=1
while True:
try:
open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")
h="({})".format(bbbbb)
except:
break
bbbbb+=1

由于使用时有可能选择不保存图片,因此要先判断你的选择是保存还是不保存。这里字符“1”表示保存(输入其他,自然就是不保存了)。然后我们需要让你选择保存路径(askdirectory()询问的是文件路径,不需要选择文件名)。然后,我们要确定文件名称:“a×b迷宫.png”。这里需要判断指定路径是否存在此名称的文件,如果存在,则我们需要在后面加上序号。总而言之,通过这串代码,我们已经将迷宫的路径+文件名确定了。

pygame.init()
icon=pygame.image.load("迷宫.png")
pygame.display.set_icon(icon)
screen=pygame.display.Info()
screen = pygame.display.set_mode((l*(2*a+1),l*(2*b+1)))
pygame.display.set_caption('迷宫')
screen.fill("white")
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
for i in range(2*a+1):
for j in range(2*b+1):
if alist[i][j]==0:
screen.blit(c, (i*l, j*l))
elif alist[i][j]==1:
screen.blit(d, (i*l, j*l))
pygame.display.flip()
if saveit=="1":
pygame.image.save(screen, "{}/{}×{}迷宫{}.png".format(ccc, a, b, h))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

这里主要是Pygame的基本设置,并将表格内容图像化。每一个数字代表一个方块,而数字的值则决定了方块的颜色,数字在表格中的位置决定了方块的位置。就这样,我们呢将表格完全转化成了图像。当然,我们还需要用pygame.image.save()函数将图像保存为图片文件。

这样,这个生成器似乎完成了。

它运行良好,但当迷宫比较复杂时,暴露出一个问题(下图是100×100的迷宫):

由于正确路径过于曲折,在复杂度较高时,这个迷宫的难度会变得极高!

难度高,在某方面上讲,的确是好事。但当你向你的朋友们展示这个迷宫时,如果你自己也无法得出正确的路径,这不是很扫兴吗?

因此,一个寻路算法变得非常有必要。

寻路算法的大体思路:

在生成的迷宫中,白格为路,黑格为墙。将起点设置为当前位置,重复执行直到终点成为当前位置:

  • 将当前位置标记为正确路径;
  • 将周围未标记的路加入一个表格;
  • 如果表格不空:
    • 将当前位置入栈;
    • 从表格中随机选择一条路,并将其设为当前位置;
  • 如果表格是空的:
    • 栈顶的路出栈;
    • 将其设为当前位置;

通过这个算法,我们可以试出正确的路径(如图):

代码的实现:

x2=0
y2=1
listing2=[]
while not(alist[-1][-2]==2):
alist[x2][y2]=3
around2=[]
try:
if x2-1<0:
print(1+"1") if alist[x2-1][y2]==0:
around2.append("x2=x2-1")
except:
while False:
print()
try: if alist[x2+1][y2]==0:
around2.append("x2=x2+1")
except:
while False:
print()
try: if alist[x2][y2+1]==0:
around2.append("y2=y2+1")
except:
while False:
print()
try:
if y2-1<0:
print(1+"1")
if alist[x2][y2-1]==0:
around2.append("y2=y2-1")
except:
while False:
print()
if len(around2)>0:
listing2.append((x2,y2))
exec(random.choice(around2))
else:
alist[x2][y2]=2
x2,y2=listing2[-1]
listing2.pop()
alist[-1][-2]=3
for i in range(len(alist)):
for j in range(len(alist[0])):
if alist[i][j]==2:
alist[i][j]=0

同时,图像绘制的过程也要作出一些改动,以显示正确路径:

if saveit=="1":
ccc = askdirectory()
h=""
bbbbb=1
while True:
try:
open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")
open("{}/{}×{}迷宫(正确线路){}.png".format(ccc,a,b,h),"r")
h="({})".format(bbbbb)
except:
break
bbbbb+=1
pygame.init()
icon=pygame.image.load("迷宫.png")
pygame.display.set_icon(icon)
screen=pygame.display.Info()
screen = pygame.display.set_mode((l*(2*a+1),l*(2*b+1)))
pygame.display.set_caption('迷宫')
screen.fill("white")
if saveit=="1":
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='white')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.image.save(screen, "{}/{}×{}迷宫{}.png".format(ccc, a, b, h))
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='red')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.image.save(screen, "{}/{}×{}迷宫(正确线路){}.png".format(ccc, a, b, h))
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='white')
for i in range(2*a+1):
for j in range(2*b+1):
if alist[i][j]==0:
screen.blit(c, (i*l, j*l))
elif alist[i][j]==1:
screen.blit(d, (i*l, j*l))
else:
screen.blit(f,(i*l, j*l))
pygame.display.flip()
aaaaaaa = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if aaaaaaa == 1:
aaaaaaa = 0
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='white')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.display.flip()
else:
aaaaaaa = 1
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='red')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.display.flip()

通过这些改动,显示正确路径的效果就实现了。生成完成以后,窗口上显示的是没有正确路径的迷宫,而点击窗口后,正确的路径就会显示(再次点击隐藏)。

刚刚那张100×100的迷宫,其正确路径是:

可以看出,本文中所用的算法生成的迷宫,其正确路径还是非常曲折的(难度很高)。你何不将其发给你的朋友,让其破解一下呢?

完整的代码:

#coding:utf-8
import contextlib
with contextlib.redirect_stdout(None):
import pygame
import random
import sys
import time
from tkinter.filedialog import *
a=int(input("列数:"))
b=int(input("行数:"))
l=int(input("大小:"))
saveit=input("是否保存:")
print("生成中...")
e = time.time()
alist = []
aa=0
need=[]
for j in range(2*a+1):
if aa==0:
aa = 1
alistone = []
for i in range(2*b+1):
alistone.append(1)
alist.append(alistone)
else:
aa=0
alistone = []
bb=0
for i in range(2*b+1):
if bb==0:
bb=1
alistone.append(1)
else:
bb = 0
need.append((j,i))
alistone.append(0)
alist.append(alistone)
alist[0][1]=0
alist[-1][-2]=0
x=1
y=1
need.remove((1, 1))
listing=[]
while len(need)>0:
aroundit=[]
try:
if x-2<0:
print(1+"1")
alist[x-2][y]=0
if (x-2,y) in need:
aroundit.append("alist[x-1][y],x=(0,x-2)")
except:
while False:
print()
try:
alist[x+2][y]=0
if (x+2,y) in need:
aroundit.append("alist[x+1][y],x=(0,x+2)")
except:
while False:
print()
try:
alist[x][y+2]=0
if (x,y+2) in need:
aroundit.append("alist[x][y+1],y=(0,y+2)")
except:
while False:
print()
try:
if y-2<0:
print(1+"1")
alist[x][y-2]=0
if (x,y-2) in need:
aroundit.append("alist[x][y-1],y=(0,y-2)")
except:
while False:
print()
if len(aroundit)>0:
listing.append((x,y))
exec(random.choice(aroundit))
need.remove((x, y))
else:
x,y=listing[-1]
listing.pop()
x2=0
y2=1
listing2=[]
while not(alist[-1][-2]==2):
alist[x2][y2]=3
around2=[]
try:
if x2-1<0:
print(1+"1") if alist[x2-1][y2]==0:
around2.append("x2=x2-1")
except:
while False:
print()
try: if alist[x2+1][y2]==0:
around2.append("x2=x2+1")
except:
while False:
print()
try: if alist[x2][y2+1]==0:
around2.append("y2=y2+1")
except:
while False:
print()
try:
if y2-1<0:
print(1+"1")
if alist[x2][y2-1]==0:
around2.append("y2=y2-1")
except:
while False:
print()
if len(around2)>0:
listing2.append((x2,y2))
exec(random.choice(around2))
else:
alist[x2][y2]=2
x2,y2=listing2[-1]
listing2.pop()
alist[-1][-2]=3
for i in range(len(alist)):
for j in range(len(alist[0])):
if alist[i][j]==2:
alist[i][j]=0
print("完成!用时{}秒".format(time.time()-e))
if saveit=="1":
ccc = askdirectory()
h=""
bbbbb=1
while True:
try:
open("{}/{}×{}迷宫{}.png".format(ccc,a,b,h),"r")
open("{}/{}×{}迷宫(正确线路){}.png".format(ccc,a,b,h),"r")
h="({})".format(bbbbb)
except:
break
bbbbb+=1
pygame.init()
icon=pygame.image.load("迷宫.png")
pygame.display.set_icon(icon)
screen=pygame.display.Info()
screen = pygame.display.set_mode((l*(2*a+1),l*(2*b+1)))
pygame.display.set_caption('迷宫')
screen.fill("white")
if saveit=="1":
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='white')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.image.save(screen, "{}/{}×{}迷宫{}.png".format(ccc, a, b, h))
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='red')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.image.save(screen, "{}/{}×{}迷宫(正确线路){}.png".format(ccc, a, b, h))
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='white')
for i in range(2*a+1):
for j in range(2*b+1):
if alist[i][j]==0:
screen.blit(c, (i*l, j*l))
elif alist[i][j]==1:
screen.blit(d, (i*l, j*l))
else:
screen.blit(f,(i*l, j*l))
pygame.display.flip()
aaaaaaa = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if aaaaaaa == 1:
aaaaaaa = 0
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='white')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.display.flip()
else:
aaaaaaa = 1
c = pygame.Surface((l, l), flags=pygame.HWSURFACE)
c.fill(color='white')
d = pygame.Surface((l, l), flags=pygame.HWSURFACE)
d.fill(color='black')
f = pygame.Surface((l, l), flags=pygame.HWSURFACE)
f.fill(color='red')
for i in range(2 * a + 1):
for j in range(2 * b + 1):
if alist[i][j] == 0:
screen.blit(c, (i * l, j * l))
elif alist[i][j] == 1:
screen.blit(d, (i * l, j * l))
else:
screen.blit(f, (i * l, j * l))
pygame.display.flip()

Python迷宫生成器的更多相关文章

  1. python 列表生成器

    python 列表生成器 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 一个循环 在C语言等其他语言中,for循环一般是这样的 ...

  2. python 迭代器 生成器

    迭代器 生成器 一 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前 ...

  3. python中和生成器协程相关的yield from之最详最强解释,一看就懂(四)

    如果认真读过上文的朋友,应该已经明白了yield from实现的底层generator到caller的上传数据通道是什么了.本文重点讲yield from所实现的caller到coroutine的向下 ...

  4. python中和生成器协程相关yield from之最详最强解释,一看就懂(二)

    一. 从列表中yield  语法形式:yield from <可迭代的对象实例> python中的列表是可迭代的, 如果想构造一个生成器逐一产生list中元素,按之前的yield语法,是在 ...

  5. python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

    yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...

  6. Python中生成器和迭代器的区别(代码在Python3.5下测试):

    https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...

  7. Python的生成器进阶玩法

    Python的生成器进阶玩法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.yield的表达式形式 #!/usr/bin/env python #_*_coding:utf-8 ...

  8. python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解

    一.生成器 1.什么是生成器? 在python中,一边循环一边计算的机制,称为生成器:generator. 2.生成器有什么优点? 1.节约内存.python在使用生成器时对延迟操作提供了支持.所谓延 ...

  9. python中生成器对象和return 还有循环的区别

    python中生成器对象和return 还有循环的区别 在python中存在这么一个关键字yield,这个关键字在项目中经常被用到,比如我写一个函数不想它只返回一次就结束那我们就不能用return,因 ...

随机推荐

  1. 基于Ansible实现Apache Doris快速部署运维指南

    Doris Ansible 使用指南 Apache Doris 介绍 Apache Doris是一个现代化的MPP分析型数据库产品.仅需亚秒级响应时间即可获得查询结果,有效地支持实时数据分析.Apac ...

  2. django orm 更新数据时间不自动更新问题

    gmt_create自动添加auto_now_add:gmt_modify自动更新auto_now class CommonInfo(models.Model): """ ...

  3. XCTF练习题---MISC---2017_Dating_in_Singapore

    XCTF练习题---MISC---2017_Dating_in_Singapore flag:HITB{CTFFUN} 解题步骤: 1.观察题目,下载附件 2.打开附件后发现是一张日历,还是新加坡的, ...

  4. MVC 的dao层、service层和controller层

    1.dao层 dao层主要做数据持久层的工作, 负责与数据库进行联络的一些任务都封装在此 ,dao层的设计 首先 是设计dao层的接口,然后在Spring的配置文件中定义此接口的实现类,然后就可以再模 ...

  5. CNN-Backbone的Pytorch实现

    创建日期: 2020-07-04 17:19:39 简介:卷积神经网络非常适合处理图像相关任务,其优势一是权值共享策略,降低了模型复杂度和参数量,本质上也对应着生物视觉神经的感受野.二是其强大的特征提 ...

  6. 从防御者视角来看APT攻击

    前言 APT防御的重要性毋庸讳言,为了帮助各位师傅在防御方面建立一个总体认识,本文会将APT防御方法分为三类,分别是:监控.检测和缓解技术,并分别进行梳理,介绍分析代表性技术.这一篇分析现有的监控技术 ...

  7. 跨云平台与物理专线使用Vxlan实现两地二层互通,并使用ospf与bgp做底层链路主备

    Vxlan基础,已掌握可略过 VXLAN网络架构 VXLAN是NVO3中的一种网络虚拟化技术,通过将原主机发出的数据包封装在UDP中,并使用物理网络的IP.MAC作为外层头进行封装,然后在IP网络上传 ...

  8. jmeter 基础使用

    相关入门链接 JMeter 5.4.1 教程 插件安装 并发线程 ServerAgent 服务器监控 ServerAgent 下载 Ubuntu 20.04 install jdk/jre 服务器监控 ...

  9. data:image字符转byte[]

    var data = "data:image/bmp;base64,Qk3aHwAAAAAAADYAAAAoAAAAZAAAABsAAAABABgAAAAAAKQfAAAAAQAAAAEAA ...

  10. Pandas复杂查询、数据类型转换、数据排序

    Pandas高级操作 1.复杂查询 (1)逻辑运算 以DataFrame其中一列进行逻辑计算,会产生一个对应的bool值组成的Series 于是我们可以利用返回的bool列表进行一系列的数据查询 (2 ...