一、登录和注册
1. 案例介绍
本例设计一个用户登录和注册模块,使用 Tkinter 框架构建界面,主要用到画布、文本框、按钮等组件。涉及知识点:Python Tkinter 界面编程、pickle 数据存储。本例实现了基本的用户登录和注册互动界面,并提供用户信息存储和验证。
pickle 是 python 语言的一个标准模块,安装 python 后已包含 pickle 库,不需要单独再安装。pickle 模块实现了基本的数据序列化和反序列化。通过 pickle 模块的序列化操作能够将程序中运行的对象信息保存到文件中去,永久存储;通过 pickle 模块的反序列化操作,能够从文件中创建上一次程序保存的对象。
本例难度为中级,适合具有 Python 基础和 Tkinter 组件编程知识的用户学习。
2. 示例效果
3. 示例源码
import tkinter as tk
import pickle
import tkinter.messagebox
from PIL import Image, ImageTk
# 设置窗口---最开始的母体窗口
window = tk.Tk() # 建立一个窗口
window.title('欢迎登录')
window.geometry('450x300') # 窗口大小为300x200
# 画布
canvas = tk.Canvas(window, height=200, width=900)
# 加载图片
im = Image.open("images/01.png")``image_file = ImageTk.PhotoImage(im)
# image_file = tk.PhotoImage(file='images/01.gif')
image = canvas.create_image(100, 40, anchor='nw', image=image_file)
canvas.pack(side='top')
# 两个文字标签,用户名和密码两个部分
tk.Label(window, text='用户名').place(x=100, y=150)
tk.Label(window, text='密 码').place(x=100, y=190)
var_usr_name = tk.StringVar() # 讲文本框的内容,定义为字符串类型
var_usr_name.set('amoxiang@163.com') # 设置默认值
var_usr_pwd = tk.StringVar()
# 第一个输入框-用来输入用户名的。
# textvariable 获取文本框的内容
entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
entry_usr_name.place(x=160, y=150)
# 第二个输入框-用来输入密码的。
entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')
entry_usr_pwd.place(x=160, y=190)
def usr_login():
usr_name = var_usr_name.get()
usr_pwd = var_usr_pwd.get()
try:
with open('usrs_info.pickle', 'rb') as usr_file:
usrs_info = pickle.load(usr_file)
except FileNotFoundError:
with open('usrs_info.pickle', 'wb') as usr_file:
usrs_info = {'admin': 'admin'}
pickle.dump(usrs_info, usr_file)
if usr_name in usrs_info:
if usr_pwd == usrs_info[usr_name]:
tk.messagebox.showinfo(
title='欢迎光临', message=usr_name + ':请进入个人首页,查看最新资讯')
else:
tk.messagebox.showinfo(message='错误提示:密码不对,请重试')
else:
is_sign_up = tk.messagebox.askyesno('提示', '你还没有注册,请先注册')
print(is_sign_up)
if is_sign_up:
usr_sign_up()
# 注册按钮def usr_sign_up():
def sign_to_Mofan_Python():
np = new_pwd.get()
npf = new_pwd_confirm.get()
nn = new_name.get()
# 上面是获取数据,下面是查看一下是否重复注册过
with open('usrs_info.pickle', 'rb') as usr_file:
exist_usr_info = pickle.load(usr_file)
if np != npf:
tk.messagebox.showerror('错误提示', '密码和确认密码必须一样')
elif nn in exist_usr_info:
tk.messagebox.showerror('错误提示', '用户名早就注册了!')
else:
exist_usr_info[nn] = np
with open('usrs_info.pickle', 'wb') as usr_file:
pickle.dump(exist_usr_info, usr_file)
tk.messagebox.showinfo('欢迎', '你已经成功注册了')
window_sign_up.destroy()
# 点击注册之后,会弹出这个窗口界面。
window_sign_up = tk.Toplevel(window)
window_sign_up.title('欢迎注册')
window_sign_up.geometry('360x200') # 中间是x,而不是*号
# 用户名框--这里输入用户名框。
new_name = tk.StringVar()
new_name.set('amoxiang@163.com') # 设置的是默认值
tk.Label(window_sign_up, text='用户名').place(x=10, y=10)
entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
entry_new_name.place(x=100, y=10)
# 新密码框--这里输入注册时候的密码
new_pwd = tk.StringVar()
tk.Label(window_sign_up, text='密 码').place(x=10, y=50)
entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
entry_usr_pwd.place(x=100, y=50)
# 密码确认框
new_pwd_confirm = tk.StringVar()
tk.Label(window_sign_up, text='确认密码').place(x=10, y=90)
entry_usr_pwd_confirm = tk.Entry(
window_sign_up, textvariable=new_pwd_confirm, show='*')
entry_usr_pwd_confirm.place(x=100, y=90)
btn_confirm_sign_up = tk.Button(
window_sign_up, text=' 注 册 ', command=sign_to_Mofan_Python)
btn_confirm_sign_up.place(x=120, y=130)
# 创建注册和登录按钮
btn_login = tk.Button(window, text=' 登 录 ', command=usr_login)
btn_login.place(x=150, y=230) # 用place来处理按钮的位置信息。
btn_sign_up = tk.Button(window, text=' 注 册 ', command=usr_sign_up)
btn_sign_up.place(x=250, y=230)
window.mainloop()
===
二、2048游戏开发
1. 游戏简介
2048 是一款比较流行的数字游戏。游戏规则:每次可按上、下、左、右方向键滑动数字,每滑动一次,所有数字都会往滑动方向靠拢,同时在空白位置随机出现一个数字,相同数字在靠拢时会相加。不断叠加最终拼出 2048 这个数字算成功。
2048 最早于 2014年3月20日发行。原版 2048 首先在 GitHub 上发布,原作者是 Gabriele Cirulli,后被移植到各个平台。
本例难度为初级,适合具有 Python 基础和 Pygame 编程知识的用户学习。
2. 设计原理
这个游戏的本质是二维列表,就以 4*4 的二位列表来分析关键的逻辑以及实现。二维列表如下图:
所有的操作都是对这个二维列表的数据的操作。分为上下左右四个方向。先说向左的方向(如图)。
向左操作的结果如下图;当向左的方向是,所有的数据沿着水平方向向左跑。
水平说明操作的是二维列表的一行,而垂直操作的则是二位列表的一列。这样就可以将二维列表的操作变成遍历后对一维列表的操作。向左说明数据的优先考虑的位置是从左开始的。这样就确定了一维列表的遍历开始的位置。
上面第 2 个图共四行,每一个行都能得到一个列表。
list1:[0,0,2,0]``list2:[0,4,2,0]``list3:[0,0,4,4]``list4:[2,0,2,0]
这样一来向左的方向就变成。从上到下获得每一行的列表,方向向左。参数(row,left)。
其他的三个方向在开始的时候记住是怎样获得以为列表的,等操作完才放回去这样就能实现了。
3. 示例效果
4. 示例源码
import random
import sys
import pygame
from pygame.locals import *
PIXEL = 150
SCORE_PIXEL = 100
SIZE = 4
# 地图的类
class Map:
def __init__(self, size):
self.size = size
self.score = 0
self.map = [[0 for i in range(size)] for i in range(size)]
self.add()
self.add()
# 新增2或4,有1/4概率产生4
def add(self):
while True:
p = random.randint(0, self.size * self.size - 1)
if self.map[int(p / self.size)][int(p % self.size)] == 0:
x = random.randint(0, 3) > 0 and 2 or 4
self.map[int(p / self.size)][int(p % self.size)] = x
self.score += x
break
# 地图向左靠拢,其他方向的靠拢可以通过适当旋转实现,返回地图是否更新
def adjust(self):
changed = False
for a in self.map:
b = []
last = 0
for v in a:
if v != 0:
if v == last:
b.append(b.pop() << 1)
last = 0
else:
b.append(v)
last = v
b += [0] * (self.size - len(b))
for i in range(self.size):
if a[i] != b[i]:
changed = True
a[:] = b
return changed
# 逆时针旋转地图90度
def rotate90(self):
self.map = [[self.map[c][r]
for c in range(self.size)] for r in reversed(range(self.size))]
# 判断游戏结束
def over(self):
for r in range(self.size):
for c in range(self.size):
if self.map[r][c] == 0:
return False
for r in range(self.size):
for c in range(self.size - 1):
if self.map[r][c] == self.map[r][c + 1]:
return False
for r in range(self.size - 1):
for c in range(self.size):
if self.map[r][c] == self.map[r + 1][c]:
return False
return True
def moveUp(self):
self.rotate90()
if self.adjust():
self.add()
self.rotate90()
self.rotate90()
self.rotate90()
def moveRight(self):
self.rotate90()
self.rotate90()
if self.adjust():
self.add()
self.rotate90()
self.rotate90()
def moveDown(self):
self.rotate90()
self.rotate90()
self.rotate90()
if self.adjust():
self.add()
self.rotate90()
def moveLeft(self):
if self.adjust():
self.add()
# 更新屏幕
def show(map):
for i in range(SIZE):
for j in range(SIZE):
# 背景颜色块
screen.blit(map.map[i][j] == 0 and block[(i + j) % 2]
or block[2 + (i + j) % 2], (PIXEL * j, PIXEL * i))
# 数值显示
if map.map[i][j] != 0:
map_text = map_font.render(
str(map.map[i][j]), True, (106, 90, 205))
text_rect = map_text.get_rect()
text_rect.center = (PIXEL * j + PIXEL / 2,
PIXEL * i + PIXEL / 2)
screen.blit(map_text, text_rect)
# 分数显示
screen.blit(score_block, (0, PIXEL * SIZE))
score_text = score_font.render((map.over(
) and "Game over with score " or "Score: ") + str(map.score), True, (106, 90, 205))
score_rect = score_text.get_rect()
score_rect.center = (PIXEL * SIZE / 2, PIXEL * SIZE + SCORE_PIXEL / 2)
screen.blit(score_text, score_rect)
pygame.display.update()
map = Map(SIZE)
pygame.init()
screen = pygame.display.set_mode((PIXEL * SIZE, PIXEL * SIZE + SCORE_PIXEL))
pygame.display.set_caption("2048")
block = [pygame.Surface((PIXEL, PIXEL)) for i in range(4)]
# 设置颜色
block[0].fill((152, 251, 152))
block[1].fill((240, 255, 255))
block[2].fill((0, 255, 127))
block[3].fill((225, 255, 255))
score_block = pygame.Surface((PIXEL * SIZE, SCORE_PIXEL))
score_block.fill((245, 245, 245))
# 设置字体
map_font = pygame.font.Font(None, int(PIXEL * 2 / 3))
score_font = pygame.font.Font(None, int(SCORE_PIXEL * 2 / 3))
clock = pygame.time.Clock()
show(map)
while not map.over():
# 12为实验参数
clock.tick(12)
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
# 接收玩家操作
pressed_keys = pygame.key.get_pressed()
if pressed_keys[K_w] or pressed_keys[K_UP]:
map.moveUp()
elif pressed_keys[K_s] or pressed_keys[K_DOWN]:
map.moveDown()
elif pressed_keys[K_a] or pressed_keys[K_LEFT]:
map.moveLeft()
elif pressed_keys[K_d] or pressed_keys[K_RIGHT]:
map.moveRight()
show(map)
# 游戏结束
pygame.time.delay(3000)
最后这里免费分享给大家一份Python学习资料,包含视频、源码。课件,希望能帮到那些不满现状,想提升自己却又没有方向的朋友,也可以和我一起来学习交流呀。
编程资料、学习路线图、源代码、软件安装包等!【点击这里】领取!
① Python所有方向的学习路线图
,清楚各个方向要学什么东西
② 100多节Python课程视频
,涵盖必备基础、爬虫和数据分析
③ 100多个Python实战案例
,学习不再是只会理论
④ 华为出品独家Python漫画教程
,手机也能学习
⑤ 历年互联网企业Python面试真题
,复习时非常方便