一个简单的计算器
# *_* coding:utf8 *_*
import tkinter
from functools import partial
# 按钮输入调用
def get_input(entry, argu):
# 从entry窗口展示中获取输入的内容
input_data = entry.get()
# 合法运算符 : + - * / -- ** // +-
# ------------ 输入合法性判断的优化 ------------
# 最后一个字符不是纯数字(已经有算数符号),原窗口值不为空,且输入值为运算符
# if not input_data[-1:].isdecimal() and (not argu.isdecimal()):
# if input_data[-2:] in ["--", "**", "//", "+-"]:
# return
# if (input_data[-1:] + argu) not in ["--", "**", "//", "+-"]:
# return
# ------------------------------------------------
# 出现连续+,则第二个+为无效输入,不做任何处理
if (input_data[-1:] == '+') and (argu == '+'):
return
# 出现连续+--,则第三个-为无效输入,不做任何处理
if (input_data[-2:] == '+-') and (argu == '-'):
return
# 窗口已经有--后面字符不能为+或-
if (input_data[-2:] == '--') and (argu in ['-', '+']):
return
# 窗口已经有 ** 后面字符不能为 * 或 /
if (input_data[-2:] == '**') and (argu in ['*', '/']):
return
# 输入合法将字符插入到entry窗口结尾
entry.insert("end", argu)
# 退格(撤销输入)
def backspace(entry):
input_len = len(entry.get())
# 删除entry窗口中最后的字符
entry.delete(input_len - 1)
# 清空entry内容(清空窗口)
def clear(entry):
entry.delete(0, "end")
def calc(entry):
input_data = entry.get()
# 计算前判断输入内容是否为空;首字符不能为*/;*/不能连续出现3次;
if not input_data:
return
clear(entry)
# 异常捕获,在进行数据运算时如果出现异常进行相应处理
# noinspection PyBroadException
try:
# eval() 函数用来执行一个字符串表达式,并返回表达式的值;并将执行结果转换为字符串
output_data = str(eval(input_data))
except Exception:
# 将提示信息输出到窗口
entry.insert("end", "Calculation error")
else:
# 将计算结果显示在窗口中
if len(output_data) > 20:
entry.insert("end", "Value overflow")
else:
entry.insert("end", output_data)
if __name__ == '__main__':
root = tkinter.Tk()
root.title("Calculator")
# 框体大小可调性,分别表示x,y方向的可变性;
root.resizable(0, 0)
button_bg = 'orange'
math_sign_bg = 'DarkTurquoise'
cal_output_bg = 'YellowGreen'
button_active_bg = 'gray'
# justify:显示多行文本的时候, 设置不同行之间的对齐方式,可选项包括LEFT, RIGHT, CENTER
# 文本从窗口左方开始显示,默认可以显示20个字符
# row:entry组件在网格中的横向位置
# column:entry组件在网格中的纵向位置
# columnspan:正常情况下,一个插件只占一个单元;可通过columnspan来合并一行中的多个相邻单元
entry = tkinter.Entry(root, justify="right", font=1)
entry.grid(row=0, column=0, columnspan=4, padx=10, pady=10)
def place_button(text, func, func_params, bg=button_bg, **place_params):
# 偏函数partial,可以理解为定义了一个模板,后续的按钮在模板基础上进行修改或添加特性
# activebackground:按钮按下后显示颜place_params色
my_button = partial(tkinter.Button, root, bg=button_bg, padx=10, pady=3, activebackground=button_active_bg)
button = my_button(text=text, bg=bg, command=lambda: func(*func_params))
button.grid(**place_params)
# 文本输入类按钮
place_button('7', get_input, (entry, '7'), row=1, column=0, ipadx=5, pady=5)
place_button('8', get_input, (entry, '8'), row=1, column=1, ipadx=5, pady=5)
place_button('9', get_input, (entry, '9'), row=1, column=2, ipadx=5, pady=5)
place_button('4', get_input, (entry, '4'), row=2, column=0, ipadx=5, pady=5)
place_button('5', get_input, (entry, '5'), row=2, column=1, ipadx=5, pady=5)
place_button('6', get_input, (entry, '6'), row=2, column=2, ipadx=5, pady=5)
place_button('1', get_input, (entry, '1'), row=3, column=0, ipadx=5, pady=5)
place_button('2', get_input, (entry, '2'), row=3, column=1, ipadx=5, pady=5)
place_button('3', get_input, (entry, '3'), row=3, column=2, ipadx=5, pady=5)
place_button('0', get_input, (entry, '0'), row=4, column=0, padx=8, pady=5,
columnspan=2, sticky=tkinter.E + tkinter.W + tkinter.N + tkinter.S)
place_button('.', get_input, (entry, '.'), row=4, column=2, ipadx=7, padx=5, pady=5)
# 运算输入类按钮(只是背景色不同)
# 字符大小('+','-'宽度不一样,使用ipadx进行修正)
place_button('+', get_input, (entry, '+'), bg=math_sign_bg, row=1, column=3, ipadx=5, pady=5)
place_button('-', get_input, (entry, '-'), bg=math_sign_bg, row=2, column=3, ipadx=5, pady=5)
place_button('*', get_input, (entry, '*'), bg=math_sign_bg, row=3, column=3, ipadx=5, pady=5)
place_button('/', get_input, (entry, '/'), bg=math_sign_bg, row=4, column=3, ipadx=5, pady=5)
# 功能输入类按钮(背景色、触发功能不同)
place_button('<-', backspace, (entry,), row=5, column=0, ipadx=5, padx=5, pady=5)
place_button('C', clear, (entry,), row=5, column=1, pady=5, ipadx=5)
place_button('=', calc, (entry,), bg=cal_output_bg, row=5, column=2, ipadx=5, padx=5, pady=5,
columnspan=2, sticky=tkinter.E + tkinter.W + tkinter.N + tkinter.S)
root.mainloop()
贪食蛇
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Wangdali time:2021年1月20日16:08:44
#python实现:贪吃蛇
'''
游戏玩法:回车开始游戏;空格暂停游戏/继续游戏;方向键/wsad控制小蛇走向
'''
'''
思路:用列表存储蛇的身体;用浅色表示身体,深色背景将身体凸显出来;
蛇的移动:仔细观察,是:身体除头和尾不动、尾部消失,头部增加,所以,新添加的元素放在列表头部、删除尾部元素;
游戏结束判定策略:超出边界;触碰到自己的身体:蛇前进的下一格子为身体的一部分(即在列表中)。
'''
#注:因为在列表中需要频繁添加和删除元素,所以用deque容器代替列表;是因为deque具有高效的插入和删除效率
#初始化蛇,长度为3,放置在屏幕左上角;
#导包
import random
import sys
import time
import pygame
from pygame.locals import *
from collections import deque
#基础设置
Screen_Height=480
Screen_Width=600
Size=20#小方格大小
Line_Width=1
#游戏区域的坐标范围
Area_x=(0,Screen_Width//Size-1) #0是左边界,1是右边界 #注:python中//为整数除法;/为浮点数除法
Area_y=(2,Screen_Height//Size-1)
#食物的初步设置
#食物的分值+颜色
Food_Style_List=[(10,(255,100,100)),(20,(100,255,100)),(30,(100,100,255))]
#整体颜色设置
Light=(100,100,100)
Dark=(200,200,200)
Black=(0,0,0)
Red=(200,30,30)
Back_Ground=(40,40,60)
#文本输出格式设置
def Print_Txt(screen,font,x,y,text,fcolor=(255,255,255)):
#font.render参数意义:.render(内容,是否抗锯齿,字体颜色,字体背景颜色)
Text=font.render(text,True,fcolor)
screen.blit(Text,(x,y))
#初始化蛇
def init_snake():
snake=deque()
snake.append((2,Area_y[0]))
snake.append((1,Area_y[0]))
snake.append((0,Area_y[0]))
return snake
#食物设置
#注意需要对食物出现在蛇身上的情况进行判断
def Creat_Food(snake):
'''
注:randint 产生的随机数区间是包含左右极限的,
也就是说左右都是闭区间的[1, n],能取到1和n。
而 randrange 产生的随机数区间只包含左极限,
也就是左闭右开的[1, n),1能取到,而n取不到。randint
产生的随机数是在指定的某个区间内的一个值,
而 randrange 产生的随机数可以设定一个步长,也就是一个间隔。
'''
food_x=random.randint(Area_x[0],Area_x[1]) #此处有疑问
food_y=random.randint(Area_y[0],Area_y[1])
#如果食物出现在蛇上,重来;
while(food_x,food_y)in snake:
food_x = random.randint(Area_x[0], Area_x[1])
food_y = random.randint(Area_y[[0], Area_y[1]])
return food_x,food_y
#食物风格
def Food_Style():
return Food_Style_List[random.randint(0,2)] #返回随机的分值和颜色
def main():
pygame.init()
screen=pygame.display.set_mode((Screen_Width,Screen_Height)) #初始化一个准备显示的窗口或屏幕
pygame.display.set_caption('贪吃蛇') #Set the current window caption
#得分字体设置
font1=pygame.font.SysFont('SimHei',24)
#GO字体设置
font2 = pygame.font.SysFont(None, 72)
fwidth, fheight = font2.size('GAME OVER') ###
#程序bug修复:如果蛇在向右移动,快速点击分别施加向下、向左的命令,向下的命令会被覆盖,只有向左的命令被接受,直接GameOver
# b变量为了防止这个情况发生
b=True
#蛇
snake=init_snake()
#食物
food=Creat_Food(snake)
food_style=Food_Style()
#方向控制
pos=(1,0) ###
#启动游戏相关变量初始化
game_over=True #结束标志 # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER
game_start=False #开始标志
score=0 #得分
orispeed=0.3 #蛇初始速度
speed=orispeed #蛇速度
last_move_time=None
pause=False #暂停
while True:
for event in pygame.event.get():
if event.type==QUIT:
sys.exit()
elif event.type==KEYDOWN:
if event.key==K_RETURN:
if game_over:
game_start=True
game_over=False
b=True
snake=init_snake()
food=Creat_Food(snake)
food_style=Food_Style()
pos=(1,0)
#得分
score=0
last_move_time=time.time()
elif event.key==K_SPACE:
if not game_over:
pause=not pause
#以下为防止蛇在向右移动时按向左键,导致GameOver
elif event.key in (K_UP,K_w):
if b and not pos[1]: ###
pos=(0,-1)
b=False
elif event.key in (K_DOWN,K_s):
if b and not pos[1]:
pos = (0, 1)
b = False
elif event.key in (K_LEFT,K_a):
if b and not pos[0]:
pos = (-1, 0)
b = False
elif event.key in (K_RIGHT,K_d):
if b and not pos[0]:
pos = (1, 0)
b = False
#填充背景色
screen.fill(Back_Ground)
###
#画网格线、竖线
for x in range(Size, Screen_Width, Size):
pygame.draw.line(screen, Black, (x, Area_y[0] * Size), (x, Screen_Height), Line_Width)
#画网格线、横线
for y in range(Area_y[0] * Size, Screen_Height, Size):
pygame.draw.line(screen, Black, (0, y), (Screen_Width, y), Line_Width)
#蛇的爬行过程
if not game_over:
curTime=time.time()
if curTime-last_move_time>speed: ###
if not pause:
b=True
last_move_time=curTime
next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
#如果吃到了食物
if next_s==food:
snake.appendleft(next_s)
score+=food_style[0]
speed = orispeed - 0.03 * (score // 100)
food = Creat_Food(snake)
food_style = Food_Style()
else:
#在区域内
if Area_x[0]<=next_s[0]<=Area_x[1] and Area_y[0]<=next_s[1]<=Area_y[1] and next_s not in snake:
snake.appendleft(next_s)
snake.pop()
else :
game_over=True
#画食物
if not game_over:
'''
rect(Surface,color,Rect,width=0)
第一个参数指定矩形绘制到哪个Surface对象上
第二个参数指定颜色
第三个参数指定矩形的范围(left,top,width,height)
第四个参数指定矩形边框的大小(0表示填充矩形)
例如绘制三个矩形:
pygame.draw.rect(screen, BLACK, (50, 50, 150, 50), 0)
pygame.draw.rect(screen, BLACK, (250, 50, 150, 50), 1)
pygame.draw.rect(screen, BLACK, (450, 50, 150, 50), 10)
'''
# 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了
pygame.draw.rect(screen, food_style[1], (food[0] * Size, food[1] * Size, Size, Size), 0)
#画蛇
for s in snake:
pygame.draw.rect(screen, Dark, (s[0] * Size + Line_Width, s[1] * Size + Line_Width,
Size - Line_Width * 2, Size - Line_Width * 2), 0)
Print_Txt(screen, font1, 30, 7, f'速度: {score // 100}')
Print_Txt(screen, font1, 450, 7, f'得分: {score}')
#画GameOver
if game_over:
if game_start:
#print('GameOver')
Print_Txt(screen, font2, (Screen_Width - fwidth) // 2, (Screen_Height - fheight) // 2, 'GAME OVER',Red)
pygame.display.update()
if __name__=='__main__':
main()
数字华容道
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import random
from collections import OrderedDict
import pygame
FPS = 60
SHAPE = 4 # 棋盘shape
CELL_SIZE = 100 # 方格大小
CELL_GAP_SIZE = 10 # 方格间距
MARGIN = 10 # 方格的margin
PADDING = 10 # 方格的padding
SCREEN_WIDTH = (CELL_SIZE + MARGIN) * SHAPE + MARGIN # 屏幕宽度
SCREEN_HEIGHT = (CELL_SIZE + MARGIN) * SHAPE + MARGIN # 屏幕高度
BACKGROUND_COLOR = "#92877d" # 背景颜色
BACKGROUND_EMPTY_CELL_COLOR = "#9e948a" # 空方格颜色
BACKGROUND_CELL_COLOR = "#edc22e" # 方格颜色
# 定义两个元组相加
def tuple_add(t1, t2):
return (t1[0] + t2[0], t1[1] + t2[1])
class Logic:
def __init__(self, shape=4):
self.shape = int(shape) if shape > 2 else 4 # 初始化形状
self.tiles = OrderedDict() # 初始化数据
self.neighbors = [ # 定义方向矢量
[1, 0], # 下
[-1, 0], # 上
[0, 1], # 右
[0, -1], # 左
]
self.click_dict = {'x': {}, 'y': {}} # 定义鼠标点击坐标转换下标的数据
self.init_load() # 初始化加载
def init_load(self):
count = 1
# 生成正确的序列
for x in range(self.shape):
for y in range(self.shape):
mark = tuple([x, y])
self.tiles[mark] = count
count += 1
self.tiles[mark] = 0
for count in range(1000): # 随机移动一千次
neighbor = random.choice(self.neighbors)
spot = tuple_add(mark, neighbor)
if spot in self.tiles:
number = self.tiles[spot]
self.tiles[spot] = 0
self.tiles[mark] = number
mark = spot
self.init_click_dict()
def init_click_dict(self):
# 初始化点击坐标转换下标的数据
for r in range(self.shape):
for c in range(self.shape):
x = MARGIN * (c + 1) + c * CELL_SIZE
x1 = x + CELL_SIZE
click_x = tuple(range(x, x1))
self.click_dict['x'][click_x] = c
y = MARGIN * (r + 1) + r * CELL_SIZE
y1 = y + CELL_SIZE
click_y = tuple(range(y, y1))
self.click_dict['y'][click_y] = r
def move(self, mark):
# 移动数据
for neighbor in self.neighbors:
spot = tuple_add(mark, neighbor)
if spot in self.tiles and self.tiles[spot] is 0:
self.tiles[spot], self.tiles[mark] = self.tiles[
mark], self.tiles[spot]
break
def click_to_move(self, x, y):
# 点击移动
x1 = None
for k, v in self.click_dict['x'].items():
if x in k:
x1 = v
if x1 is None:
return
y1 = None
for k, v in self.click_dict['y'].items():
if y in k:
y1 = v
if y1 is None:
return
self.move((y1, x1))
def is_win(self):
# 游戏结束判定
if self.tiles[(self.shape - 1, self.shape - 1)] is not 0:
return False
values = list(self.tiles.values())
for index in range(values.__len__() - 1):
if index + 1 != values[index]:
return False
return True
def init_game():
# 初始化游戏
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('数字华容道 -- 0')
return screen
def draw_num(logic, screen):
for r in range(logic.shape):
for c in range(logic.shape):
num = logic.tiles[(r, c)]
if num is not 0:
color = pygame.Color(BACKGROUND_CELL_COLOR)
else:
color = pygame.Color(BACKGROUND_EMPTY_CELL_COLOR)
x = MARGIN * (c + 1) + c * CELL_SIZE
y = MARGIN * (r + 1) + r * CELL_SIZE
pygame.draw.rect(screen, color, (x, y, CELL_SIZE, CELL_SIZE))
if num is not 0:
font_size = int((CELL_SIZE - PADDING) / 1.3)
font = pygame.font.SysFont('arialBlod', font_size)
font_width, font_height = font.size(str(num))
screen.blit(font.render(str(num), True, (255, 255, 255)),
(x + (CELL_SIZE - font_width) / 2, y +
(CELL_SIZE - font_height) / 2 + 5))
def press(is_game_over, logic, COUNT, counts):
for event in pygame.event.get():
if event.type == COUNT and not is_game_over: # 设置定时器,记录时间
counts += 1
pygame.display.set_caption('数字华容道 -- {}'.format(counts))
if event.type == pygame.QUIT: # 点击关闭按钮退出
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP: # 鼠标点击
if event.button == 1 and not is_game_over:
x, y = event.pos
logic.click_to_move(int(x), int(y)) # 点击移动
elif event.type == pygame.KEYDOWN and event.key == 13: # 游戏结束,回车重开
return True
if COUNT:
return counts
def game_win(screen, logic, clock, text='You Win!'):
font = pygame.font.SysFont('Blod', int(SCREEN_WIDTH / 4))
font_width, font_height = font.size(str(text))
while True:
if press(True, logic, None, None):
break
screen.fill(pygame.Color(BACKGROUND_COLOR))
draw_num(logic, screen)
screen.blit(font.render(str(text), True, (0, 0, 0)),
((SCREEN_WIDTH - font_width) / 2,
(SCREEN_HEIGHT - font_height) / 2))
pygame.display.update()
clock.tick(FPS)
def main():
screen = init_game()
clock = pygame.time.Clock()
logic = Logic(SHAPE)
COUNT = pygame.USEREVENT + 1
pygame.time.set_timer(COUNT, 1000)
seconds = 0 # 记录时间
while True:
if logic.is_win(): # 判断游戏是否胜利
break
seconds = press(False, logic, COUNT, seconds) # 监控按键
screen.fill(pygame.Color(BACKGROUND_COLOR)) # 填充背景
draw_num(logic, screen) # 画数字
pygame.display.update()
clock.tick(FPS)
game_win(screen, logic, clock, text='Time:' + str(seconds))
if __name__ == "__main__":
while True:
main()