zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【敬初学者】Python基础学完了,该怎么知道自己学的怎么样呢?十个经典实战小项目附源码

Python经典项目源码基础 怎么 实战 自己
2023-06-13 09:11:44 时间

大家好,又见面了,我是你们的朋友全栈君。

前言

前言

初学者要想成功,一句话,大量的实操,大量的练,乍一看我的这个答案似乎有点敷衍,但是这确实是我接触Python以来,总结出的最有价值的经验,接下来分享我自己初学时用来练手的经典实战小项目,适合初学者敲的代码。

1.街霸游戏

1.1 KO街霸

游戏小剧场 特别调查员春丽突然收到了来自中尉查理的一封邮件,邮件里详细地说明了神月家族在美国唐人街举办的街霸挑战赛,挑战的终极boss正是街霸维加。春丽在很小的时候,父亲就被维加残忍地杀害,为报父仇,春丽毅然决然地买好了飞往唐人街的机票。

邪恶的维加正通过催眠术,控制着在擂台上饮败的格斗家们在世界各地执行暗杀计划。

隆远在印度修行,孤身一人的春丽能在擂台上挑战成功吗?

程序完整源码

这是一个针对Python初学者的练手小程序,简单地模拟春丽与维加的格斗过程。有一定开发经验的朋友可以对程序进行扩展,比如利用多进程来模拟春丽同时与多人进行格斗。

Python

# 导入random模块,执行random模块中的choice方法来随机获取列表中的元素
import random
import time


VEGA_STRATEGIES = ["原地蹲防", "失误", "回旋攻击", "失误", "伤害修正", "回血", "超必杀"]
CHUNLI_KUNFU = ["气功拳", "旋转踢", "百裂脚", "霸山天升脚"]


def countdown(seconds=3, message=""):
    """ :param seconds: 倒数的秒数 :param message: 倒计时结束后输出的提示信息 :return: """
    for _ in range(seconds, 0, -1):
        _, _ = print(_), time.sleep(1)
    else:
        print(message)
        
        
def  generate_prompts(kunfu):
    """ :param kunfu: 街霸格斗选手的格斗招数,为一个列表对象,例如["气功拳", "旋转踢"] :return: 返回用户指令输入的提示信息,为一个字符串对象 """
    prompts = "\n"
    for index, value in enumerate(kunfu):
        prompts += "<{}>{}".format(index, value)
    prompts += "\n输入<>中的指令来挑战街霸:__\b\b"
    return prompts
    
    
    
def fight():
    # 定义整型变量fighter,用来保存街霸维加的血量
    vega = 100
    # 定义整型变量chunli,用来保存春丽的血量
    chunli = 100
    blood = 5
    prompts = generate_prompts(CHUNLI_KUNFU)
    countdown(message="Fight!")
    # 执行while循环,不断重复执行下面的代码
    while True:
        # 春丽或boss其中一人血量为0时就退出战斗
        if vega * chunli == 0:
            break
        # 执行input函数获得键盘的输入内容
        command = input(prompts)
        # 对输入的字符串类型转换为整型,读者在输入时必须输入有效的数字,否则会抛出异常
        try:
            command = int(command)
            _ = CHUNLI_KUNFU[command]
        except (ValueError, IndexError):
            print("春丽,这是在战斗,请输入正确的战斗指令!")
            continue
        print("春丽对街霸使出了{}".format(CHUNLI_KUNFU[command]))
        # 使用random模块中的choice函数,来随机选择列表里的值
        vega_strategy = random.choice(VEGA_STRATEGIES)
        if vega_strategy == "失误":
            print("街霸维加在对战中反击失误!")
        else:
            print("街霸维加在对战中对你使用了{}".format(vega_strategy))
        if vega_strategy in { 
   "原地蹲防", "回血"}:
            if vega_strategy == "回血" and vega < 100:
                vega += blood
        elif vega_strategy == "失误":
            vega -= blood*2
        elif vega_strategy == "伤害修正":
            vega -= blood
        elif vega_strategy == "超必杀":
            chunli -= blood*2
        else:
            chunli -= blood
        chunli = 0 if chunli  <=0 else chunli
        vega = 0 if vega  <=0 else vega
        
        print("\n-*- 春丽现在的血量:{} 维加现在的血量:{} -*-".format(chunli, vega))
        time.sleep(3)
    if chunli == 0:
        print("春丽,你战败了!")
    else:
        print("维加,我今天终于把你打败,父亲泉下有知,可以瞑目了!")
        
        
        
if __name__ == "__main__":
    fight()

程序的输出界面

1.2 春丽VS巴洛克

