废话不多说,直接上代码!
# -*- coding: utf-8 -*-
import tkinter as tk
import tkinter.messagebox
import pickle
import random
# 窗口
window = tk.Tk()
window.title('欢迎进入python')
window.geometry('450x200')
# 画布放置图片
# canvas=tk.Canvas(window,height=300,width=500)
# imagefile=tk.PhotoImage(file='qm.png')
# image=canvas.create_image(0,0,anchor='nw',image=imagefile)
# canvas.pack(side='top')
# 标签 用户名密码
Verification_Code = random.randint(1000, 9999)#设置一个随机的四位数
Verification_Code = str(Verification_Code)#把类型转换为str型
print(type(Verification_Code))
tk.Label(window, text='用户名:').place(x=100, y=30)
tk.Label(window, text='密码:').place(x=100, y=70)
tk.Label(window, text='验证码').place(x=100, y=110)
tk.Label(window, text=Verification_Code).place(x=320, y=110)
# 用户名输入框
var_usr_name = tk.StringVar()
entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
entry_usr_name.place(x=160, y=30)
# 密码输入框
var_usr_pwd = tk.StringVar()
entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')
entry_usr_pwd.place(x=160, y=70)
#验证码输入框
var_usr_yzm = tk.StringVar()
entry_usr_yzm = tk.Entry(window, textvariable=var_usr_yzm)
entry_usr_yzm.place(x=160, y=110)
# 登录函数
def usr_log_in():
# 输入框获取用户名密码
usr_name = var_usr_name.get()
usr_pwd = var_usr_pwd.get()
usr_yzm = var_usr_yzm.get()
#测试类型
print(type(usr_yzm),type(Verification_Code))
# 从本地字典获取用户信息,如果没有则新建本地数据库
try:
with open('usr_info.pickle', 'rb') as usr_file:
usrs_info = pickle.load(usr_file)
except FileNotFoundError:
with open('usr_info.pickle', 'wb') as usr_file:
usrs_info = {'admin': 'admin'}
pickle.dump(usrs_info, usr_file)
# 判断验证码是否正确用户名和密码是否匹配
if usr_yzm == Verification_Code:
if usr_name in usrs_info:
if usr_pwd == usrs_info[usr_name]:
tk.messagebox.showinfo(title='welcome',
message='欢迎您:' + usr_name)
else:
tk.messagebox.showerror(message='密码错误')
# 用户名密码不能为空
elif usr_name == '' or usr_pwd == '':
tk.messagebox.showerror(message='用户名或密码为空')
# 不在数据库中弹出是否注册的框
else:
is_signup = tk.messagebox.askyesno('欢迎', '您还没有注册,是否现在注册')
if is_signup:
usr_sign_up()
elif usr_yzm == '':
tk.messagebox.showerror(message='验证码不能为空')
else:
tk.messagebox.showerror(message='验证码有误!')
# 注册函数
def usr_sign_up():
# 确认注册时的相应函数
def signtowcg():
# 获取输入框内的内容
nn = new_name.get()
np = new_pwd.get()
npf = new_pwd_confirm.get()
# 本地加载已有用户信息,如果没有则已有用户信息为空
try:
with open('usr_info.pickle', 'rb') as usr_file:
exist_usr_info = pickle.load(usr_file)
except FileNotFoundError:
exist_usr_info = {}
# 检查用户名存在、密码为空、密码前后不一致
if nn in exist_usr_info:
tk.messagebox.showerror('错误', '用户名已存在')
elif np == '' or nn == '':
tk.messagebox.showerror('错误', '用户名或密码为空')
elif np != npf:
tk.messagebox.showerror('错误', '密码前后不一致')
# 注册信息没有问题则将用户名密码写入数据库
else:
exist_usr_info[nn] = np
with open('usr_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.geometry('350x200')
window_sign_up.title('注册')
# 用户名变量及标签、输入框
new_name = tk.StringVar()
tk.Label(window_sign_up, text='用户名:').place(x=10, y=10)
tk.Entry(window_sign_up, textvariable=new_name).place(x=150, y=10)
# 密码变量及标签、输入框
new_pwd = tk.StringVar()
tk.Label(window_sign_up, text='请输入密码:').place(x=10, y=50)
tk.Entry(window_sign_up, textvariable=new_pwd, show='*').place(x=150, y=50)
# 重复密码变量及标签、输入框
new_pwd_confirm = tk.StringVar()
tk.Label(window_sign_up, text='请再次输入密码:').place(x=10, y=90)
tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*').place(x=150, y=90)
# 确认注册按钮及位置
bt_confirm_sign_up = tk.Button(window_sign_up, text='确认注册',
command=signtowcg)
bt_confirm_sign_up.place(x=150, y=130)
# 退出的函数
def usr_sign_quit():
window.destroy()
# 登录 注册按钮
bt_login = tk.Button(window, text='登录', command=usr_log_in)
bt_login.place(x=140, y=150)
bt_logup = tk.Button(window, text='注册', command=usr_sign_up)
bt_logup.place(x=210, y=150)
bt_logquit = tk.Button(window, text='退出', command=usr_sign_quit)
bt_logquit.place(x=280, y=150)
# 主循环
window.mainloop()
import tkinter
import time
import random
from threading import Thread, Event
from tkinter import Canvas
# 游戏数值统计类
class MyScore(object):
str_score = "Score:"
str_buff = '状态:'
str_random = '总Buff:'
def __init__(self):
self.game_window = Canvas(root, width=width, height=23, bg='Snow') # 'Snow'
self.game_window.place(x=2, y=2)
self.font_format = ('宋体', 12)
self.score = -10
self.buff = 0
self.var_random = 0
self.var_buff = '稳如老狗'
self.sum = 0
# 绘制矩形框
def show_frame(self):
self.game_window.create_rectangle(2, 2, 301, 24, tag=("frame",))
self.game_window.create_rectangle(82, 2, 192, 24, tag=("frame",))
# 增加积分提示
def show_game_score(self):
self.score += 10
self.game_window.create_text(
10, 13, text=MyScore.str_score + str(self.score), font=self.font_format, anchor=tkinter.W, tag=('score',))
# 随机值显示
def show_game_random(self):
self.sum += self.buff
self.game_window.create_text(
195, 13, text=MyScore.str_random + '%.3f' % self.sum, font=self.font_format, anchor=tkinter.W,
tag=('random',))
# 增加状态显示
def show_game_buff(self):
if self.buff > 0:
self.var_buff = '幸运光环'
elif self.buff < 0:
self.var_buff = '衰神附体'
else:
self.var_buff = '稳如老狗'
self.game_window.create_text(
138, 13, text=MyScore.str_buff + self.var_buff, font=self.font_format, tag=('buff',))
# 游戏界面类
class MyCanvas(object):
msg_1 = "游戏说明"
msg_2 = "1.开始\暂停\继续:Enter\Space"
msg_3 = "2.移动方向:按wasd键"
msg_end = "GAME OVER"
msg_stop = " Press Enter\Space\nto continue the game"
def __init__(self):
self.game_window = Canvas(root, width=width, height=height, bg='Tan') # Tan
self.game_window.place(x=2, y=27)
self.font_format = ('宋体', 12)
self.flag = True
# 绘制矩形框
def show_frame(self):
self.game_window.create_rectangle(2, 2, width + 1, height + 1)
# 绘制说明文本
def game_description(self):
self.game_window.create_rectangle(20, 70, 280, 200, fill='Snow', width=1, tag=('description',))
self.game_window.create_text(150, 100, text=MyCanvas.msg_1, font=self.font_format, tag=('description',))
self.game_window.create_text(
32, 135, text=MyCanvas.msg_2, font=self.font_format, anchor=tkinter.W, tag=('description',))
self.game_window.create_text(
32, 170, text=MyCanvas.msg_3, font=self.font_format, anchor=tkinter.W, tag=('description',))
# 游戏结束,说明文字!
def show_game_over(self):
self.game_window.create_text(150, 135, text=MyCanvas.msg_end, font=('Arial', 30), tag=("game_over",))
# 游戏暂停,说明文字!
def show_game_stop(self):
self.game_window.create_text(
150, 135, text=MyCanvas.msg_stop, font=('Arial', 22), fill='white', tag=("game_stop",))
# 食物类
class Food(object):
def __init__(self):
self.food = []
self.x = None
self.y = None
self.bg = 'Bisque'
# 生产食物对象
def produce_food(self):
# 判定食物的坐标不能在蛇身体
while True:
self.x = (random.randint(0, 299) // 10) * 10
self.y = (random.randint(0, 399) // 10) * 10
for snake_x, snake_y in snake.node:
if self.x == snake_x and self.y == snake_y:
break
else:
self.food.append((self.x, self.y))
game_window.create_rectangle(self.x, self.y, self.x + 10, self.y + 10, fill=self.bg, tag=("food",))
break
# 判断食物是否为空
def is_empty(self):
if not len(self.food):
return True
# 删除食物对象 清列表
def del_food(self):
if not self.is_empty():
game_window.delete("food")
self.food.clear()
# 蛇类
class Snake(object):
def __init__(self):
# 存放节点数据
self.node = []
# 控制事件开关,也即是控制游戏开始\暂停\继续
self.e = Event()
# 定义蛇头的坐标 游戏窗口的正中间 每个蛇块占10像素的等宽高
self.head_x = ((width - 10) // 10 // 2) * 10
self.head_y = ((height - 10) // 10 // 2) * 10
# 蛇的朝向
self.direction = 'up'
# 蛇的间隔时长
self.t_snake = 0.15
# 结束游戏的标志 真为判定游戏结束
self.is_game_over = False
# 尾结点
self.end_x = None
self.end_y = None
# 删除所有对象id,node
def del_all_id_node(self):
game_window.delete('snake')
self.node.clear()
# 判断节点是否为空
def is_empty(self):
if not self.count:
return True
# 未吃到食物的情况:绘制头节node,删除尾节点node,移动id
def headnode(self):
# 删除尾部节点
self.node.pop()
# 更新头节点
self.node.insert(0, (self.head_x, self.head_y))
# 获得尾部对象 find_enclosed 判断在矩形内的对象,如果重叠是无法获得,返回的是元组类型的id对象
end_id = game_window.find_enclosed(self.end_x - 1, self.end_y - 1, self.end_x + 10 + 1, self.end_y + 10 + 1)[0]
# 画布方法 coords() 可以将id对象改变位置与大小,目前我们用到改变位置 变到头部位置
game_window.coords(end_id, self.head_x, self.head_y, self.head_x + 10, self.head_y + 10)
# 变色处理
game_window.itemconfig(end_id, fill=bg_snake)
# 增加头部对象同步至列表node,绘制新id
def add_headnode(self):
game_window.create_rectangle(
self.head_x, self.head_y, self.head_x + 10, self.head_y + 10, fill=bg_snake, tag=("snake",))
# 头部插入新节点
self.node.insert(0, (self.head_x, self.head_y))
# 判断吃到食物后[删除食物对象,并生成新食物]
def is_eat_food(self):
if self.head_x == food.x and self.head_y == food.y:
# 删除食物对象及id
food.del_food()
# 生成食物
food.produce_food()
return True
# 更新游戏相关参数显示
def update_parameters(self):
# 吃到食物
# 删除原有积分显示
my_score.game_window.delete('score')
# 更新积分显示
my_score.show_game_score()
# 删除原有游戏状态显示
my_score.buff = random.uniform(-0.1, 0.1)
my_score.game_window.delete('buff')
# 更新现有游戏状态显示
my_score.show_game_buff()
# 删除原有数值显示
my_score.game_window.delete('random')
# 更新随机值显示
my_score.show_game_random()
# 吃到食物后更新速度显示
def update_t_snake(self):
# 当buff跟原先速度相加 如果小于0 则降速至肉眼能看到的死亡
if self.t_snake + my_score.buff <= 0:
self.t_snake = 0.01
else:
self.t_snake += my_score.buff
# 游戏结束
def game_over(self):
# 显示结束文字说明
my_canvas.show_game_over()
# 要清空蛇对象id,node,清空食物对象
self.del_all_id_node()
food.del_food()
# 移动一步的封装
def one_step(self):
# 判断是否吃到自己
if self.is_eat_self():
self.is_game_over = True
# 判断吃到食物,不删除尾结点
if self.is_eat_food():
# 绘制添加头节点
self.add_headnode()
# 更新游戏相关参数显示
self.update_parameters()
# 更新游戏下次启动速度
self.update_t_snake()
else:
# 未吃到食物的情况
# 绘制头节点node,删除尾节点node,移动id,
self.headnode()
# 节点总计达到2个及以上要开始做第二位节点变色处理
if self.count >= 2:
self.change_colour()
# 节点总计达到2个及以上要开始做第个蛇身位节点变色处理
def change_colour(self):
# 获取第二个位置的对象
second_id = game_window.find_enclosed(
self.node[1][0] - 1, self.node[1][1] - 1, self.node[1][0] + 10 + 1, self.node[1][1] + 10 + 1)[0]
# 画布方法 itemconfig() 能够处理尾部id对象的颜色更替
game_window.itemconfig(second_id, fill=bg_snake_end)
# 出场蛇头增加node
def make_snake_head(self):
game_window.create_rectangle(
self.head_x, self.head_y, self.head_x + 10, self.head_y + 10, fill=bg_snake, tag=('snake',))
self.node.append((self.head_x, self.head_y))
# 获取节点个数
@property
def count(self):
return len(self.node)
# 判定是否吃到自己
def is_eat_self(self):
if self.count >= 2:
for snake_x, snake_y in self.node[1:]:
if self.head_x == snake_x and self.head_y == snake_y:
return True
# 游戏开始的时候 加载相关显示菜单
def load_show(self):
# 增加积分显示
my_score.show_game_score()
# 增加状态显示
my_score.show_game_buff()
# 随机值显示
my_score.show_game_random()
# 游戏说明显示
my_canvas.game_description()
# 描边游戏框
my_canvas.show_frame()
my_score.show_frame()
# 游戏开始入口
def start(self):
while True:
self.load_show()
self.run()
break
def run(self):
while True:
# 先等待游戏开始
self.e.wait()
# 头节点
self.head_x, self.head_y = self.node[0][0], self.node[0][1]
# 尾节点
self.end_x, self.end_y = self.node[-1][0], self.node[-1][1]
# 判断方向
if self.direction == 'up':
# 越界判定顶部
if self.head_y - 10 in range(0, height):
self.head_y -= 10
self.one_step()
else:
self.is_game_over = True
elif self.direction == 'down':
# 越界判定底部
if self.head_y + 10 in range(0, height):
self.head_y += 10
self.one_step()
else:
self.is_game_over = True
elif self.direction == 'left':
# 越界判定左边
if self.head_x - 10 in range(0, width):
self.head_x -= 10
self.one_step()
else:
self.is_game_over = True
else:
# 越界判定右边
if self.head_x + 10 in range(0, width):
self.head_x += 10
self.one_step()
else:
self.is_game_over = True
# 走完判定是否结束游戏
if self.is_game_over:
self.game_over()
break
time.sleep(self.t_snake)
# 按键触发的各类事件 判定移动方向的
def change_direction(self, event):
if event.char.upper() == 'W':
self.direction = 'up'
elif event.char.upper() == 'S':
self.direction = 'down'
elif event.char.upper() == 'A':
self.direction = 'left'
elif event.char.upper() == 'D':
self.direction = 'right'
# 开始游戏\继续\暂停 Enter\Spaca键
elif event.char.upper() == '\r' or event.char.upper() == ' ':
# 刚开始游戏 只会运行一次
if my_canvas.flag:
# 进入这里代表已经开始游戏了,所以删除显示的游戏说明
game_window.delete("description")
# 出场生成食物
food.produce_food()
# 出场蛇头绘制
self.make_snake_head()
my_canvas.flag = False
# 控制游戏开始\继续\暂停开关
if self.e.is_set():
# 显示游戏暂停信息
my_canvas.show_game_stop()
self.e.clear()
else:
# 删除游戏暂停信息
game_window.delete("game_stop")
self.e.set()
else:
pass
if __name__ == '__main__':
# 定义根(游戏)窗口的基本信息 居中显示
root = tkinter.Tk()
root.title('My Snake')
width_root, height_root = 306, 431 # 300 425
width_max, height_max = root.maxsize()
size_center = '%dx%d+%d+%d' % (
width_root, height_root, (width_max - width_root) / 2, (height_max - height_root) / 2)
root.geometry(size_center)
root.resizable(width=False, height=False)
# 画布尺寸 还有游戏的相关尺寸
width, height = 300, 400
# # 设置蛇颜色参数
bg_snake = 'Indigo'
bg_snake_end = 'MediumPurple'
# 初始化画布对象
my_canvas = MyCanvas()
# 获得画布对象
game_window = my_canvas.game_window
# 初始化数值对象
my_score = MyScore()
# 生成蛇类
snake = Snake()
# 生成食物类
food = Food()
# 绑定主窗口事件 主要是为了记录键盘的操作
root.bind('<KeyPress>', snake.change_direction)
# 开始游戏
t1 = Thread(target=snake.start)
t1.setDaemon(True)
t1.start()
# 主窗口循环
root.mainloop()