Python实战之看图猜字游戏的实现

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Python实战之看图猜字游戏的实现

木木子学python   2023-03-21 我要评论

导语

看图猜成语,是考验一个人的反应能力,也考验一个人的右脑思维。

据说越聪明的人,这道题的完成率越高。你想试一试嘛?今天就给你这次机会啦!

哈喽!大家下午好,我是即将出场每天疯狂码代码的木木子。

为了想一下今天给大家更新什么内容的我,想了整整一个晚上,顺便熬了一个通宵的熊猫眼,在今天晚上快6点下班之前终于赶完了最后的游戏代码。每天都在代码的海洋里来来回回,痛并快乐喆.....(其实上班只有痛苦,主要是舍不得那个money,只能选择肝了鸭)大实话.jpg

最近很多网友又在问小编要成语游戏玩,我知道大家已经把前面的(往期也有很多游戏PYhton代码的哈)给玩穿了,所以今天再给大家带来一款全新的Python代码小程序猜成语游戏《疯狂猜成语》,这款游戏小编觉得是目前(我努力了真的)成语游戏里面做得最为漂亮的,最古朴的,画风很简单,希望大家不要丢菜叶子跟臭鸡蛋,23333......

当然了游戏本身的挑战非常不简单了,所以喜欢挑战的朋友一定别错过,欢迎大家一起来玩儿哈,看看谁能问鼎看图猜成语的顶峰呢?评论区看看你们谁的分数最6吧!

本文主要分为两块大的内容代码:首先是爬取成语的图片,然后做一个游戏界面。

一、爬取成语图片

1)运行环境 

 本文用到的环境如下—— 

 Python3、Pycharm社区版,第三方模块:requests、pillow、fake_useragent等部分自带的库只

要安装完 Python就可以直接使用了

 一般安装:pip install +模块名 

镜像源安装:pip install -i pypi.douban.com/simple/+模块名…

 (之前有说过安装报错的几种方式跟解决方法,不会安装的可以去看下,还有很多国内镜像源也有文章的)

2)代码展示

import requests
import re
import os
import time
from PIL import Image
from fake_useragent import UserAgent

# 爬取成语图片
def SpiderIdiomPictures():
    cookies = {
        'BAIDU_SSP_lcr': 'https://www.baidu.com/link?url=58oz4AEVxDWXanBqrfF95dogUPcAVAktBQT0uBu8o4rGPY4J4Kg_-DsmJdvTHryfy8pdGnnOjDG54qbh82KB7K&wd=&eqid=ecc1cb040001afcc0000000662a84cc7',
        'Hm_lvt_8754302607a1cfb0d1d9cddeb79c593d': '1654580566,1655196891',
        'Hm_lpvt_8754302607a1cfb0d1d9cddeb79c593d': '1655200014',
    }
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        'Pragma': 'no-cache',
        'Referer': 'http://www.hydcd.com/cy/fkccy/index3.htm',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
    }
    if not os.path.exists('./看图猜成语'):
        os.mkdir('./看图猜成语')
    idx = 0
    for page in range(1,3): #爬取2页的图片
        print(f'\n\033[31m<<<第{page}页爬取中……>>>\033[0m')
        if page == 1:
            page = ''
        url = f'http://www.hydcd.com/cy/fkccy/index{page}.htm'
        session = requests.session()
        response = session.get(url=url, cookies=cookies, headers=headers)
        response.encoding = response.apparent_encoding
        ###解析图片url(http://www.hydcd.com/cy/fkccy/images/CF91100-50.png)和成语
        for i in re.findall('<img border="0" src="(.*?)"></p>',response.text):
            result = i.split('"')
            if len(result) > 2:
                img_url = f'http://www.hydcd.com/cy/fkccy/{result[0]}'  #图片url
                idiom_name = result[2] #图片名字(成语名)
                if len(idiom_name) == 4:
                    headers['User-Agent'] = UserAgent().Chrome
                    with open(f'./看图猜成语/{idiom_name}.png','wb') as f:
                        f.write(session.get(img_url,headers=headers).content)
                    print(f'{idiom_name}.png 保存成功!!!')
                    time.sleep(0.3)
                    idx += 1

    print(f'\n抓取完毕!!!\n总共抓取\033[31m{idx}张\033[0m图片')

