Windows装不上Wordcloud?看这里

如果你是一个写Python,且又喜欢做词云的朋友。

你应该遇到过Windows上跑不动你词云程序的情况,比如你可能在装Wordcloud时候会遇到如下情况:

虽然网上也有一些教程,但好像都不是很清晰。

有的教程,干脆让我们先去下载一个微软的Visual Studio……

其实,就差一个C++生成工具。

而这个工具包含在了Build tools这么个套件里面。

下载地址:

https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16

打开以后不要慌,选中这个勾就行。

如果你的硬盘不富裕,就别全选了,继续往后边看。

我一般是选这几个。

然后,该程序会提醒你。要下载4.4GB左右的组件包。

管你要不要,反正它要下载。

好的一点是,它可以边下边安装,总算能节约一点时间。

下载完成后要重启生效。

然后,你的wordcloud就可以装上了。

下面写段代码测试一下:

from wordcloud import WordCloud

f = open('text.txt','r',encoding='utf8').read()
wordcloud = WordCloud(background_color="white",width=800, height=600, margin=2).generate(f)

# width,height,margin可以设置图片属性
wordcloud = WordCloud(font_path = r'simsun.ttf').generate(f)
# 你可以通过font_path参数来设置字体集
#background_color参数为设置背景颜色,默认颜色为黑色

import matplotlib.pyplot as plt
plt.imshow(wordcloud)
plt.axis("off")
plt.show()

wordcloud.to_file('test.png')

能生成词云了,只是不够好看,得再调整一下。

更多精彩内容,欢迎关注“IoT前哨站”的微博和公众号。我是王文文。

用Python实现经典游戏《小蜜蜂》

估计很多老玩家在小时候都玩过Galaxian(小蜜蜂)吧。这款射击游戏的鼻祖叫《太空侵略者》,上手简单,但可玩性很强。

高手用C语言精准复现的1978年《太空侵略者》版本

《太空侵略者》大火之后,新推出的Galaxian(小蜜蜂)于1979年成为其最大竞争对手。由Namco发行的Galaxian为外星敌人提供了新的色彩和不可预测的动作,后者不但会发射炮弹,还会自杀式俯冲攻击。

《Galaxian》在街机游戏中大受欢迎,以至于Namco在两年后又发布了续作《Galaga》——这款游戏使攻击模式更加复杂。

很难说《Galaxian》究竟有多少移植和克隆的版本,因为几乎每个家用游戏机上都有类似版本。

小霸王平台的《Galaxian》

玩家在《Galaxian》中的角色与《太空侵略者》类似,驾驶一艘飞船与一支外星舰队战斗。

与《太空侵略者》不同的是,在《Galaxian》中,外星人总会打破队形向玩家的飞船发起俯冲轰炸。

玩家需要摧毁所有敌人,然后进入下一关。随着玩家的推进,一波又一波的敌人将让过关变得更加困难。

我们这里将着眼于外星人的俯冲机制,用Pygame Zero开发《Galaxian》游戏的核心功能。

用Pygame Zero开发的版本

首先,《Galaxian》拥有一个纵向显示画面,所以我们将游戏区域的宽度和高度分别设置为600和800。

接下来,我们可以用位图创建一个滚动的星空背景。​将位图逐渐往屏幕下方移动,用第二颗恒星来填充第一颗恒星向下滚动时留下的空间,我们还可以在后面添加另一个静态背景图像,这将提供一些视野深度。

然后,我们将玩家的飞船设置为Actor。并在update()函数中捕获左右箭头键,以便在屏幕上左右移动飞船。我们也可以用空格键发射子弹,子弹会沿屏幕向上移动,直到击中外星人或离开屏幕顶部。

和原版《Galaxian》一样,你一次只能发射一颗炮弹,所以我们只需要一个Actor。

外星人排成一行,一起在屏幕上左右移动。在这个例子中,我们只画一种类型的外星人,共画两行。你可以添加额外的类型和任意多行。当我们创建alien Actors时,我们还可以添加一个状态标志,我们需要确定当它们打破队形时,它们在行的哪一边,两边朝相反的方向飞行。在这种情况下,每行左边有4个外星人,右边有4个。

