作者自我介绍:大爽歌, b站小UP主直播编程+红警三python1对1辅导老师

本教程步骤明确,过程清晰简明,最终代码量250行上下适合学习pygame的新手

项目代码已上传到我的github: https://github.com/BigShuang/simple-brick-games-by-pygame

游戏已录制成视频,投稿至本人b站:点击前往b站观看游戏视频

游戏运行效果,截图如下

〇、初始准备工作

  • 本项目使用的python3版本(如果你用python2,我不知会怎么样)
  • Ide推荐大家选择pycharm(不同ide应该没影响)
  • 需要安装第三方库pygame,安装方法(windows电脑,mac系统本人实测与pygame不兼容,强行运行本项目卡成ppt)

电脑打开cmd命令窗口,输入pip install pygame

如果电脑上安的是pip3则是pip3 install pygame

补充说明:

由于众所周知的原因,安装过程中下载可能十分缓慢,甚至由此导致安装失败

此时建议大家尝试使用镜像下载

---国内源---

清华:https://pypi.tuna.tsinghua.edu.cn/simple

阿里云:http://mirrors.aliyun.com/pypi/simple/

中国科技大学: https://pypi.mirrors.ustc.edu.cn/simple/

华中理工大学:http://pypi.hustunique.com/

山东理工大学:http://pypi.sdutlinux.org/

豆瓣:http://pypi.douban.com/simple/

使用办法 pip install xxxx -i jinxiangurl

具体到pygame,则是:

pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple

一、实现基础窗口

0 - 新建car_racing.py文件,内容如下

import pygame

WIN_WIDTH = 600  # 窗口宽度
WIN_HEIGHT = 900 # 窗口高度 pygame.init() # pygame初始化,必须有,且必须在开头
# 创建主窗体
win=pygame.display.set_mode((WIN_WIDTH,WIN_HEIGHT))

此时运行car_racing.py,会发现一个一闪而逝的窗口,

1 - 进一步,我们自然而然的就要思考这些问题

  • 游戏窗口大小设置为多少合适?

    由于是方块游戏,所以可以根据方格尺寸、行格字数、列格子数去计算出窗口的宽高
  • 怎么维持住这个窗口?

    通过while循环去实现
  • 但是简单的循环只是单纯的将界面卡住,怎么实现刷新?

    在循环体内使用pygame.display.update()语句进行界面的更新
  • 循环的刷新频率不做节制的话,界面会飞速刷新导致卡死,怎么办?

    pygame有专门的对象pygame.time.Clock用于去控制循环刷新的频率,创建pygame.time.Clock对象后,调用该对象的tick()方法,函数参数为每秒刷新次数,就可以设置循环每秒刷新频率,术语叫做帧率

可前往官方文档观看pygame.time.Clock的更多细节,https://www.pygame.org/docs/ref/time.html#pygame.time.Clock

  • 根据上面的思路,修改car_racing.py后如下
import pygame

C, R = 11, 20  # 11列, 20行
CELL_SIZE = 40 # 格子尺寸 FPS=60 # 游戏帧率
WIN_WIDTH = CELL_SIZE * C # 窗口宽度
WIN_HEIGHT = CELL_SIZE * R # 窗口高度 pygame.init() # pygame初始化,必须有,且必须在开头
# 创建主窗体
clock = pygame.time.Clock() # 用于控制循环刷新频率的对象
win = pygame.display.set_mode((WIN_WIDTH,WIN_HEIGHT)) while True:
clock.tick(FPS) # 控制循环刷新频率,每秒刷新FPS对应的值的次数
pygame.display.update()

此时运行car_racing.py, 就可以得到一个最最最基础的窗口了,

2 - 但是,这个窗口有个大问题, 此时窗口的关闭按钮很容易出bug(卡死)

所以需要自己去重新实现这个窗口关闭功能,需要在循环体内添加如下代码

# 获取所有事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 判断当前事件是否为点击右上角退出键
pygame.quit()
sys.exit() # 需要提前 import sys

同时我们一般会希望能够设置下背景的颜色

比如,这个游戏的背景色是轻灰色(200, 200, 200)

那么设置背景的代码为

bg_color = (200, 200, 200)
win.fill(bg_color)

不过需要注意的是,这段代码放在不同的位置会产生不同的效果。

放在while循环之前,代表只绘制一次背景,会被后面绘制的东西遮住。

放在while循环中,则是每一帧都会绘制一次背景,一般用于去覆盖掉那些希望删掉的元素。

3 - 给窗口设置标题