# 图片放大
def ImageProcessingBig():
    print(f'\n\033[31m开始将图片进行放大>>>\033[0m')
    for imgfile in os.listdir('./看图猜成语/'):
        if len(imgfile.split('.')) == 2:
            # 待处理图片路径
            img_path = Image.open('./看图猜成语/'+imgfile)
            # resize图片大小,入口参数为一个tuple,新的图片的大小
            img_size = img_path.resize((300, 300))
            # 处理图片后存储路径,以及存储格式
            imgname = imgfile.split('.')[0]
            img_size.save(f'./看图猜成语/{imgname}.png')
    print(f'\n\033[31m<<<所有图片已放大完成!!!\033[0m')


if __name__ == '__main__':
    # 爬取网站上的成语图片(http://www.hydcd.com/cy/fkccy/index.htm),图片大小120x120
    SpiderIdiomPictures()
    # 把爬取到的所有图片放大(300x300)
    ImageProcessingBig()

3)效果展示

这里是有一千多张图片的哦!

​让我们看下爬下来的图片是怎么样子的吧:

有很多重复的,因为下载了几次了哈。

二、看图猜成语

1)素材准备

2)代码实现

import ttkbootstrap as ttk
import sys,os,random,threading,time,datetime
from ttkbootstrap.constants import *
from ttkbootstrap.dialogs import Messagebox,Querybox

class ttkbootstrapWindow:
    # 实例化创建应用程序窗口
    root = ttk.Window(title="看图猜成语", themename="litera", resizable=(False, False))
    # 让窗口居中
    def window_middle(self,windowwidth,windowheight):
        screenwidth = self.root.winfo_screenwidth()
        screenheight = self.root.winfo_screenheight()
        locx = int((screenwidth - windowwidth) / 2)
        locy = int((screenheight - windowheight) / 2)
        self.root.geometry("{}x{}+{}+{}".format(windowwidth, windowheight, locx, locy))
    # 显示窗口
    def window_displaymodule(self):
        self.root.mainloop()

# 看图猜成语
class guessIdiomsFromPictures(ttkbootstrapWindow):
    def __init__(self):
        super().__init__()
        self.index()
        self.window_displaymodule()
    # 首页内容
    def index(self):
        self.window_middle(windowwidth=960,windowheight=540) #窗口大小宽x高(960 x 540),默认居中
        self.index_frame = ttk.Frame(self.root)
        self.index_frame.pack(fill=BOTH,expand=YES)
        self.bg_img = ttk.PhotoImage(file='./sucai/index_bg.png')
        self.bg_img_Label = ttk.Label(self.index_frame, image=self.bg_img)
        self.bg_img_Label.pack(fill=BOTH,expand=YES)
        self.title_lable = ttk.Label(self.index_frame,text='  看图猜成语', font=('华文行楷',56,'italic'),cursor='watch', background='#E7CBB5', bootstyle=WARNING,width=14)
        self.begin_button_img = ttk.PhotoImage(file='./sucai/beginGame.png')
        self.entry_nickname = ttk.Entry(self.index_frame, show=None, font=('微软雅黑', 16))
        self.begin_button = ttk.Button(self.index_frame, bootstyle=(SUCCESS, "outline-toolbutton"),image=self.begin_button_img,command=self.begin_game)
        self.exit_button_img = ttk.PhotoImage(file='./sucai/exitGame.png')
        self.exit_button = ttk.Button(self.index_frame, bootstyle=(SUCCESS, "outline-toolbutton"),image=self.exit_button_img,command=self.exit_game)
        self.index_move()
    # 页面组件移动
    def index_move(self):
        def run(rate):
            rate += 5
            button_posy = 540 - rate*1.5
            self.begin_button.place(x=270,y=button_posy)
            self.exit_button.place(x=480,y=button_posy+10)
            if rate < 80:
                self.title_lable.place(x=190, y=rate)
                self.title_lable.after(60,run ,rate % 80)
            elif 80<= rate < 150:
                self.title_lable.after(60, run, rate % 150)
            else:
                ttk.Label(self.bg_img_Label, text='请输入昵称:', cursor='watch', bootstyle=DARK).place(x=250, y=212)
                self.entry_nickname.insert('0', "暴龙战士之王")
                self.entry_nickname.place(x=340, y=200, width=360, height=50)
        run(0)
    # 验证昵称是否为空
    def index_verify(self):
        self.nickname = self.entry_nickname.get().strip()
        if self.nickname:
            return True
        else:
            return False
    # 开始游戏
    def begin_game(self):
        try:
            if not self.index_verify():
                Messagebox.show_info(message="请先输入您的昵称!")
                return
            self.index_frame.destroy()
            game_modeSelection_page(self.nickname)
        except:
            pass
    # 退出游戏
    def exit_game(self):
        sys.exit()