游戏小剧场 虽然美丽的春丽打败了维加,但邪恶的影罗组织并未就此覆灭。许多年以后,春丽站在A号街区,会突然想起打败神月卡琳后的那个下午。当时,身躯高大的巴洛克已将面具摘下,道场中的其他四名影子杀手,形如雕塑,酷似木偶…春丽经过这场残酷的战斗以后,在背部留下了一道很长的月牙形伤痕。

在本节程序实战中,通过多进程的方式来模拟春丽一人对抗影罗组织的五名邪恶杀手。

参考源码

通过多进程+队列来模拟春丽1VS5的街霸游戏挑战赛:

from multiprocessing import Process, Queue
import random



class Fighter:
    def __init__(self, name, blood = 100, justice = True, kungfu = None, enemies = 1):
        """ :param name: 表示该fighter的姓名 :param blood: 表示该fighter的血量 :param justice: 布尔类型,表示该fighter是否代表正义的一方 :param kungfu: 表示该fighter的格斗技能 :param enemies: 表示该fighter对抗的敌人数 """
        self.__name = name
        self.__blood = blood
        self.__justice = justice
        self.__kungfu = kungfu
        self.__enemies = enemies
        
        
        
    def  attack(self):
       kungfu, harm = None, 0
       if self.__blood > 0:
           kungfu = random.choice(list(self.__kungfu.keys()))
           harm = self.__kungfu[kungfu]
       return kungfu, harm
       
       
       
    @property
    def name(self):
        return self.__name
        
        
        
    @property
    def blood(self):
        return self.__blood
        
        
        
    @blood.setter
    def blood(self, value):
        self.__blood = value
        
        
        
    @property
    def enemies(self):
        return self.__enemies
        
        
        
    @enemies.setter
    def enemies(self, count):
        self.__enemies = count
        
        
        
    @property
    def justice(self):
        return self.__justice
        
        
        
def fight(fighter,  justice_attacks, injustice_attacks):
    """ :param fighter: Fighter对象 :param justice_attacks: 队列类型,表示春丽的攻击 :param injustice_attacks: 队列类型,表示巴洛克等杀手的攻击 :return: """
    while True:
        kungfu, harm = fighter.attack()
        attack = { 
   "name": fighter.name, "kungfu": kungfu,
                  "harm": harm, "blood": fighter.blood}
        if fighter.justice:
            # 通过justice_attacks代表的队列,向以巴洛克为首的杀手们发起一个攻击
            justice_attacks.put(attack)
            if fighter.blood == 0:
                break
            # 从justice_attacks代表的消息队列中,接收对方的一个攻击
            attack = injustice_attacks.get()
            # 如果对方攻击时的blood值为0,表示对方已被击败
            if attack["blood"] == 0:
                # 减去敌人数
                fighter.enemies -= 1
                if fighter.enemies == 0:
                    # 敌人已全部被击败, 退出战斗!
                    break
                else:
                    continue
        else:
            # 通过justice_attacks代表的队列,向春丽发起一个攻击
            injustice_attacks.put(attack)
            if fighter.blood == 0:
                break
            # 从justice_attacks队列中接收春丽发起的攻击
            attack = justice_attacks.get()
            # 如果春丽攻击时的血量为0,说明春丽已经被击败
            if attack["blood"] == 0:
               """ 春丽已经战败,通过justice_attacks对列向己方的杀手们进行消息转发, 同时退出战斗 """
               justice_attacks.put({ 
   "blood": 0})
               break
               
        kungfu, harm = fighter.attack()
        """ 如果在回击的过程中反击的伤害大于对方的伤害值, 则加上已有的血量值来实现回血的功能,否则将血量减去对应的伤害值 """
        fighter.blood += harm - attack["harm"]
        if fighter.blood <= 0:
            fighter.blood = 0
        elif fighter.blood > 100:
            fighter.blood = 100
            
    if fighter.blood > 0:
        print("{} 获得了胜利!!!".format(fighter.name))
        
        
        