一旦它们在列表中建立起来,我们就可以在每次更新时遍历列表,并向前或向后移动它们。

当我们在移动外星人时,我们也可以查看它们是否与炮弹或玩家飞船相撞。

如果与炮弹碰撞,那么外星人将使用状态标志连续播放爆炸的那几帧,当状态达到5时,它们将不再被绘制到界面上。

如果碰撞发生在玩家的飞船身上,那么玩家会死亡,游戏也就结束了。

我们也可以检查一个随机数,看看外星人是否开始轰炸。如果是,我们将状态设置为1,这将开始调用flyAlien()函数。这个函数会检查外星人的位置,并根据侧边的不同改变外星人的角度,然后根据角度更改x和y坐标。为了方便大家看明白,我们这里处理的比较简单,你也可以使用一些乘数变量将其折叠到x坐标和角度上,将其收窄。

相关代码:

https://github.com/IoToutpost/Python_game

要运行调试请先安装Pygame Zero。

现在大家应该初步掌握了Galaxian游戏的基础知识。你可以试着完善它了。

老游戏新写之Jetpac重返地球

主人公流落外星球,遇到一群不讲道理的外星人。想跑路,载具又摔得七零八落。

任务:​顶着外星人的进攻,把宇宙飞船的零件都找回来组装好,然后为其添加燃料。最后安全逃离,重返地球。

这是由Chris和Tim Stamper兄弟于1983年创建的8位机游戏Jetpac里的剧情,也是其工作室Ultimate Play the Game出品的首批热门游戏之一。

8位ZX Spectrum电脑上的Jetpac

而当一个宇航员和Ultimate Play the Game的徽标在屏幕上出现时,你知道之前的等待是值得的(八十年代能有这么个游戏玩已经很激动)。

游戏的角色是不幸的宇航员杰特曼,他必须收集四处散落的零件,制造火箭并为其添加燃料,同时还要与成群的致命外星人战斗。

本文提供的代码片段包含收集火箭零件和燃料,以便杰特曼搭载火箭起飞的技巧。

我们可以对所有屏幕元素和Actor碰撞例程使用内置的Pygame Zero Actor对象,以便处理重力并拾取物品。

首先,我们需要初始化Actor。

我们需要游戏中的主人公杰特曼,地面,火箭的三个零件,还有火箭发动机所需的一些燃料。

每个Actor的行为方式将由一组列表决定。我们有一个重力对象列表,每帧绘制的对象,平台列表,碰撞对象列表以及可以拾取的对象列表。

杰特曼跳进火箭,回家了。欢呼!

我们的draw()函数很简单,因为它循环遍历绘制列表中的项目列表,然后再绘制几个条件元素。

update()功能是所有动作发生的地方:我们检查键盘输入来移动杰特曼,将重力应用于重力列表上的所有项目,检查与平台列表的碰撞,如果杰特曼触摸它,则拾取这个项目(对象),应用对杰特曼的任何推力,并移动杰特曼持有的任何物品随他一起移动。

完成所有操作后,我们可以检查添加的燃料量是否已达到火箭可升空的程度。

如果查看辅助函数checkCollisions()checkTouching(),你会发现它们使用了不同的碰撞检测方法,第一种方法是检查与指定点的碰撞,以便我们可以检测到与actor顶部或底部的碰撞以及触摸冲突是矩形或边界框的冲突,因此如果两个Actor的边界框相交,则会记录一个冲突。

另一个辅助函数applyGravity()使重力列表中的所有元素向下移动,直到Actor的底部撞到碰撞列表上的某物为止。

目前的程序主要就是组装一枚火箭,加满燃料,然后升空。你后续要添加的是一群讨厌的外星人,以及一种用激光枪摧毁它们的方法。

以上就是Mark的Jetpac代码,你可以在这里下载。

https://github.com/IoToutpost/Python_game/

Have fun.

树莓派音乐盒,让你像DJ一样玩音乐

用按钮来控制LED灯,是树莓派比较经典的一种应用。

那用按钮来控制音乐呢?

我们这次的任务是做个树莓派音乐盒,以便你能像DJ一样,通过它不停的切换和调整音乐。

