美文网首页
用python编写的工具和游戏

用python编写的工具和游戏

作者: Mc杰夫 | 来源:发表于2021-06-19 12:54 被阅读0次

    一个简单的计算器

    #  *_* 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()
    

    相关文章

      网友评论

          本文标题:用python编写的工具和游戏

          本文链接:https://www.haomeiwen.com/subject/wigryltx.html