#游戏模式选择页面
class game_modeSelection_page(ttkbootstrapWindow):
    def __init__(self,nickname):
        super().__init__()
        self.nickname = nickname
        self.page()
    def page(self):
        self.window_middle(500,300)
        self.frame = ttk.Frame(self.root)
        self.frame.pack(fill=BOTH, expand=YES)
        self.bg = ttk.PhotoImage(file='./sucai/bg2.png')
        ttk.Label(self.frame,anchor='nw', image=self.bg).pack()
        l1 = ttk.Label(self.frame,text='训练模式', font=('华文行楷', 32),relief=RAISED,cursor='hand2',bootstyle=WARNING,background='#324762')
        l1.place(x=150,y=60)
        l1.bind("<Button-1>",self.game_train_mode)
        l2 = ttk.Label(self.frame, text='闯关模式', font=('华文行楷', 32),relief=RAISED,cursor='hand2',bootstyle=SUCCESS,background='#324762')
        l2.place(x=150, y=140)
        l2.bind("<Button-1>", self.game_chuangguan_mode)
    def game_train_mode(self,event):
        self.frame.destroy()
        game_train_page(self.nickname)
    def game_chuangguan_mode(self,event):
        # 默认10个关卡(initialvalue=10)
        number = Querybox.get_integer(prompt="请设置关卡数量:",title="自定义关卡数量 ",initialvalue=10,minvalue=0,maxvalue=50)
        if number:
            self.frame.destroy()
            game_chuangguan_page(self.nickname,number)

#在游戏两种模式中有相同写法的组件
class game_same_components(ttkbootstrapWindow):
    def __init__(self):
        super().__init__()
    def same_page(self,nickname):
        self.nickname = nickname
        self.window_middle(960, 540)
        self.canvas = ttk.Canvas(self.root)
        self.canvas.pack(fill=BOTH, expand=YES)
        self.bg = ttk.PhotoImage(file='./sucai/bg3.png')
        self.canvas.create_image(0, 35, anchor='nw', image=self.bg)
        self.canvas.create_rectangle(0, 0, 960, 35, fill='#F4F4F4', outline='#F4F4F4')
        nickname_lable = ttk.Label(self.canvas, text=f'欢迎:【{self.nickname}】玩家上线', font=20, bootstyle=INFO,background='#F4F4F4')
        nickname_lable.place(x=960, y=4)
        def nickname_lable_move(rate):
            rate += 5
            nickname_lable.place(x=960 - rate, y=4)
            if rate < 960:
                nickname_lable.after(50, nickname_lable_move, rate % 960)
        nickname_lable_move(0)
        self.return_button_img = ttk.PhotoImage(file='./sucai/return.png')
        self.return_button = ttk.Button(self.canvas, bootstyle=(LIGHT, "outline-toolbutton"), image=self.return_button_img,command=self.return_game_modeSelection_page)
        self.return_button.place(x=0, y=35)
    def return_game_modeSelection_page(self):
        self.canvas.destroy()
        game_modeSelection_page(self.nickname)