硬件需求:

  • 树莓派1个
  • 面包板1个
  • 接触式开关4个
  • 公对母跳线5根
  • 母对母跳线4根
  • 扬声器或耳机1个

软件需求:

Raspbian 最新版

制作过程:

先找到你想播放的音频文件,如果你自己没有什么准备,可以在Raspbian系统的/usr/share/sonic-pi/samples目录中找一些示例音乐。

不过你要用Python播放声音的话,得将里面的.flac文件转换为.wav文件。

批量转换命令:

for f in *.flac; do ffmpeg -i "$f" "${f%.flac}.wav"; done

如果没出错,你现在应该得到大量的wav文件了。

挑出四个备用,对应4个按钮。将其保存在gpio-music-box目录中

drum_tom_mid_hard.wav
drum_cymbal_hard.wav
drum_snare_hard.wav
drum_cowbell.wav

电路最基本的接法:

当然,用面包板会让你更方便。

示例程序中有四个按钮,所以我们要分别接入GPIO4、10、17、27四个口。

接下来开始撸代码。

import pygame
from gpiozero import Button

pygame.init()

drum = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_tom_mid_hard.wav")
cymbal = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cymbal_hard.wav")
snare = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_snare_hard.wav")
bell = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cowbell.wav")

btn_drum = Button(4)
btn_cymbal = Button(17)
btn_snare= Button(27)
btn_bell = Button(10)

btn_drum.when_pressed = drum.play
btn_cymbal.when_pressed = cymbal.play
btn_snare.when_pressed = snare.play
btn_bell.when_pressed = bell.play

以上的代码应该能正常工作,但不够简洁优雅,我们用Python的字典功能来优化一下。

创建一个字典。