win = pygame.display.set_mode((WINWIDTH,WINHEIGHT))后面,

添加代码如下,设置窗口标题(Big Shuang是我的英文名,可以删掉或者修改为你的名字)

pygame.display.set_caption('Car Racing by Big Shuang')

本阶段最后car_racing.py如下

import pygame
import sys FPS=60 # 游戏帧率
WINWIDTH = 600 # 窗口宽度
WINHEIGHT = 900 # 窗口高度 pygame.init() # pygame初始化,必须有,且必须在开头
# 创建主窗体
clock = pygame.time.Clock() # 用于控制循环刷新频率的对象
win = pygame.display.set_mode((WINWIDTH,WINHEIGHT))
pygame.display.set_caption('Car Racing by Big Shuang') bg_color = (200, 200, 200)
win.fill(bg_color) while True:
# 获取所有事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 判断当前事件是否为点击右上角退出键
pygame.quit()
sys.exit() clock.tick(FPS) # 控制循环刷新频率,每秒刷新FPS对应的值的次数
pygame.display.update()

到这里,基础窗口就完成了~

二、实现基础方块绘制

1 - 最基础的绘制方法

pygame里面,绘制一个小方格实际上是很简单的。

新建一个方格色块(放在while循环之前)

area = pygame.Surface((CELL_SIZE, CELL_SIZE))
enemy_color = (50, 50, 50)
area.fill(enemy_color)

再将方格色块放在窗口对象上(放在while循环中,clock.tick(FPS)之前)

win.blit(area, (CELL_SIZE, 0))

此时运行,效果如图

不过这个绘制方法的问题在于, 后面的移动操作管理起来颇为不便。

要在while循环中编写各种代码来实现area这个色块的位置变换的话,代码写起来麻烦,管理起来也乱。

pygame 给我们提供了一个Sprite类,用于实现可以移动的二维图像对象。

我们将继承这个类,并封装一些需要的方法,方便移动以及管理。

2 - 使用pygame的Sprite类

In computer graphics, a sprite is a two-dimensional bitmap that is integrated into a larger scene, most often in a 2D video game.

在计算机图形学中,精灵是一种二维位图,它被集成到一个更大的场景中,通常在二维视频游戏中。

个人理解,sprite是一个计算机术语,代表界面中可以移动的二维位图。

继承Sprite, 新建Block类如下(在新建win对象,应该是14行,后面添加如下代码)

class Block(pygame.sprite.Sprite):
def __init__(self, c, r, color):
super().__init__() self.cr = [c, r]
self.x = c * CELL_SIZE
self.y = r * CELL_SIZE self.image = pygame.Surface((CELL_SIZE, CELL_SIZE))
self.image.fill(color) self.rect = self.image.get_rect()
self.rect.move_ip(self.x, self.y)

删掉前面 1 最基础的绘制方法中, area的相关代码

在while循环之前, 添加如下代码

enemy_color = (50, 50, 50)
block = Block(1, 1, enemy_color)
win.blit(block.image, block.rect)

此时运行效果和1中相同。

三、 基础方块移动

1 - 给Block添加移动方法

首先,给Block 类添加移动到指定行列的类方法如下

    def move_cr(self, c, r):
self.cr[0] = c
self.cr[1] = r
self.x = c * CELL_SIZE
self.y = r * CELL_SIZE
self.rect.left = self.x
self.rect.top = self.y

但是这个方法还是不够的的,

因为游戏中的移动,一般都是操作上下左右来移动。

那么,我们需要把上下左右,转换成c、r的变换。

所以建立字典如下

DIRECTIONS = {
"UP": (0, -1), # (dc, dr)
"DOWN": (0, 1),
"LEFT": (-1, 0),
"RIGHT": (1, 0),
}

然后再给Block 类添加按方向移动的方法如下

    def move(self, direction):
dc, dr = DIRECTIONS[direction]
next_c, next_r = self.cr[0] + dc, self.cr[1] + dr
self.move_cr(next_c, next_r)

2 - 响应键盘按键移动

1 中只是添加了移动的方法,但是玩家要通过键盘来移动的话,

还需要程序中有能够响应处理键盘操作

所以在while循环中的for event in pygame.event.get()循环里,添加代码如下

if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
block.move("LEFT")
if event.key == pygame.K_RIGHT or event.key == ord('d'):
block.move("RIGHT")
if event.key == pygame.K_UP or event.key == ord('w'):
block.move("UP")
if event.key == pygame.K_DOWN or event.key == ord('s'):
block.move("DOWN")

