面向对象编程项目案例(栈与队列封装和乌龟吃鱼游戏)

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-1 06:04   141   0

一.Pygame相关介绍

1、Pygame是跨平台Python模块,专为电子游戏设计,包含图像、声音。允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。Pygame常用模块
2、一个游戏循环(也可以称为主循环)就做下面这三件事:
处理事件
更新游戏状态
绘制游戏状态到屏幕上

3、安装:Pygame的安装非常简单

1)在Terminal里面执行pip install Pygame就可以。此方法较慢。

2)在Terminal里面执行pip install -i https:pypi.duban.com/simple pygame。此方法比较迅速。

Pygame安装如下:

表示安装成功!

4.Pygame简单操作介绍:

每次需要导入Pygame这个模块

import pygame

# 1). 初始化pygame
pygame.init()
# 2). 显示游戏界面
pygame.display.set_mode((600, 600))           #设置画布的规格
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            print("游戏结束......")
            exit(0)
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                print("UP")
            elif event.key == pygame.K_DOWN:
                print('DOWN')

饰演结果:

2)Pygame常用模块

import pygame
import sys

pygame.init()   #初始化pygame
size=width, height=320,240   #设置窗口大小
screen=pygame.display.set_mode(size)    #显示窗口

while True:               #死循环确保窗口一直显示
    for event in pygame.event.get():    #遍历所有事件
        if event.type== pygame.QUIT:     #如果单击关闭窗口,则退出
            sys.exit()

pygame.quit()    #退出pygame

打印结果如下:

二.项目案例

项目案例一: 栈与队列的封装

栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈”。

向一个栈内插入元素称为是进栈(push)
从一个栈删除元素称为是出栈(pop)

特点 :后进先出(LIFO)

队列是限制在一端进行插入操作和另一端删除操作的线性表,允许进行插入操作的一端称为“队尾”,允许进行删除操作的一端称为“队头”,当队列中没有元素时称为“空队”。

特点 :先进先出(FIFO)

如:实现一个简单的入栈出栈功能:

class Stack(object):
    """
       根据列表的数据结构封装栈的数据结构
       属性: 栈元素stack
       方法:
           get_top()
           get_bootom()
           push()
           pop()
    """

    def __init__(self):
        self.stack=[]
    def top(self):
        return self.stack[-1]
    def bootom(self):
        return self.stack[0]
    def push(self,item):
        self.stack.append(item)
        return True

    def pop(self):
        item=self.stack.pop()
        return item
    def show(self):
        return self.stack
    #魔术方法:(对于已封装好的模块(stack),不能直接调用内置方法len求长度,只有用了魔术方才可以调用len()这个函数)
    def __len__(self):
        return len(self.stack)
if __name__ =='__main__':
    stack=Stack()
    print(stack.show())
    stack.push(1)
    stack.push(2)
    stack.push(3)
    print("入栈后:",stack.show())
    item=stack.pop()
    print("出栈元素为:", item)
    print("出栈后:",stack.show())
    print("栈元素个数:",len(stack))          #或者print("栈元素个数:", stack.__len__()),两种写法同样的效果。

打印结果:

[]
入栈后: [1, 2, 3]
出栈元素为: 3
出栈后: [1, 2]
栈元素个数: 2

项目案例二: 二叉树的理解(二叉树节点的封装)

1)(lchild, rchild)

class Node(object):
    def __init__(self, data, lchild=None, rchild=None):
        self.data = data
        self.lchild = lchild
        self.rchild = rchild
        
        # 魔术方法__str__
    def __str__(self):
        return 'Node<%s>' % (self.data)

if __name__ == '__main__':
    D = Node('D')
    B = Node('B', D)
    C = Node('C')
    A = Node('A', B, C)
    print("A-left:", str(A.lchild))
    print("A-right:", str(A.rchild))

打印结果:

A-left: Node<B>
A-right: Node<C>

2)先序遍历: 根节点-左子树节点-右子树节点;

后序遍历: -左子树节点-右子树节点-根节点;

中序遍历: -左子树节点--根节点-右子树节点

class Node(object):
    def __init__(self, data, lchild=None, rchild=None):
        self.data = data
        self.lchild = lchild
        self.rchild = rchild

    # 魔术方法: len(), __len__. str(), __str__
    def __str__(self):  # 友好的字符串显示信息
        return 'Node<%s>' % (self.data)

def pre_view( root):
    """
    先序遍历: 根节点-左子树节点-右子树节点
    传递根节点
    :param root:
    :return:
    """
    if root == None:
        return
    print(root.data)
    pre_view(root.lchild)
    pre_view(root.rchild)
def last_view(root):
    """
    后序遍历: -左子树节点-右子树节点-根节点
    传递根节点
    :param root:
    :return:
    """
    if root == None:
        return
    last_view(root.lchild)
    last_view(root.rchild)
    print(root.data)

def mid_view(root):
    """
    中序遍历: -左子树节点--根节点-右子树节点
    传递根节点
    :param root:
    :return:
    """
    if root == None:
        return
    mid_view(root.lchild)
    print(root.data)
    mid_view(root.rchild)

if __name__ == '__main__':
    D = Node('D')
    B = Node('B', D)
    C = Node('C')
    A = Node('A', B, C)

    # 先序遍历(根左右)、中序遍历(左根右)、后序遍历(左右根)
    print("先序遍历:")
    pre_view(A)
    print("后序遍历:")
    last_view(A)
    print("中序遍历:")
    mid_view(A)