button_sounds = {Button(4): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_tom_mid_hard.wav"),
                 Button(17): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cymbal_hard.wav"),
                 Button(27): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_snare_hard.wav"),
                 Button(10): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cowbell.wav")}

然后用Button作为键,Sound作为值。

优化后的代码:

import pygame
from gpiozero import Button

pygame.init()

button_sounds = {Button(4): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_tom_mid_hard.wav"),
                 Button(17): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cymbal_hard.wav"),
                 Button(27): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_snare_hard.wav"),
                 Button(10): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cowbell.wav")}

for button, sound in button_sounds.items():
    button.when_pressed = sound.play

是不是简洁多了?

好了,拿去玩吧。

视频讲解地址:

https://v.qq.com/x/page/x0967xsxe7j.html

线索:Raspberrypi.org

编译:王文文

你能不损失数百万美元成功登月吗?

对航空知识有兴趣的朋友都知道,飞行器在月球软着陆不是一件容易的事情。

即使在刚刚过去的2019年,印度也没能成功实现该技术,承载着希望的“月船2号”着陆器在距离月球表面2.1公里的时候失去了信号,从此不知所踪。

迄今为止,只有中美俄三个国家实现了月球软着陆。

印度“月船2号”着陆器失联前的直播画面

在阿波罗11号登月十周年纪念日的时候,阿塔里(Atari)公司曾经出了一款名叫“Lunar Lander”的投币式街机游戏。

游戏的玩法是通过方向调整和推力控制来引导你的着陆器,将其轻轻地放到安全而平坦的停靠区。如果玩家能将着陆器成功停放在更具挑战的险峻区域,将获得额外的积分。

街机的版本是有操纵杆的,玩家可以用其控制方向和大小不同的推力,并以屏幕顶部的海拔,水平速度和垂直速度为指导,在燃料有限的情况下按时降落飞船。

游戏内置了四个难度级别,分别调整了着陆控制器和着陆区域,玩家需要凭借高超的技巧才能涉险过关。

我们这次用Pygame Zero来简单还原一下这款游戏,如果你不打算外接操纵杆,用键盘操作也可以。

构思

首先用绘制好的静态背景替换矢量图形,并将其用作碰撞检测和高度统计。

如果我们的背景是着陆器可以飞行的黑色背景,而着陆区所在的地方是另一种颜色,那么我们可以使用Pygame的image.get_at()函数来测试像素点是否在着陆位置。

我们还可以检测着陆器沿Y轴向下的像素线,直到抵达着陆区,这将让我们获悉着陆器当前的高度。

着陆器的控制非常简单,因为我们可以捕获左右箭头键来增加或减少着陆器的旋转角度。

然而当施加推力(通过按向上箭头)时,事情会变得有些复杂。我们需要记住推力来自哪个方向,让飞船即使打转也将继续沿该方向运动。所以我们在着陆器对象上附加了direction属性。对着陆器的位置施加一点重力,然后我们只需要一点三角函数的知识即可根据着陆器的速度和行进方向算出其运动轨迹。

要判断着陆器安全着陆还是在月球表面撞坏,我们要观察其到达高度1时,飞行器的下降速度和角度。

如果速度足够慢且角度接近垂直,则我们触发着陆成功的消息,游戏结束。

如果着陆器在没有满足这些条件的情况下达到零高度,则我们将判定坠机事故。

有兴趣的话,你还可以在此基础上添加一个有限的燃料表和可变的难度级别之类的东西。甚至可以尝试添加原始街机游戏中火箭助推器噪音的声音。

要点:

推力方位的改变可以有多种方法完成。在本例中我们简单一点,一个方向被施加推力,它就逐渐往那个方向移动,直到新的方向出现推力。你可以尝试对其进行X轴和Y轴方向计算,以获得结合点的坐标值。还可以添加操纵杆控制,提供可变的推力。

以下是核心代码段:

接下来看看效果:

视频:https://v.qq.com/x/page/b095944gc59.html

完整代码请访问:https://github.com/IoToutpost/Python_game

调试前记得先安装Pygame Zero。

线索:Wireframe #37

编译:王文文

创客妹子教你做“一键发Twitter眼镜”

关注“IoT前哨站”的朋友可能记得之前我们发过一篇“让相机根据GPS定位自动拍照”的文章。

是的,那位名叫“Estefannie” 的创客妹子又出现了,这次她给大家带来的是一个可以自动发Twitter的眼镜,而且是“侏罗纪公园模式”。

什么叫侏罗纪公园模式呢?

看看这个眼镜发的Twitter内容就知道了。

发现梁龙一只
发现雷龙一只

准确的说, Estefannie 做的这个装置应该叫“侏罗纪恐龙抓拍系统”。因为她这个发的每张照片都会标一个恐龙的名字,比如:“发现梁龙”,“发现雷龙”……她在眼镜上装了一个按钮。按下就能把照片发到Twitter上。

制作流程:

Estefannie 先是找了一个像护目镜一样的眼镜模型。

用3D打印机把眼镜的原型做出来以后,对其进行打磨、喷漆、抛光。然后在上面接好树莓派Zero W,LED和按钮,加上可调节部分、软垫以及绿色镜片……

大量的涂胶、焊接和布线工作之后,她最终得到了一副漂亮的眼镜。

紧接着,她写了一个Python脚本来拍照、与Twitter交互,并通过LED环来提供眼镜当前的状态信息。树莓派系统启动时,会先连到她手机的无线热点。然后,眼镜上的红色LED亮起,表示程序正常运行。

然后,就可以戴着这个眼镜去抓拍有意思的景物了。

背景:

原本这是她被邀请去“Coolest Projects”青少年创客大会演讲而制作的道具,但你可以根据她的代码自己改改,做一个发微博或者抖音的版本。

关于详细流程,建议大家看视频。

相关视频:https://v.qq.com/x/page/c3010lo613b.html

3D模型文件: https://www.thingiverse.com/thing:3732889

代码下载: https://github.com/IoToutpost/JurassicGoggles

素材:Raspberrypi.org

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

解析Python开发的一款迷你跑步游戏

之前“IoT前哨站”上发了一些用Python写文本游戏的文章。不管对于Python开发者来说还是对于游戏爱好者来说,都非常适合打基础。

这次我们迈入图形时代,来看看国外开发者“Rik Cross”制作的一款迷你跑步游戏。

他用了不到一百行代码,就写出了值得一玩的2D动作游戏,怎么做到的?

在此之前,先向大家介绍一个游戏框架:pgzero。

该框架全名Pygame Zero,是一个基于Pygame的游戏编程框架。它可以更容易地编辑游戏,无需模板、不用编写事件循环,也无需学习复杂的Pygame API,而且支持树莓派。

安装
pip install pgzero

需求:
通过键盘的左右键操作,让运动员向前奔跑,每过25米有路标提醒,最后看谁在百米跑步中耗时最少。

代码下载地址:
https://github.com/IoToutpost/Python_game/tree/master/Sprint

素材(地址同上):
Images文件夹中有21张图,包括运动员的动作分解、跑道等。

其中的关键代码,是一个叫做Sprinter()的类。

class Sprinter(Actor):
     def init(self, **kwargs):
         super().init(image='idle', pos=(200,220), **kwargs)
         self.startTime = time()
         self.finishTime = time()
         self.runFrames = ['run' + str(i) for i in range(1,16)]
         self.timeOnCurrentFrame = 0
         self.speed = 0
         self.lastPressed = None
         self.keyPressed = False
         self.distance = 0
# 将运动员推进到下一帧
def nextFrame(self):
    # 如果当前空闲,则启动正在运行的动画。 
    if self.image == 'idle':
        self.image = self.runFrames[0]
    else:
        # 在列表中找到下一个图像,然后返回到第一个图像 
        # 当列表已经到末尾的时候
        nextImageIndex = (self.runFrames.index(self.image) + 1) % len(self.runFrames)
        self.image = self.runFrames[nextImageIndex]

# 检查左右方向键是否正确
# 被交替按下
def isNextKeyPressed(self):
    if keyboard.left and self.lastPressed is not 'left' and not keyboard.right:
        self.lastPressed = 'left'
        return True
    if keyboard.right and self.lastPressed is not 'right' and not keyboard.left:
        self.lastPressed = 'right'
        return True
    return False

def update(self):
    # 更新运动员的速度
    # 交替按键加速
    if self.isNextKeyPressed() and self.distance < 100:
        self.speed = min(self.speed + ACCELERATION, 0.15)
    # 如果没有按键,减速
    else:
        self.speed = max(0, self.speed-DECELERATION)
    # 根据运动员的速度更新距离 
    self.distance += self.speed
    # 根据运动员的速度对其进行动画 
    self.timeOnCurrentFrame += 1
    if self.speed > 0 and self.timeOnCurrentFrame > 10 - (self.speed * 75):
        self.timeOnCurrentFrame = 0
        self.nextFrame()
    # 如果不移动,则设置为空闲
    if self.speed <= 0:
        self.image = 'idle'

里面有一些变量用来跟踪运动员的速度和距离,以及全局的常量(ACCELERATION和DECELERATION的值)。这样可以确定玩家的速度变化。这些数字很小,因为它们代表了玩家加速和减速时,每一帧对应的米数。

玩家通过交替按左右键来增加运动员的速度。这个输入由Sprinter类中的isNextKeyPressed()方法处理,如果按下正确的键,该方法将返回True。

lastPressed变量用于确保左右键被交替按压。如果未按下任何键,玩家会减速,并且该减速程度应小于加速度,以免让玩家突然停下。

在游戏设计中,作者用了gameart2d.com上一个名为“The Boy”的免费形象来作为运动员,里面有15张跑步动作分解图构成的循环。他将从空闲状态开始,只要速度大于0,就切换到跑步动作循环。

这是通过index()在runFrames列表中查找当前运动员图像的名称来实现的,程序会将当前图像设置为列表中的下一个图像(并且在到达列表的末尾时返回第一个图像)。

我们还需要让运动员在跑步动作循环中以成比例的速度向前移动,通过跟踪当前图像显示的帧数来实现(在那个名为timeOnCurrentFrame的变量中)。

为了给玩家一种移动的错觉,作者添加了一些经过玩家的物品:一条终点线和三个显示跑动距离的标记。

这些物品出现的时机是根据运动员在屏幕上的x位置和运动距离计算出来的。

​然而,这意味着每个物品距离玩家最多只有100像素的距离,似乎移动的有点缓慢。我们可以通过SCALE因子来解决,它对应的是运动员跑过的米数和屏幕上像素之间的关系。比如设成1:75。

这些物品最初被绘制在屏幕看不见的右侧,然后向左移动并更快地经过运动员。

最后,startTime和finishTime变量用于计算比赛时间。这两个值最初都设置为比赛开始的时间,只要跑动的距离小于100,finishTime就会更新。使用time模块,比赛时间可以简单地计算为finishTime – startTime。

附注:该游戏在树莓派和Windows PC上都能跑,如果要试玩,记得在Python文件前面加pgzrun命令。

Have fun.

素材:Wireframe #23

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

Python图形界面开发入门之Guizero

不管是手机电脑,还是带触摸屏的终端设备,简单易用的图形界面,总是很受欢迎。

而提起Python下的图形界面开发,大家一定都会想到 PyQt 和 wxPython、Kivy 等经典模块。

不过我们这次要介绍的“guizero”,是一个非常易用的GUI库,能让初学者快速、轻松地为他们的程序创建图形界面。

安装很简单:

pip3 install guizero

这里先来个基础的例子。

from guizero import App, Text, PushButton
app = App(title="IoT前哨站")
intro = Text(app, text="试着用guizeo开发图形界面")
ok = PushButton(app, text="Ok")
app.display()

这个例子应该很容易懂,先设置窗体、标题,然后放入一个文本框和一个按钮。

由于文本框没有设置内容,所以不太看得出来,整个窗体只能发现一个按钮孤零零的杵那儿。

下面我们试着给按钮加功能,让它做一个显示字符的操作(准备让文本框发挥作用了)。

from guizero import App, Text, PushButton

def say_hello():
    text.value = "欢迎关注IoT前哨站"

from guizero import App, Text, PushButton
app = App()
text = Text(app)
button = PushButton(app, command=say_hello)
app.display() 

当你单击 Button 按钮时,原本空着的文本框会显示“欢迎关注IoT前哨站”。

如果你的程序功能比较复杂,需要另外一个窗体展示内容的时候……

from guizero import App, Window, Text
app = App(title="主窗体")
window = Window(app, title="第二窗体")
text = Text(window, text="这段文字将在第二窗体显示")
app.display()

默认情况下,guizero是自动布局,或者通过修改窗体内各部件的align属性,来调整它们的基本方位,但那肯定不够。

更细致一点的布局方式 —— 网格。

from guizero import App, PushButton
app = App(title="IoT前哨站",layout="grid")
button1 = PushButton(app, text="1", grid=[0,0])
button2 = PushButton(app, text="2", grid=[1,0])
button3  = PushButton(app, text="3", grid=[2,0])
button4  = PushButton(app, text="4", grid=[0,1])
button5  = PushButton(app, text="5", grid=[1,1])
button6  = PushButton(app, text="6", grid=[2,1])
button7  = PushButton(app, text="7", grid=[0,2])
button8  = PushButton(app, text="8", grid=[1,2])
button9  = PushButton(app, text="9", grid=[2,2])
button0  = PushButton(app, text="0", grid=[1,3])
app.display()

通过grid参数来修改各部件的[x,y]坐标,以此改变它们在窗体中出现的位置。

你也可以通过在网格参数中指定范围,使部件跨越多个列或行。这些都是可选的,但必须用[x,y,xspan,yspan]这样的格式来指定它们。

比如下面这个图片摆放的例子。

from guizero import App, Picture
app = App(title="IoT前哨站",layout="grid")
picture1 = Picture(app, image="Debian.jpg", grid=[0,0])
picture2 = Picture(app, image="IotOutpost.jpg", grid=[1,0])
picture3 = Picture(app, image="wide.jpg", grid=[0,1,2,1])
picture4 = Picture(app, image="tall.jpg", grid=[2,0,2,2])
app.display()

弹出框大家也经常在用,一般经典的就是询问、提示和警告。

from guizero import App
app = App(title="月饼提问")
build_a_snowman = app.yesno("问题", "你喜欢吃蛋黄月饼吗?")
if build_a_snowman == True:
    app.info("月饼", "这就给你拿一块过来。")
else:
    app.error("月饼", "好吧,那就不吃了。")
app.display()

再看一个经典的滑动条,假设要调整空调的温度。

from guizero import App, PushButton, Slider
app = App(title="空调操作")
button = PushButton(app, text="开/关",width=30, height=5)
slider = Slider(app, width=200, height=30)
app.display() 

下面来一个读取传感器数值并每秒钟刷新的例子。当然,为了方便演示,里面用的是随机数。

from guizero import *
import random
def read_sensor():
    return random.randrange(3200, 5310, 10) / 100
def update_label():
    text.value = read_sensor()
    # recursive call
    text.after(1000, update_label)

if name == 'main':
    app = App(title='Sensor Display!',
              height=100,
              width=200,
              layout='grid')

title = Text(app, 'Sensor value:', grid=[0, 0]) 
text = Text(app, "xx", grid=[1, 0]) 
text.after(1000, update_label) 
app.display()

最后,来一个带菜单选项的例子。

 from guizero import *

 def switch_screen(switch_to):
     hide_all()
     switch_to.show()

 def hide_all():
     for screen in all_screens:
         screen.hide()

 app = App("多选择框运用", layout="grid")
 all_screens = []

 创建一个菜单区域
 menu = Box(app, grid=[0,0], layout="grid")
 menu.tk.width = 900
 menu.bg = "gray"

 选项1
 option1 = Box(app, grid=[1,0])
 text1 = Text(option1, text="这是列表区的内容")
 combo = Combo(option1, options=["树莓派","小熊派","香橙派"])
 all_screens.append(option1)

 选项2
 option2 = Box(app, grid=[1,0])
 text2 = Text(option2, text="这是滑动框")
 slider = Slider(option2)
 all_screens.append(option2)
 
 option1_button = PushButton(menu, text="列表区", \
 command=switch_screen, args=[option1], grid=[0,0], align="left")
 option2_button = PushButton(menu, text="滑动框", \
 command=switch_screen, args=[option2], grid=[0,1], align="left")
 hide_all()
 all_screens[0].show()
 app.display()

左侧灰色的两个菜单选项,分别是“列表区”和“滑动框”,单击任意一个按钮后会出现相应内容,列表区中有个下拉式清单,而滑动框点进去是与其对应的部件。

其他的用法大家可以继续挖掘,不管你的系统是 Windows 还是 Mac、Raspbian Linux,Guizero均可支持。

虽然看着似乎有一点糙,但好在上手快。哪怕你是一个刚开始研究图形界面的 Python 开发者,也能轻松掌握。

作者:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

拒绝炎热和潮湿 DIY智能换气扇

夏季的上海,烈日炎炎。

白天出门就是一种折磨。

在屋里一直开着空调吧,到了昼夜交替或者深夜的时候,可能又觉得冷。

暴雨的时候,外面空气清新,室内却很闷热……

如果给你两个换气扇,怎样才能让室内空气健康流通呢?

美国有一位名叫 Ishmael Vargas 的创客,给我们带来了他的方案。

在芝加哥地区,夏季的白天和夜晚都是炎热潮湿的。太阳下山的时候外面温度下降,但家里却未必。

这就是窗式换气扇用得着的地方,它可以把冷空气吹进房子里。

但一直这么开着也不行,因为温度在不停变化。

去年夏天,Ishmael Vargas 经常要在半夜起床把换气扇关掉,但他觉得可以用一个更好的方法来控制风扇,无需人工干预,于是他便启动了这个小项目。

Ishmael Vargas 用树莓派和DHT22温湿度传感器来监测室温,然后将其与外部温度进行比较。如果后者更凉爽,则通过智能Wi-Fi电源插头(TP-Link HS100)打开换气扇 —— 这比将风扇连接到继电器要简单得多。

传感器的三根线分别接在树莓派的电源、接地、GPIO 4(建议加上10K电阻)
Smart WiFi Plug 智能插座

室外温度感知

为了简单起见,Ishmael 选择使用 pywapi 库从 Weather Channel 获取室外温度,而不再连接外部传感器。

“Weather Channel 提供的温度和实际温度可能相差一两度。这对于这个项目来说已经足够了。”他解释道。

智能WiFi插座用于打开和关闭窗户风扇

在测试中,Ishmael 发现清晨的风扇可能会把温暖的空气吹进房子里。

他说:“根据风扇的大小、房间的大小和房屋材料的不同,室内的温度可能永远不会像室外那么低。”例如,如果外面的温度是65°F(18°C),那么里面的温度可能会是67°F(19.5°C)。当室外温度开始上升时,你可能需要关掉风扇。”

远程控制

Ishmael 没有让风扇程序在启动时自动运行,而是选择通过Android智能手机手动启动并控制它。后者运行VNC查看器应用程序,允许远程访问Raspberry Pi的桌面,在桌面有一个快捷方式可以启动风扇应用程序。然后显示一个Pygame窗口,其中包含温度信息和控制按钮。

树莓派的桌面

“风扇应用程序有两个按钮,可以向上或向下改变(所需的温度)设定值。”Ishmael说。

此外,右上角的按钮是关闭应用程序并返回桌面。他的目标是在他的树莓派上运行多个项目,并为每个应用程序提供桌面快捷方式。

在手机或PC上,可以通过VNC查看温度数据和控制按钮

虽然最初的项目只使用了一个换气扇,但他后来对其进行了修改,添加了另一个风扇。因为他意识到,要想取得最好的性能,需要两个换气扇。一个吹进来,另一个吹出去。

编者注:最近在上海转悠了几个老小区,发现多户人家的通风问题需要改善。有的是楼道和通风管道设计的问题,这个就不说了。有的纯粹是自己不重视,如果能做科学的改动,应该可以让生活更舒畅。

源码地址:

https://github.com/IoToutpost/Smart-Window-Fan

素材:MagPi,编译:IoT前哨站,转载请注明出处。

王文文,前51CTO安全频道主编,阿里巴巴资深安全工程师。Redhat认证工程师,华为IoT认证工程师。

Python文本游戏之根据提示猜词

之前IoT前哨站上发布了“Python写文本冒险游戏的要点”和“在文本冒险游戏中加入道具”,讲的都是冒险类游戏。

那猜谜类型的文本游戏大家知道怎么做吗?

比如经常被用来练习的猜数字:

这确实是一个经典的入门。不过我们这次要加点难度。让大家来猜词语。

要求:

每次随机给出一部分残缺的字符,让大家回忆并输入完整的词语。

答对输出正确,答错提示错误,并告知正确答案。

思路:

1、创建一个小的词库,这里我们将一部分词语放入数组,命名为:questions。

import random

questions = [“As you like it”, “The Tempest”, “Measure for Measure”, “Much Ado About Nothing”, “The Comedy of Errors”, “King Lear”, “Cymbeline”, “Hamlet”, “Coriolanus”, “Othello”, “Love’s Labour’s Lost”, “King John”, “Julius Caesar”, “Edward III”]

2、随机选择一个短语,并将其转换为大写。

chosen_phrase = random.choice(questions)
chosen_phrase = chosen_phrase.upper()

3、去掉元音、空格和单引号。把删选后的字符拼接起来,赋值给变量puzzle。

vowels = [“A”, “E”, “I”, “O”, “U”, ” “, “‘”]
puzzle = “”
for letter in chosen_phrase:
if not letter in vowels:
puzzle += letter

4、随机插入空格

puzzle_with_spaces = “”

while len(puzzle) > 0:
group_length = random.randint(1,5)
puzzle_with_spaces += puzzle[:group_length] + ” “
puzzle = puzzle[group_length:]

5、最后加入答案检测,如果输入和答案一致,就告知“That’s correct!”,如果答案错误,提示:No,并给出正确答案。

guess = input(“What is your guess? “)
guess = guess.upper()

if guess == chosen_phrase:
print(“That’s correct!”)
else:
print(“No. The answer is “, chosen_phrase)

好了,一个根据提示信息猜短语的文本游戏就写完了。

完整代码可访问:

https://github.com/IoToutpost/Python_game/tree/master/Puzzles

在把这个游戏给别人玩的时候,记得先让玩家看一看你的词库。不然就是瞎猜了。

有能力的朋友可以试着扩展一下,说不定你可以把它改成一个英语学习程序。

注:文中猜词代码来自MagPi 82《Code a quiz game with Python》。