#游戏训练模式页面
class game_train_page(game_same_components):
    def __init__(self,nickname):
        super().__init__()
        self.nickname = nickname
        self.game_page()
    loading_img_times = 0  # 记录加载图片次数
    answer_times = 0  # 记录回答总次数
    answer_correct_times = 0  # 记录回答正确次数
    #游戏页面
    def game_page(self):
        self.same_page(self.nickname)
        self.canvas.create_rectangle(200, 100, 535, 435)
        self.answer_idiom_entry = ttk.Entry(self.canvas, show=None, font=('微软雅黑', 32),bootstyle=DANGER)
        self.answer_idiom_entry.place(x=580,y=190,height=100,width=300)
        self.answer_idiom_entry.bind("<Return>", lambda event: self.answer())
        self.answer_idiom_button_img = ttk.PhotoImage(file='./sucai/ensure.png')
        answer_idiom_button = ttk.Button(self.canvas, bootstyle=(LIGHT, "outline-toolbutton"),image=self.answer_idiom_button_img,command=self.answer)
        answer_idiom_button.place(x=635,y=310)
        see_idiom_button = ttk.Button(self.canvas,text='查看', bootstyle=(PRIMARY, "outline-toolbutton"),command=self.see_answer)
        see_idiom_button.place(x=480, y=470)
        self.accuracy_lable1 = ttk.Label(self.canvas,text='正确率:',font=('华文行楷', 20),background='#D3E0E8')
        self.accuracy_lable1.place(x=600, y=120)
        self.accuracy_lable2 = ttk.Label(self.canvas, text="0.0%", font=('华文行楷', 20),bootstyle=DANGER,background='#D3E0E8')
        self.accuracy_lable2.place(x=750, y=120)
        self.loading_idiom_img()
    #加载成语图片
    def loading_idiom_img(self):
        self.loading_img_times += 1
        self.idiom = random.choice(os.listdir('./看图猜成语'))
        self.idiom_result = self.idiom.split('.')[0]
        print('答案:',self.idiom_result)
        self.idiom_img = ttk.PhotoImage(file=f'./看图猜成语/{self.idiom}')
        lm = ttk.Label(self.canvas,image=self.idiom_img)
        lm.place(x=215,y=115)
        guanqia_lable = ttk.Label(self.canvas, font=('华文行楷', 32),background='#48A6B0')
        guanqia_lable.place(x=300,y=450)
        guanqia_lable.config(text=f'第 {self.loading_img_times} 关')
    #查看答案
    def see_answer(self):
        Messagebox.show_info(message=self.idiom_result)
    def answer(self):
        if self.answer_idiom_entry.get().strip():
            self.answer_times += 1
            if self.answer_idiom_entry.get().strip() == self.idiom_result:
                Messagebox.show_info(message="恭喜,回答正确!!!")
                self.loading_idiom_img()
                self.answer_idiom_entry.delete(0,'end')
                self.answer_correct_times += 1
            else:
                if not Messagebox.yesno(message="回答错误!!!\n是否继续回答?") == 'Yes':
                    self.loading_idiom_img()
                    self.answer_idiom_entry.delete(0, 'end')
            self.accuracy_lable2.config(text=f'{round(self.answer_correct_times / self.answer_times, 2) * 100}%')