if __name__ == "__main__":
    # 定义chunli_kungfu来保存春丽的招式及对应的伤害值
    chunli_kungfu = { 
   
        "失误": 0,
        "原地蹲防": 5,
        "龙星落": 10,
        "气功拳": 15,
        "旋转踢": 20,
        "百裂脚": 20,
        "霸山天升脚": 20,
        "超必杀-千翼气功掌": 25
    }
    # 定义baroque_kungfu来保存杀手巴洛克的招式及对应的伤害值
    baroque_kungfu = { 
   
        "失误": 0,
        "伤疤之恨": 15,
        "闪光漩涡": 20,
        "飞翔巴塞罗那": 20,
        "红色冲击": 20
    }
    # 定义来shadow_kungfu保存影子杀手的攻击策略及对应的伤害值
    shadow_kungfu = { 
   
        "失误": 0,
        "暗器": 10,
        "毒药": 15,
        "炸弹": 20
    }
    processes = []
    fighters = [
        Fighter(name="春丽", kungfu=chunli_kungfu, enemies=5),
        Fighter(name="巴洛克", kungfu=baroque_kungfu, justice=False),
        Fighter(name="影子杀手1", kungfu=shadow_kungfu, justice=False),
        Fighter(name="影子杀手2", kungfu=shadow_kungfu, justice=False),
        Fighter(name="影子杀手3", kungfu=shadow_kungfu, justice=False),
        Fighter(name="影子杀手4", kungfu=shadow_kungfu, justice=False)
    ]
    justice_attacks = Queue()
    injustice_attacks = Queue()
    for fighter in fighters:
        process = Process(target=fight, args=(fighter, justice_attacks, injustice_attacks))
        processes.append(process)
        
    [process.start() for process in processes]
    [process.join() for process in processes]

2.猜谜游戏

2.1简单的猜数字游戏

项目要求

实现一个简单的猜数字游戏:程序启动时获取一个随机值,根据用户的输入提示大了还是小了,如果用户输入的整数与随机值相等,则退出循环。

通过random模块randint方法获取一个随机值,通过input函数获取用户的输入。

代码示例:

# 导入random模块
import random
# 获取从1到100000之间的随机数
random_number = random.randint(1, 1000000)
# 执行input方法获取用户的输入,input的返回值为字符串类型,通过int()将其转换为整型
guess_number = int(input("Please enter the number:____\b\b\b\b"))

参考源码

import time
import random


def get_random_number(start=0, end=10**3):
    return random.randint(start, end)
    

def countdown(seconds=3, message=""):
    """ :param seconds: 倒数的秒数 :param message: 倒计时结束后输出的提示信息 :return: """
    for _ in range(seconds, 0, -1):
        _, _ = print(_), time.sleep(1)
    else:
        print(message)
        
    
def serve_forever():
      
    random_number = get_random_number()
    countdown(message="猜数字游戏开始,Go!!!")
    
    while True:
        try:
            guess_number = int(input("请输入你猜的数字:"+"_"*4+"\b"*4))
        except ValueError:
            print("请输入合法的数字!")
            continue
        if guess_number != random_number:
            _ = print("你输入的数字大了") if guess_number > random_number else print("你输入的数字小了")
            continue
        print("恭喜你猜对了!!!")
        if input("按键盘任意键继续玩猜数字游戏或输入quit退出游戏:____\b\b\b\b").lower() == "quit":
            break
        else:
            random_number = get_random_number()
    print("游戏已被终止,再见!!!")
    
    
    
if __name__ == "__main__":
    serve_forever()

程序的输出界面

2.2 进阶的猜姓名游戏

项目要求

定义一个人名集合,例如 {“王祖贤”, “李嘉欣”, “李嘉诚”, “刘德华”, “叶倩文”,“叶倩倩”, “王李丹妮”}。如果用户的输入前缀匹配第一个字,则提示”不错,有点接近了”,前缀匹配前面两个字,则提示”厉害,比较接近了”,完全匹配则提示”哇塞,你是个猜姓名天才,请收下我的膝盖”。

构造该Trie结构的算法逻辑很简单,以第一次构造为例:

将姓名中的第一个字作为键插入到指针指向的空字典中,键值为一个空字典,然后将指针指向键值所对应的空字典,接着将姓名中的第二个字作为键插入到指针指向的空字典中,键值为一个空字典,同样需要将指针指向键值所对应的空字典,不断重复这样的过程,直到遍历完姓名中的所有字符。

简化的代码实例:

name = "王八蛋"
trie = { 
   }
trie[name[0]] =  { 
   }
trie[name[0]][name[1]] =  { 
   }
trie[name[0]][name[1]][name[2]] =  { 
   }

这样在查找用户的输入是否包含某姓名的前缀时,只需要遍历用户输入的字符,然后在构造好的Trie结构中进行查找。

参考源码

import time

def countdown(seconds=3, message=""):
    """ :param seconds: 倒数的秒数 :param message: 倒计时结束后输出的提示信息 :return: """
    for _ in range(seconds, 0, -1):
        _, _ = print(_), time.sleep(1)
    else:
        print(message)
        
        
        