同时移动后,需要再进行绘制才能看到在上面的for循环后面(外面)添加

win.blit(block.image, block.rect)

但是这个时候会有一个问题,移动后原来的位置色块还在,没有消失掉(被清掉)。

多移动几下后,结果就像下图一样

3 - 清除之前的绘制

所以我们需要擦除之前绘制的色块。

pygame里面,一般采用重新绘制整个界面的方式擦除之前的绘制。

重新绘制界面后,再在界面上添加新的需要绘制的东西。

即在while循环中,win.blit(block.image, block.rect)之前添加代码:

win.fill(bg_color)

此时, while 循环之前的这两句代码删不删除没啥区别

win.fill(bg_color)
win.blit(block.image, block.rect)

(个人视为多余的,所以删除)

此时移动小方块就不会有之前的色块残留了

不过此时还有一个小小的问题,就是小方块可以移动到界面边界外

虽然可以再移动回来,但是这不符合我们这个程序的规则。

所以需要再进行边界处理,使其无法移到边界外。

4 - 边界处理

Block 类添加检查能否移动的方法如下

    def check_move(self, direction=""):
move_c, move_r = DIRECTIONS[direction]
next_c, next_r = self.cr[0] + move_c, self.cr[1] + move_r if 0 <= next_c < C and 0 <= next_r < R:
return True return False

再在while循环中的for循环中的每次调用move方法前,使用check_move检查是否 能移动。

修改后的while循环如下

while True:
# 获取所有事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 判断当前事件是否为点击右上角退出键
pygame.quit() # 关闭窗口
sys.exit() # 停止程序 if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
if block.check_move("LEFT"):
block.move("LEFT")
if event.key == pygame.K_RIGHT or event.key == ord('d'):
if block.check_move("RIGHT"):
block.move("RIGHT")
if event.key == pygame.K_UP or event.key == ord('w'):
if block.check_move("UP"):
block.move("UP")
if event.key == pygame.K_DOWN or event.key == ord('s'):
if block.check_move("DOWN"):
block.move("DOWN") win.fill(bg_color)
win.blit(block.image, block.rect) clock.tick(FPS) # 控制循环刷新频率,每秒刷新FPS对应的值的次数
pygame.display.update()

当然这么写不够优雅,if block.check_move("RIGHT"):重复了四次,

有的朋友可能会觉得把check_move的调用放在move方法里面开头更好。

这里之所以不这么做,是因为后面会在方块组成的赛车类里,进行这个check_move的工作。

具体见下文。

四 多个方块组成方块赛车

1 - 使用方块组绘制赛车

无论是玩家的车,还是敌人的车,

都是由多个方块组成的。

所以首先要定义下,玩家车和敌人车的方格组成,代码如下

CARS = {  # 车的形状,即格子位置
"player": [
[0, 1, 0],
[1, 1, 1],
[1, 0, 1],
],
"enemy": [
[1, 0, 1],
[1, 1, 1],
[0, 1, 0],
]
}

根据这个方格祖,绘制赛车方法如下:

(放在while循环中,重置背景之后)

car_c, car_r = 2, 2
for ri, row in enumerate(CARS["enemy"]):
for ci, cell in enumerate(row):
if cell == 1:
i_block = Block(car_c + ci, car_r + ri, enemy_color)
win.blit(i_block.image, i_block.rect)

2 - 使用Group管理方块

接下来要建立一个赛车类,用来管理这些方块。

pygame为我们提供了一个管理多个Sprite的工具pygame.sprite.Group

这个Group类可以使用draw方法,将内部的Sprite一起绘制在屏幕窗口上。

这里赛车类就继承这个Group类,如下。

class Car(pygame.sprite.Group):
def __init__(self, c, r, car_kind, car_color):
super().__init__() for ri, row in enumerate(CARS[car_kind]):
for ci, cell in enumerate(row):
if cell == 1:
block = Block(c+ci, r+ri, car_color)
self.add(block)

同时,给这个赛车类添加移动方法,用于统一移动内部的方块

    def move(self, direction=""):
if all(block.check_move(direction) for block in self.sprites()):
for block in self.sprites():
block.move(direction)

然后删掉其他的建立方块与绘制方块的代码

此时while循环上下代码如下