#游戏闯关模式页面
class game_chuangguan_page(game_same_components):
    CLICKTIMES = 0 #点击次数
    TRUEANSWER = '' #答案
    IDX = 1        #第几关,默认第1关
    def __init__(self, nickname,number):
        super().__init__()
        self.nickname = nickname
        self.idiom_list = random.sample(os.listdir('./看图猜成语'), number) #随机初始化选取20张图片,用于设置20个关卡
        self.game_page()
    def game_page(self):
        self.same_page(self.nickname)
        self.canvas.create_rectangle(150, 100, 485, 435)
        self.guanqia_lable = ttk.Label(self.canvas,text='第? / ?关', font=('华文行楷', 32), background='#48A6B0') #显示关卡数
        self.guanqia_lable.place(x=200, y=40)
        self.lm = ttk.Label(self.canvas)  #用于配置图片
        self.lm.place(x=165, y=115)
        self.result_label = ttk.Label(self.canvas,text='', font=('华文行楷', 32), background='#A1F8EE', bootstyle=DANGER) # 用于显示答案的结果
        self.result_label.place(x=40,y=135,height=300)
        ttk.Button(self.canvas,text='重选', bootstyle=(SUCCESS, "outline-toolbutton"),command=self.update_label).place(x=550,y=470,width=90,height=60) # 重选按钮
        self.create_selection_result_label()
        self.create_option_text_label()
        self.loading_idiom_img()
        self.recording_time()
    # 创建四个用于选择结果的标签
    def create_selection_result_label(self):
        self.answer_list = []
        for i in range(4):
            label = ttk.Label(self.canvas, text='', font=("微软雅黑", 35), background='', width=2, cursor='hand2')
            label.place(x=130 + i * 100, y=450)
            self.answer_list.append(label)
    # 创建用于选择的内容标签
    def create_option_text_label(self):
        def click_label(event):
            if self.CLICKTIMES < 4:
                self.CLICKTIMES += 1
                label_text = event.widget["text"]  # 得到标签上的文本
                self.answer(label_text)
        self.label_oop_list = []
        # 设置4行4列的标签
        for i in range(4):
            for j in range(4):
                label = ttk.Label(self.canvas, text='', font=("微软雅黑", 35), background='#FFFAE3', width=2,cursor='hand2')
                label.place(x=510 + j * 100, y=90 + i * 95)
                label.bind("<Button-1>", click_label)
                self.label_oop_list.append(label)
    # 加载成语图片
    def loading_idiom_img(self,):
        self.idiom = self.idiom_list[self.IDX - 1].split('.')[0]
        print('答案:', self.idiom)
        disturb_text_list = [self.GBK2312() for i in range(12)]  # 随机生成12个干扰汉字
        disturb_text_list.extend([i for i in self.idiom])
        for label_oop in self.label_oop_list:
            text = random.choice(disturb_text_list)
            disturb_text_list.remove(text)
            label_oop.configure(text=text)
        self.guanqia_lable.config(text=f'第 {self.IDX} / {len(self.idiom_list)}关')
        self.idiom_img = ttk.PhotoImage(file=f'./看图猜成语/{self.idiom}.png')
        self.lm.configure(image=self.idiom_img)
    def answer(self,label_text):
        self.answer_list[self.CLICKTIMES - 1].configure(text=label_text)
        self.TRUEANSWER += label_text
        if len(self.TRUEANSWER) == 4:
            if self.TRUEANSWER == self.idiom:
                t = threading.Thread(target=self.dispaly_answer_result,args=('回\n答\n正\n确',))
                t.setDaemon(True)
                t.start()
                self.IDX += 1
                if self.IDX > len(self.idiom_list):
                    Messagebox.show_info(message=f"恭喜您已通过!!!\n耗时为:{self.time_}")
                    self.flag = False
                    self.return_game_modeSelection_page()
                    return
                self.update_label()
                self.loading_idiom_img()
            else:
                t = threading.Thread(target=self.dispaly_answer_result, args=('回\n答\n错\n误',))
                t.setDaemon(True)
                t.start()
    # 显示回答结果是否正确
    def dispaly_answer_result(self,text):
        self.result_label.configure(text=text)
        time.sleep(3)
        try: self.result_label.configure(text='')
        except Exception as e: print(e)
    # 重选
    def update_label(self):
        self.CLICKTIMES = 0
        self.TRUEANSWER = ''
        for i in self.answer_list:i.destroy()
        self.create_selection_result_label()
    # 随机生成一个汉字
    def GBK2312(self, ):
        head = random.randint(0xb0, 0xf7)
        body = random.randint(0xa1, 0xfe)
        val = f'{head:x}{body:x}'
        str = bytes.fromhex(val).decode('gb2312')
        return str
    # 记录通关所耗时
    def recording_time(self):
        self.flag = True # 定义一个信号量,用于当我们完成游戏通过时,run()结束循环
        time_label = ttk.Label(self.canvas,text='时长:00:00:00', font=("华文行楷", 15), background='#DAEFE6',bootstyle=DANGER)
        time_label.place(x=730,y=50)
        start_time = datetime.datetime.now()
        def run():
            if self.flag:
                time_label.after(1000, run)
                update_time = datetime.datetime.now() - start_time
                self.time_ =f'时长:{update_time}'.split('.')[0]
                time_label.configure(text=self.time_) # 不显示时长的毫秒值
        run()

if __name__ == '__main__':
    guessIdiomsFromPictures()

3)效果展示

游戏界面——

随机截图——

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们