def build_lookup_table(data):
    """ :param data: a set of names, e.g: {"王祖贤", "李嘉欣"} :return: lookup table e.g:{'王': {'祖': {'贤': {}}}, '李': {'嘉': {'欣': {}}}} """
    lookup_table = { 
   }
    for name in data:
        lookup_table_ = lookup_table
        for char in name:
            if char not in lookup_table_:
                lookup_table_[char] = { 
   }
            lookup_table_ = lookup_table_[char]
    return lookup_table
    
    
    
def guess_name():
    stars = { 
   "王祖贤", "李嘉欣", "李嘉诚", "刘德华", "叶倩文", "叶倩倩", "王李丹妮"}
    # 构造一个查找表
    lookup_table = build_lookup_table(stars)
    countdown(3, "猜姓名游戏开始,Go!!!")
    messages = { 
   0: "不要瞎猜好吗?",  1: "不错,有点接近了",  2: "厉害,比较接近了",
                66: "哇塞,你是个猜姓名天才,请收下我的膝盖"}
    end = 2
    while True:
        name = input("请输入你要猜的姓名:____\b\b\b\b")
        if name in stars:
            print(messages[66])
            if input("按键盘任意键继续玩猜数字游戏或输入quit退出游戏:____\b\b\b\b").lower() == "quit":
                break
        else:
            lookup_table_ = lookup_table
            index = 0
            for word in name:
                if word in lookup_table_:
                    lookup_table_ = lookup_table_[word]
                    index = index+1 if index < end else index
                else:
                    break
            print(messages[index])
if __name__ == "__main__":
    guess_name()

程序的输出界面

2.3基于英文分词的猜单词游戏

项目要求

① 对某一篇英文文章进行分词,以获取一个英语词典 ② 如果用户输入的单词在词典中,则提示”你是个猜单词天才,请收下我的膝盖” ③ 如果用户的输入前缀匹配第一个字母,则提示”不错,有点接近了”,前缀匹配前面两个字母,则提示”厉害,比较接近了”

算法逻辑如下:

① 定义一个布尔类型的标记变量,初始情况下为True,表示已完成单词的拆分 ② 遍历英文字符串,如果当前字符为分隔符且尚未切分,则开始分词:将起始位置的索引与分隔符位置之前的所有字符进行拆分

③ 如果当前字符不是分隔符且已拆分,则将标记变量更新为False, 同时更新拆分的起始位置

参考源码

import time

def cut(content, language=0):
    """ :param content: 待分词的英文字符串,例如:"when a great dream shows up" :param language: 0表示对英文进行分词 :return: 返回分词后的词典,是一个集合类型, 例如:{"an", "and"} """
    dictionary = set()
    length = len(content)
    # 定义英文中的分隔符
    stop_words = { 
   ";", " ", "\n", ".", "!"}
    if language == 0:
        begin = 0
        # 标记变量,初始情况下表示已拆分
        is_cutted = True
        for index in range(length):
            # 如果当前字符为分隔符
            if content[index] in stop_words:
                # 且未拆分
                if not is_cutted:
                    dictionary.add(content[begin:index])
                    is_cutted = True
                continue
            elif is_cutted:
                begin = index
                is_cutted =  False
    return dictionary
    
    
    
def build_trie(dictionary):
    """ :param dictionary:英文词典集合 :return: 单词查找树,系字典对象 """
    trie = { 
   "root": { 
   }}
    for word in dictionary:
        next = trie["root"]
        for char in word:
            if char not in next:
                next[char] = { 
   }
            next = next[char]
        else:
            next[0]=0
    return trie
    
    
    
def countdown(seconds=3, message=""):
    """ :param seconds: 倒数的秒数 :param message: 倒计时结束后输出的提示信息 :return: """
    for _ in range(seconds, 0, -1):
        _, _ = print(_), time.sleep(1)
    else:
        print(message)
        
        
        
def guess_words():
    content = "when a great dream shows up, grab it!"
    dictionary = cut(content)
    lookup_table = build_trie(dictionary)
    countdown(3, "猜单词游戏开始,Go!!!")
    messages = { 
   0: "不要瞎猜好吗?", 1: "不错,有点接近了", 2: "厉害,比较接近了",
                66: "哇塞,你是个猜单词天才,请收下我的膝盖"}
    end = 2
    
    while True:
        word = input("请输入你要猜的单词:____\b\b\b\b")
        if word in dictionary:
            print(messages[66])
            if input("按键盘任意键继续玩猜单词游戏或输入quit退出游戏:____\b\b\b\b").lower() == "quit":
                break
        else:
            lookup_table_ = lookup_table["root"]
            index = 0
            for ch in word:
                if ch in lookup_table_:
                    lookup_table_ = lookup_table_[ch]
                    index = index+1 if index < end else index
                else:
                    break
            print(messages[index])
            
            
            
if __name__ == "__main__":
    guess_words()

程序的输出界面

3.简洁的小项目

(偷懒上线)

3.1 抓取知乎图片,只用30行代码

from selenium import webdriver
import time
import urllib.request

driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.zhihu.com/question/29134042")
i = 0
while i < 10:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(2)
    try:
        driver.find_element_by_css_selector('button.QuestionMainAction').click()
        print("page" + str(i))
        time.sleep(1)
    except:
        break
result_raw = driver.page_source
content_list = re.findall("img src=\"(.+?)\" ", str(result_raw))
n = 0
while n < len(content_list):
    i = time.time()
    local = (r"%s.jpg" % (i))
    urllib.request.urlretrieve(content_list[n], local)
    print("编号:" + str(i))
    n = n + 1

3.2 两个聊天机器人互相聊天

from time import sleep
import requests
s = input("请主人输入话题:")
while True:
    resp = requests.post("http://www.tuling123.com/openapi/api",data={ 
   "key":"4fede3c4384846b9a7d0456a5e1e2943", "info": s, })
    resp = resp.json()
    sleep(1)
    print('小鱼:', resp['text'])
    s = resp['text']
    resp = requests.get("http://api.qingyunke.com/api.php", { 
   'key': 'free', 'appid':0, 'msg': s})
    resp.encoding = 'utf8'
    resp = resp.json()
    sleep(1)
    print('菲菲:', resp['content'])
#网上还有一个据说智商比较高的小i机器人,用爬虫的功能来实现一下:

import urllib.request
import re

while True:
    x = input("主人:")
    x = urllib.parse.quote(x)
    link = urllib.request.urlopen(
        "http://nlp.xiaoi.com/robot/webrobot?&callback=__webrobot_processMsg&data=%7B%22sessionId%22%3A%22ff725c236e5245a3ac825b2dd88a7501%22%2C%22robotId%22%3A%22webbot%22%2C%22userId%22%3A%227cd29df3450745fbbdcf1a462e6c58e6%22%2C%22body%22%3A%7B%22content%22%3A%22" + x + "%22%7D%2C%22type%22%3A%22txt%22%7D")
    html_doc = link.read().decode()
    reply_list = re.findall(r'\"content\":\"(.+?)\\r\\n\"', html_doc)
    print("小i:" + reply_list[-1])

3.3 自动写检讨书

import random
import xlrd

ExcelFile = xlrd.open_workbook(r'test.xlsx')
sheet = ExcelFile.sheet_by_name('Sheet1')
i = []
x = input("请输入具体事件:")
y = int(input("老师要求的字数:"))
while len(str(i)) < y * 1.2:
    s = random.randint(1, 60)
    rows = sheet.row_values(s)
    i.append(*rows)
print(" "*8+"检讨书"+"\n"+"老师:")
print("我不应该" + str(x)+",", *i)
print("再次请老师原谅!")
''' 以下是样稿: 请输入具体事件:抽烟 老师要求的字数:200 检讨书 老师: 我不应该抽烟, 学校一开学就三令五申,一再强调校规校纪,提醒学生不要违反校规,可我却没有把学校和老师的话放在心上,没有重视老师说的话,没有重视学校颁布的重要事项,当成了耳旁风,这些都是不应该的。同时也真诚地希望老师能继续关心和支持我,并却对我的问题酌情处理。 无论在学习还是在别的方面我都会用校规来严格要求自己,我会把握这次机会。 但事实证明,仅仅是热情投入、刻苦努力、钻研学业是不够的,还要有清醒的政治头脑、大局意识和纪律观念,否则就会在学习上迷失方向,使国家和学校受损失。 再次请老师原谅! '''

3.4 屏幕录相机,抓屏软件

from time import sleep
from PIL import ImageGrab

m = int(input("请输入想抓屏几分钟:"))
m = m * 60
n = 1
while n < m:
    sleep(0.02)
    im = ImageGrab.grab()
    local = (r"%s.jpg" % (n))
    im.save(local, 'jpeg')
    n = n + 1

3.5 制作Gif动图

 from PIL import Image

im = Image.open("1.jpg")
images = []
images.append(Image.open('2.jpg'))
images.append(Image.open('3.jpg'))
im.save('gif.gif', save_all=True, append_images=images, loop=1, duration=1, comment=b"aa

分享到这结束了,感谢观看哦,最后说一句,要想成功就要多去练多去敲,重中之重。

更多Python精彩内容与资源分享可以看我主页简介。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142177.html原文链接:https://javaforall.cn