bg_color = (200, 200, 200)
enemy_color = (50, 50, 50)
player_color = (65, 105, 225) # RoyalBlue bottom_center_c = (C - len(CARS["player"][0])) // 2
bottom_center_r = R - len(CARS["player"])
car = Car(bottom_center_c, bottom_center_r, "player", player_color) while True:
# 获取所有事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 判断当前事件是否为点击右上角退出键
pygame.quit() # 关闭窗口
sys.exit() # 停止程序 if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
car.move("LEFT")
if event.key == pygame.K_RIGHT or event.key == ord('d'):
car.move("RIGHT")
if event.key == pygame.K_UP or event.key == ord('w'):
car.move("UP")
if event.key == pygame.K_DOWN or event.key == ord('s'):
car.move("DOWN") win.fill(bg_color) car.draw(win) clock.tick(FPS) # 控制循环刷新频率,每秒刷新FPS对应的值的次数
pygame.display.update()

此时效果如图,小车可以左右移动

五 刷新敌人赛车

敌人的赛车绘制,同上面第四部分。

不过敌人的赛车

  1. 需要隔一段时间就能自动生成一个
  2. 不能由玩家的键盘操作移动,而是自动地向下移动。
  3. 向下移动出边界后需要清理掉

1 - 为Car添加新的方法

这里有几个问题需要先解决,

  • 敌人的赛车是可以从上边界移动出来, 可以向下移动出下边界的。

    所以需要修改下原有的赛车内

    Car添加无边界限制的移动方法free_move如下
    def free_move(self, direction=""):
for block in self.sprites():
block.move(direction)

再修改原有的move方法如下

    def move(self, direction=""):
if all(block.check_move(direction) for block in self.sprites()):
self.free_move(direction)
  • 敌人赛车完全移动出边界后要清理掉

    所以要给赛车类添加一个方法判断是否完全出了边界

    先给组成赛车的方格Block添加方法is_out如下
    def is_out(self):
if 0 <= self.cr[0] < C and 0 <= self.cr[1] < R:
return False
return True

再为Car添加方法is_out如下

    def is_out(self):
return all(block.is_out() for block in self.sprites())

2 - 添加敌人赛车管理类

我们需要一个管理敌人赛车的类EnemyManager

其代码如下

import random  # 在代码文件开头部分添加

# 在 enemy_color 声明之后的位置添加
class EnemyManager():
def __init__(self):
self.enemies = [] self.move_count = 0 def gen_new_enemies(self): # 生成敌人赛车
# 设置敌人赛车的生成间隔, 隔两倍的敌人赛车行数+1
if self.move_count % (2 * len(CARS["enemy"]) + 1) == 1: ec = random.randint(1, C - len(CARS["enemy"][0]))
enemy = Car(ec, 0, "enemy", enemy_color) self.enemies.append(enemy) def move(self): # 自动向下移动敌人赛车
# 超出边界后,自动清理掉
to_delete = []
for i, enemy in enumerate(self.enemies):
enemy.free_move("DOWN")
if enemy.is_out():
to_delete.append(i) for di in to_delete[::-1]: # 倒着按序号来删除
self.enemies.pop(di) self.move_count += 1 self.gen_new_enemies() def draw(self, master):
# 绘制敌人赛车
for enemy in self.enemies:
enemy.draw(master)

3 - 绘制敌人赛车

在while循环之前实例化EnemyManager,代码如下

emg = EnemyManager()

while中对敌车进行绘制,即在win.fill(bg_color)之后添加代码如下

emg.move()
emg.draw(win)

但是此时敌人赛车运动的太快了,是每帧一次移动。

所以需要设置一下,让敌人的赛车每过MOVE_SPACE帧才进行一次移动

在开头添加代码如下

MOVE_SPACE = 5

再在while循环之前添加帧计数器

frame_count = 0

while循环中的开头添加

frame_count += 1

再修改刚才的敌人赛车绘制代码如下

if frame_count % MOVE_SPACE == 0:
emg.move() emg.draw(win)

此时运行效果如图

六 碰撞检测

1 - 添加检测方法

要实现碰撞检测,只需给敌人赛车管理类EnemyManager添加方法

遍历其中现有的敌人赛车,检查是否与玩家赛车相撞即可。

赛车相撞的判断方法为两车的方块有重叠,即有相同位置的方块。

所以给类Car添加check_collide方法,代码如下

    def check_collide(self, other_car):
for block in self.sprites():
bcr1 = tuple(block.cr)
for other_block in other_car.sprites():
bcr2 = tuple(other_block.cr)
if bcr1 == bcr2:
return True return False

再给敌人赛车管理类EnemyManager添加check_collide方法,代码如下

    def check_collide(self, player):
for enemy in self.enemies:
if enemy.check_collide(player):
return True return False

2 - 碰撞后结束游戏

while循环中,绘制完赛车后添加碰撞检测

即在clock.tick(FPS)之前添加代码如下

    if emg.check_collide(car):
break

此时玩家赛车碰到敌人赛车,游戏就会结束。

不过,此时游戏结束后会直接关闭窗口。

玩家体验并不好,所以需要进一步的优化下。

最好是游戏结束后,窗口不关闭,展示Game Over的提示,并告诉玩家得分。

七 综合优化

1 游戏流程优化

游戏流程上,运行代码后,敌人赛车就直接迎面而来,留给玩家的缓冲准备时间太短了。

所以这里修改为代码运行后,游戏处于等待状态,玩家按键盘任意键开始游戏。

同时游戏结束后,玩家可按键盘任意键重新开始。

首先需要在while循环前,添加一个游戏运行状态变量,默认游戏未开始

running = False

再修改while循环如下

while True:
frame_count += 1 # 获取所有事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 判断当前事件是否为点击右上角退出键
pygame.quit() # 关闭窗口
sys.exit() # 停止程序 if event.type == pygame.KEYDOWN:
if running: # 游戏开始时,响应上下左右按键
if event.key == pygame.K_LEFT or event.key == ord('a'):
car.move("LEFT")
if event.key == pygame.K_RIGHT or event.key == ord('d'):
car.move("RIGHT")
if event.key == pygame.K_UP or event.key == ord('w'):
car.move("UP")
if event.key == pygame.K_DOWN or event.key == ord('s'):
car.move("DOWN")
else: # 游戏结束后,响应任意按键,开始游戏
# reset game, 重置变量和游戏状态
car = Car(bottom_center_c, bottom_center_r, "player", player_color)
frame_count = 0
emg = EnemyManager()
running =True if running:
win.fill(bg_color) if frame_count % MOVE_SPACE == 0:
emg.move() emg.draw(win) car.draw(win) if emg.check_collide(car):
running = False # 撞车后,游戏状态改变为结束 clock.tick(FPS) # 控制循环刷新频率,每秒刷新FPS对应的值的次数
pygame.display.update()

此时游戏流程就修改好了,但是没有文本提示,玩家会不明就里,感到迷惑,所以需要文字在开始时和结束时进行提示。

2 文本提示与得分展示

在游戏开头添加大中小三种字体(必须要在pygame.init()之后,能后不能前)

# 大中小三种字体,48,36,24
FONTS = [
pygame.font.Font(pygame.font.get_default_font(), font_size) for font_size in [48, 36, 24]
]

代码运行后,游戏尚未开始,需要文本提示玩家按任意键开始游戏

即在while循环之前添加代码如下

score_color = (0,128,0)
start_info = FONTS[2].render("Press any key to start game", True, score_color)
text_rect = start_info.get_rect(center=(WIN_WIDTH / 2, WIN_HEIGHT / 2))
win.blit(start_info, text_rect)

游戏过程中,展示玩家得分(玩家坚持时间)

while循环中,car.draw(win)之后添加代码如下

text_info = FONTS[2].render("Scores: %d" % (frame_count / FPS), True, score_color)
win.blit(text_info, dest=(0, 0))

玩家撞车后,一轮游戏结束,需要展示Game Over,玩家得分,与按任意键结束游戏

修改while循环中,原有的代码

        if emg.check_collide(car):
running = False # 撞车后,游戏状态改变为结束

        if emg.check_collide(car):
running = False # 撞车后,游戏状态改变为结束 over_color = (255,0,0)
texts = ["Game Over", "Scores: %d" % (frame_count / FPS), "Press Any Key to Restart game"]
for ti, text in enumerate(texts):
over_info = FONTS[ti].render(text, True, over_color)
text_rect = over_info.get_rect(center=(WIN_WIDTH / 2, WIN_HEIGHT / 2 + 48 * ti))
win.blit(over_info, text_rect)

3 代码优化

我们注意到,关于颜色这个常量,都是直接写在用的地方。

后面多了后,容易找起来不方便,所以建议把所有的颜色声明都统一移到开头位置。

这里放在CELL_SIZE = 40之后,移动后颜色设置代码如下

bg_color = (200, 200, 200)
enemy_color = (50, 50, 50)
player_color = (65, 105, 225) # RoyalBlue
score_color = (0,128,0) # SpringGreen
over_color = (255, 0, 0)

4 后续

  • 其实,由于颜色值比较多,我更喜欢把颜色统一放在一个字典里面,根据键来取值,本文github项目下的car_racing.py就是这样写的
  • 游戏中赛车移动,是按一下移动一个,可能有的人跟喜欢能够连续移动,这个已在项目下的1 car racing文件夹下的car_racing_plus1.py中实现。

pygame 入门实例教程 1 - 复古方块赛车游戏的更多相关文章

  1. React 入门实例教程(转载)

    本人转载自: React 入门实例教程

  2. Omnet++ 4.0 入门实例教程

    http://blog.sina.com.cn/s/blog_8a2bb17d01018npf.html 在网上找到的一个讲解omnet++的实例, 是4.0下面实现的. 我在4.2上试了试,可以用. ...

  3. let import export React入门实例教程 connect provider combineReducers 箭头函数 30分钟掌握ES6/ES2015核心内容 Rest babel

    let与var的区别 http://www.cnblogs.com/snandy/archive/2015/05/10/4485832.html es6 导入导出 http://www.csdn.ne ...

  4. WebService入门实例教程

    什么是WebService 通过使用WebService,您的应用程序可以向全世界发布信息,或提供某项功能,它是基于Web的服务,通过Web进行发布.查找和使用. WebService脚本平台需支持X ...

  5. React 入门实例教程

    现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Face ...

  6. Facebook React.js库 入门实例教程

    作者: 阮一峰 日期: 2015年3月31日 现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩 ...

  7. 2015年最热门前端框架React 入门实例教程

    现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Face ...

  8. React入门实例教程

    文章转自:阮一峰 现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React ...

  9. React 入门实例教程(转载)

    现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Face ...

  10. 【转】react入门实例教程

    作者: 阮一峰 日期: 2015年3月31日 写在前面:原文链接http://www.ruanyifeng.com/blog/2015/03/react.html    github地址https:/ ...

随机推荐

  1. 2014年蓝桥杯C/C++大学B组省赛真题(地宫寻宝)

    题目描述: X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. ...

  2. 在树莓派上使用numpy实现简单的神经网络推理,pytorch在服务器或PC上训练好模型保存成numpy格式的数据,推理在树莓派上加载模型

    这几天又在玩树莓派,先是搞了个物联网,又在尝试在树莓派上搞一些简单的神经网络,这次搞得是mlp识别mnist手写数字识别 训练代码在电脑上,cpu就能训练,很快的: 1 import torch 2 ...

  3. web_枚举

    网页枚举 使用工具 gobuster,Nikto,WPScan Gobuster 安装:sudo apt install gobuster 有用的全局标志 -t 线程 并发线程数(默认10) -v 冗 ...

  4. 【HMS Core】华为帐号服务,获取Access Token报错{sub_error:20152,error_description:invalid code,error:1101}

    ​ [问题描述] 华为账号服务,接口获取Access Token报错:{sub_error:20152,error_description:invalid code,error:1101} [问题分析 ...

  5. IDEA中去除竖线

    IDEA中去除竖线 使用IDEA时突然多出了一条竖线 , 进入设置取消竖线

  6. C++面试八股文:知道std::unordered_set/std::unordered_map吗?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第27面: 面试官:知道std::unordered_set/std::unordered_map吗? 二师兄:知道.两者都是C++11引入的新容器, ...

  7. 2023-07-03:讲一讲Redis缓存的数据一致性问题和处理方案。

    2023-07-03:讲一讲Redis缓存的数据一致性问题和处理方案. 答案2023-07-03: 数据一致性 当使用缓存时,无论是在本地内存中缓存还是使用 Redis 等外部缓存系统,会引入数据同步 ...

  8. 深入解析Redis的LRU与LFU算法实现

    作者:vivo 互联网服务器团队 - Luo Jianxin 重点介绍了Redis的LRU与LFU算法实现,并分析总结了两种算法的实现效果以及存在的问题. 一.前言 Redis是一款基于内存的高性能N ...

  9. 一体化元数据管理平台——OpenMetadata入门宝典

    大家好,我是独孤风,一位曾经的港口煤炭工人,目前在某国企任大数据负责人,公众号大数据流动主理人.在最近的两年的时间里,因为公司的需求,还有大数据的发展趋势所在,我开始学习数据治理的相关知识.今天给大家 ...

  10. Doris写入数据异常提示actual column number in csv file is less than schema column number

    版本信息: Flink 1.17.1 Doris 1.2.3 Flink Doris Connector 1.4.0 写入方式 采用 String 数据流,依照社区网站的样例代码,在sink之前将数据 ...