打印结果:

先序遍历:
A
B
D
C
后序遍历:
D
B
C
A
中序遍历:
D
B
A
C

项目案例二: 乌龟(小聪)吃鱼(热狗)游戏

游戏规则:
1). 假设游戏场景为范围(x,y)为0<=x<=10,0<=y<=10
2). 游戏生成1只乌龟和10条鱼, 它们的移动方向均随机
3). 乌龟的最大移动能力为2(它可以随机选择1还是2移动),
鱼儿的最大移动能力是1当移动到场景边缘,自动向反方向移动
4). 乌龟初始化体力为100(上限), 乌龟每移动一次,体力消耗1
当乌龟和鱼坐标重叠,乌龟吃掉鱼,乌龟体力增加20, 鱼暂不计算体力
5). 当乌龟体力值为0(挂掉)或者鱼儿的数量为0游戏结束

import random
import pygame

class SiCong(object):
    """
    小聪(人)类:
        属性: (x,y), power
        方法: move(), eat()
    """

    def __init__(self):
        self.x = random.randint(50, width - 50)
        self.y = random.randint(50, height - 50)
        self.power = 100

    def move(self, new_x, new_y):
        """小聪移动的方法"""
        self.x = new_x % width
        self.y = new_y % height

    def eat(self):
        """小聪吃热狗"""
        self.power += 20
        print("小聪吃到热狗, 能量+20!")
class HotDog(object):
    """
    食物类:
        属性: (x,y)
        方法: move()
    """

    def __init__(self):
        self.x = random.randint(50, width - 50)
        self.y = random.randint(50, height - 50)

    def move(self):
        """
           热狗的最大移动能力是1当移动到场景边缘,
        """
        # 热狗的最大移动能力是1当移动到场景边缘,
        move_skills = [-8]
        # 计算热狗最新的x轴坐标;()
        new_x = self.x + random.choice(move_skills)
        # 当移动到场景边缘如何处理?
        self.x = new_x % width
def main():
    pygame.init()
    # 显示游戏界面
    screen = pygame.display.set_mode((width, height))
    # 设置界面标题
    pygame.display.set_caption("吃热狗游戏")

    # 加载游戏中需要的图片
    bg = pygame.image.load('./img/bg2.png').convert()
    hotdogImg = pygame.image.load('./img/hot-dog.png').convert_alpha()
    sicongImg = pygame.image.load('./img/sicong.png').convert_alpha()

    hd_width, hd_height = hotdogImg.get_width(), hotdogImg.get_height()
    sc_width, sc_height = sicongImg.get_width(), sicongImg.get_height()

    # 加载游戏音乐(背景音乐和吃掉热狗的音乐)
    pygame.mixer.music.load('./img/game_music.mp3')
    pygame.mixer.music.play(loops=0, start=0.0)  # 播放设置, 不循环且从0.0s开始播放

    # 设置分数显示参数信息(显示位置、字体颜色、字体大小)
    scoreCount = 0
    font = pygame.font.SysFont('arial', 30)  # 系统设置字体的类型和大小
    # 颜色表示法: RGB  (255, 0, 0)-红色  (255, 255, 255)-白色  (0, 0, 0)-黑色
    score = font.render("Score: %s" % (scoreCount), True, (0, 0, 0))

    # 创建一个Clock对象,跟踪游戏运行时间
    fpsClock = pygame.time.Clock()

    # 创建一个小聪和15个热狗
    sicong = SiCong()
    hotdogs = [HotDog() for item in range(15)]

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                print("游戏结束......")
                exit(0)
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    # 移动人物向上多少个像素
                    sicong.move(sicong.x, sicong.y - 15)
                elif event.key == pygame.K_DOWN:
                    sicong.move(sicong.x, sicong.y + 15)
                if event.key == pygame.K_LEFT:
                    # 移动人物向上多少个像素
                    sicong.move(sicong.x - 15, sicong.y)
                elif event.key == pygame.K_RIGHT:
                    sicong.move(sicong.x + 15, sicong.y)

        # 绘制背景和分数
        screen.blit(bg, (0, 0))
        screen.blit(score, (200, 20))
        # 绘制热狗,并实现热狗的移动
        for hd in hotdogs:
            screen.blit(hotdogImg, (hd.x, hd.y))
            hd.move()

        # 绘制sicong
        screen.blit(sicongImg, (sicong.x, sicong.y))
        # 判断游戏是否结束: 当人物体力值为0(挂掉)或者热狗的数量为0游戏结束
        if sicong.power == 0:
            print("Game Over: Sicong Power is 0")
            exit(1)
        if len(hotdogs) == 0:
            print("Game Over: hot-dog count is 0")
            exit(2)
        # 判断人物是否吃到热狗:人物和热狗的坐标值相同, 则认为吃掉
        for hd in hotdogs:
            if 0 < sicong.x - hd.x < 50 and 0 < sicong.y - hd.y < 50:
                # 增加人物的能量值
                sicong.eat()
                # 移除被吃掉的热狗
                hotdogs.remove(hd)
                # 增加得分
                scoreCount += 10
                # 重新设置得分信息
                score = font.render("Score: %s" % (scoreCount), True, (0, 0, 0))
        # 更新内容到游戏窗口
        pygame.display.update()
        fpsClock.tick(10)  # 每秒更新10帧
if __name__ == '__main__':
    width =785
    height = 570
    main()

运行结果:

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP