用python写扫雷游戏

这篇具有很好参考价值的文章主要介绍了用python写扫雷游戏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

# -*- coding: utf-8 -*-
# __/author__by:Kevin_F/__
import tkinter.messagebox
import random
import time
import pygame
import tkinter
import tkinter.messagebox
num_w = 30  # 横向格子数
num_h = 16  # 竖向格子数


#  界面初始化
def window_init():
    pygame.init()
    global window
    #  格子尺寸30*30,状态栏高度100,上下左右边界20
    window = pygame.display.set_mode((30 * num_w + 20 * 2, 100 + 30 * num_h + 2 * 40))
    pygame.display.set_caption('扫雷xp')
    window.fill((128, 138, 135))  # 背景色:冷灰
    pygame.draw.rect(window, (192, 192, 192), (0, 0, 30 * num_w + 20 * 2, 100))  # 最上面状态框

    for j in range(num_h):
        for i in range(num_w):
            #  格子坐标
            block_x = 20 + i * 30
            block_y = 100 + 20 + j * 30
            list_block.append([block_x, block_y, 0, 0])
            list_block_pos.append((block_x, block_y))
            """
            list_temp生成存放每一行中格子的坐标信息
            block_x:格子的x坐标
            block_y:格子的y坐标 (坐标信息是固定不可修改的,所以用元组表示)
            0:定义此格子是否是雷  是雷:-1  不是雷:表示周边相邻非雷格子的数量,先写入默认值为0
            0:定义格子的标记状态  0-未标记,即初始值  1-标记是雷  2-标记问号 3-左击点开
            """

            pygame.draw.rect(window, (192, 192, 192), (block_x, block_y, 30, 30), 0)  # 实心格子
            pygame.draw.rect(window, (220, 220, 220), (block_x, block_y, 30, 30), 2)  # 格子边线

    pygame.display.flip()


#  状态栏 雷剩余数
def bomb_les():
    global count_bomb
    if count_bomb < 0:
        count_bomb = 0
    #  不存在标记雷超过99的可能,因为未标记的状态只有先标记成雷-1,再右键取消标记雷+1
    pygame.draw.rect(window, (192, 192, 192), (0, 0, 150, 100), 0)
    font_bomb_num = pygame.font.SysFont('Microsoft YaHei', 60, bold=True)
    bomb_num = font_bomb_num.render(str(count_bomb), True, (255, 0, 0))
    window.blit(bomb_num, (20, 10))
    pygame.display.update()


#  状态栏 状态显示
def game_status(status):
    img_working = pygame.image.load('me.png')
    img_bad = pygame.image.load('yc.png')
    img_win = pygame.image.load('yes.png')
    if status == 'working':  # 游戏开始时的图片
        window.blit(img_working, (15 * num_w + 20 - 45, 5))
    elif status == 'loose':  # 游戏失败的图片
        window.blit(img_bad, (15 * num_w + 20 - 45, 5))
    elif status == 'win':  # 游戏胜利的图片
        window.blit(img_win, (15 * num_w + 20 - 45, 5))
    else:
        pass
    pygame.display.update()


#  游戏初始化(随机生成a颗雷,初始化每个格子的位置信息,状态信息)
def game_init():
    #  随机生成99颗地雷
    a = random.randint(10, 100)
    global list_bomb_pos
    list_bomb_pos = random.sample(list_block_pos, a)
    #  从所有格子中取不重复的99个,即得到99个位置坐标(x,y),组成的列表即是所有雷的坐标列表

    #  改写list_block中格子的第三个值 从0改成-1 即表示是雷
    for i in range(len(list_bomb_pos)):
        for j in range(len(list_block)):
            if list_block[j][0] == list_bomb_pos[i][0] and list_block[j][1] == list_bomb_pos[i][1]:
                list_block[j][2] = -1

    #  不是雷的格子,要计算出格子周边的雷数,并写入list_block
    for index in range(len(list_block)):
        # index为list_block的下标
        x = index % 30
        y = index // 30
        if list_block[index][2] == -1:
            continue
        else:
            list_beside = list_side(x, y)

            mark_num = 0  # 定义一个变量,用于存放此格子周边是雷的格子的个数
            for element in list_beside:
                if element[2] == -1:
                    mark_num += 1
            list_block[index][2] = mark_num  # 将周边雷的个数写入list_block中的第三个值

    #  初始化一个列表,用于存放不是雷的格子的坐标
    for i in list_block_pos:
        if i not in list_bomb_pos:
            list_not_bomb.append(i)


#  获得一个存放此格子周边相邻格子组成的列表(定义此函数返回值就是这个列表)
def list_side(x, y):
    if 1 <= x <= 28 and 1 <= y <= 14:
        list_side = [
            list_block[x - 1 + (y - 1) * 30],
            list_block[x + (y - 1) * 30],
            list_block[x + 1 + (y - 1) * 30],
            list_block[x - 1 + y * 30],
            list_block[x + 1 + y * 30],
            list_block[x - 1 + (y + 1) * 30],
            list_block[x + (y + 1) * 30],
            list_block[x + 1 + (y + 1) * 30]
        ]
    elif x == 0 and 1 <= y <= 14:
        list_side = [
            list_block[(y - 1) * 30],
            list_block[1 + (y - 1) * 30],
            list_block[1 + y * 30],
            list_block[(y + 1) * 30],
            list_block[1 + (y + 1) * 30]
        ]
    elif x == 29 and 1 <= y <= 14:
        list_side = [
            list_block[28 + (y - 1) * 30],
            list_block[29 + (y - 1) * 30],
            list_block[28 + y * 30],
            list_block[28 + (y + 1) * 30],
            list_block[29 + (y + 1) * 30]
        ]
    elif 1 <= x <= 28 and y == 0:
        list_side = [
            list_block[x - 1 + y * 30],
            list_block[x + 1 + y * 30],
            list_block[x - 1 + (y + 1) * 30],
            list_block[x + (y + 1) * 30],
            list_block[x + 1 + (y + 1) * 30]
        ]
    elif 1 <= x <= 28 and y == 15:
        list_side = [
            list_block[x - 1 + (y - 1) * 30],
            list_block[x + (y - 1) * 30],
            list_block[x + 1 + (y - 1) * 30],
            list_block[x - 1 + y * 30],
            list_block[x + 1 + y * 30]
        ]
    elif x == 0 and y == 0:
        list_side = [list_block[1], list_block[30], list_block[31]]
    elif x == 0 and y == 15:
        list_side = [list_block[420], list_block[421], list_block[451]]
    elif x == 29 and y == 0:
        list_side = [list_block[28], list_block[58], list_block[59]]
    else:
        list_side = [list_block[448], list_block[449], list_block[478]]

    return list_side


#  绘制鼠标点击后的格子
def draw_block(para, x, y):
    if para == 0:  # 此格子周围格子都不是雷,此格子直接画个实心方块
        pygame.draw.rect(window, (180, 180, 180), (x * 30 + 20, y * 30 + 120, 30, 30), 0)
    elif para in [1, 2, 3, 4, 5, 6, 7, 8]:  # 此格子周围有雷,显示周围雷的数量
        colors = {
            1: (0, 0, 255),
            2: (34, 139, 34),
            3: (25, 25, 112),
            4: (160, 32, 240),
            5: (94, 38, 18),
            6: (199, 97, 20),
            7: (240, 230, 140),
            8: (240, 230, 140)
        }
        num_font = pygame.font.SysFont('SimHei', 24, bold=True)
        text_num = num_font.render(str(para), True, colors[para])
        w1, h1 = text_num.get_size()
        window.blit(text_num, (x * 30 + 35 - w1 / 2, y * 30 + 135 - h1 / 2))
    elif para == 'bomb':  # 左键点击到雷的时候,地雷爆炸(变红色)
        pygame.draw.circle(window, (0, 0, 0), (x * 30 + 35, y * 30 + 135), 12)

    elif para == 'mark':  # 右键标记为雷时,画个红色实心圆表示地雷
        pygame.draw.rect(window, (192, 192, 192), (x * 30 + 20, y * 30 + 120, 30, 30), 0)  # 实心格子
        pygame.draw.rect(window, (220, 220, 220), (x * 30 + 20, y * 30 + 120, 30, 30), 2)  # 格子边线
        pygame.draw.circle(window, (255, 0, 0), (x * 30 + 35, y * 30 + 135), 11)
    elif para == '?':  # 右键标记?,格子上显示?
        num_font = pygame.font.SysFont('SimHei', 24)
        text_num = num_font.render('?', True, (255, 0, 0))
        w1, h1 = text_num.get_size()
        pygame.draw.rect(window, (192, 192, 192), (x * 30 + 20, y * 30 + 120, 30, 30), 0)  # 实心格子
        pygame.draw.rect(window, (220, 220, 220), (x * 30 + 20, y * 30 + 120, 30, 30), 2)  # 格子边线
        window.blit(text_num, (x * 30 + 35 - w1 / 2, y * 30 + 135 - h1 / 2))
    elif para == 'blank':  # 右键切换成未标记状态时,画为初始化时的格子
        pygame.draw.rect(window, (192, 192, 192), (x * 30 + 20, y * 30 + 120, 30, 30), 0)  # 实心格子
        pygame.draw.rect(window, (220, 220, 220), (x * 30 + 20, y * 30 + 120, 30, 30), 2)  # 格子边线
    else:
        pass
    pygame.display.update()


#  扫雷区鼠标左击事件
def mouse_click_left(mouse_x, mouse_y):
    global list_block, is_loose, count_click
    pos_x = (mouse_x - 20) // 30
    pos_y = (mouse_y - 120) // 30
    index = pos_x + pos_y * 30  # list_block的下标index

    #  触发了此位置的左击事件,要先把此位置的左击事件表达出来

    if list_block[index][3] == 3:  # 如果这个格子已经被左击点开过,则不能重复点击
        pass
    else:
        #  先判断点击是否是雷 ,如果是雷,游戏失败
        if list_block[index][2] == -1:  # 鼠标左击 是雷  游戏失败
            is_loose = True
            for x, y in list_bomb_pos:
                draw_block('bomb', (x - 20) // 30, (y - 120) // 30)
            #  把当前点击的这个雷标成红色
            pygame.draw.rect(window, (255, 0, 0), (20 + pos_x * 30, 120 + pos_y * 30, 30, 30), 0)
            draw_block('bomb', pos_x, pos_y)
            game_status('loose')
            #  游戏已经失败,这个时候再点击扫雷区,无效
            #  计时停止
        else:
            #  不是雷的情况下,再判断这个格子是否是周边雷数为0 ,如果为0 ,则要继续触发左击点开该格子周围8个格子
            #  除了画出当前位置的左击事件,还需要判断当前周边雷数是否为0
            #  如果为0,自动触发此格子周边8个相邻格子的左击事件(因为0 代表周边8个格子都不是雷,直接自动左击显示出这8个格子每一个的周边雷数)
            #  如果这8个格子中还有周边雷数为0的,则递归调用函数
            if list_block[index][2] == 0:
                draw_block(list_block[index][2], pos_x, pos_y)
                list_block[index][3] = 3

                list_beside = list_side(pos_x, pos_y)
                for i in list_beside:
                    x = (i[0] - 20) // 30
                    y = (i[1] - 120) // 30
                    if list_block[x + 30 * y][3] == 0:  # 判断此位置的标记状态(list_block里的最后一个参数),0-未标记
                        mouse_click_left(x * 30 + 20, y * 30 + 120)  # 调用函数
                        draw_block(list_block[x + 30 * y][2], x, y)  # 画出左击后的图形
                        list_block[x + 30 * y][3] = 3  # 调用函数,即说明发生左击(即使是电脑自动触发,而非人为操作),更改标记状态为3


            else:  # 该格子周边雷数不为0,直接显示该格子的周边雷数
                draw_block(list_block[index][2], pos_x, pos_y)
                list_block[index][3] = 3

    count_click = 0
    for i in list_block:
        if i[3] == 3:
            count_click += 1
    #  每次触发鼠标左击事件后,都重新统计已经左击点开的格子个数
    #  为了后面判断如果点开的格子个数=非雷的格子总数,则游戏胜利


#  扫雷区鼠标右击事件
def mouse_click_right(mouse_x, mouse_y):
    global count_bomb
    pos_x = (mouse_x - 20) // 30
    pos_y = (mouse_y - 120) // 30
    index = pos_x + pos_y * 30  # list_block的下标index
    status = list_block[index][3]

    #  游戏结束,不能再右击
    if is_loose:
        import tkinter.messagebox
        tkinter.messagebox.showinfo('扫雷xp','你死了')
        # -*- conding:utf-8 -*-

        while True:
            # 检查音乐流播放,有返回True,没有返回False

            # 如果没有音乐流则选择播放
            if pygame.mixer.music.get_busy() == False:
                pygame.mixer.music.play()
    else:
        #  右击,格子显示状态在0-未标记 1-标记雷 2-标记? 三种状态之间循环切换
        if status == 0:  # 如果此格子当前处于未标记状态
            draw_block('mark', pos_x, pos_y)
            list_block[index][3] = 1
            count_bomb -= 1
        elif status == 1:
            draw_block('?', pos_x, pos_y)
            list_block[index][3] = 2
            count_bomb += 1
        elif status == 2:
            draw_block('blank', pos_x, pos_y)
            list_block[index][3] = 0
        else:
            #  已经左击点开的位置 不能在右击(即status=3的情况)
            pass


#  扫雷区鼠标中键事件
def mouse_click_mid(mouse_x, mouse_y):
    #  鼠标中键该格子,表示扫描该格子周边相邻格子
    #  该格子只有被左击点开(list_block[index][3]==3),且该格子周边雷数(list_block[index][2])=标记雷的总个数
    #  中键触发自动左键点开周边非雷的格子(之前没有左击点开过 ),如果之前左击点开过,则跳过

    pos_x = (mouse_x - 20) // 30
    pos_y = (mouse_y - 120) // 30
    index = pos_x + pos_y * 30  # list_block的下标index
    status = list_block[index][3]

    list_beside = list_side(pos_x, pos_y)
    mark_bomb_sum = 0
    for item in list_beside:
        if item[3] == 1:  # item[3]即相当于list_block[index][3]  如果该值为1 表示标记是雷
            mark_bomb_sum += 1

    if list_block[index][3] == 3 and list_block[index][2] == mark_bomb_sum and list_block[index][2] != 0:
        #  该格子只有被左击点开(list_block[index][3]==3),且该格子周边雷数(list_block[index][2])=标记雷的总个数,且不等于0
        for item in list_beside:
            #  中键触发自动左键点开周边非雷的格子(之前没有左击点开过 ),如果之前左击点开过,则跳过
            if item[3] == 3 or item[3] == 1 or item[3] == 2:
                #  状态是3,表示左击点开过,状态为1 ,表示标记是雷,状态为2,表示疑问,这三种情况都不能触发鼠标左击事件
                continue
            else:
                mouse_click_left(item[0], item[1])


def main():
    global is_loose, list_block, list_block_pos, list_bomb_pos, list_not_bomb, count_click, count_bomb, num_not_bomb, t_start
    list_block_pos = []  # 用于存放每个格子的位置坐标信息(x,y)
    list_block = []  # 用于存放每个格子的坐标和状态信息,即每个元素=[x,y,0,0]
    list_bomb_pos = []  # 用于存放雷的元素的坐标
    list_not_bomb = []  # 用于存放不是雷的格子的坐标
    count_click = 0  # 用于记录左击点开的格子数量

    window_init()
    game_status('working')
    game_init()

    is_loose = False
    num_not_bomb = len(list_block_pos) - len(list_bomb_pos)
    count_bomb = len(list_bomb_pos)

    while True:


        bomb_les()

        if 0 <= count_click < num_not_bomb and not is_loose:
            if count_click == 0:
                t_start = int(time.time())
                #  在while True循环内,如果count_click=0,表示没有鼠标左击,此时不计时
                #  此时,因为while True一直循环,所以会一直刷新t_start的值,不断获取当前时间

            #  当count_click从1开始,即一旦发生左击点击,上面if条件 count_click==0不成立,则不会再刷新t_start的值
            #  t_start的值固定在count_click=1前上一次循环的值,即左击点击之前的最后的一次循环的值,从而实现左击开始计时
            t_show = int(time.time()) - t_start
            pygame.draw.rect(window, (192, 192, 192), (720, 0, 200, 100), 0)
            font_time = pygame.font.SysFont('Microsoft YaHei', 60, bold=True)
            text_time = font_time.render(str(t_show), True, (255, 0, 0))
            window.blit(text_time, (920 - text_time.get_size()[0], 10))  # 时间靠右显示
            pygame.display.update()
        else:  # 如果游戏成功(count_click = num_not_bomb) 或者游戏失败(is_loose=True) 都停止时间显示
            # !/usr/bin/python
            # -*- coding: UTF-8 -*-

            # Python2.x 导入方法

            # Python3.x 导入方法
            # from tkinter import *
            pass
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if is_loose:
                    game_status('loose')
                    continue
                elif count_click < num_not_bomb:
                    mouse_x, mouse_y = pygame.mouse.get_pos()
                    click = pygame.mouse.get_pressed()
                    if 20 <= mouse_x <= 920 and 120 <= mouse_y <= 600:
                        if click == (True, False, False):  # 鼠标左击
                            mouse_click_left(mouse_x, mouse_y)
                        elif click == (False, True, False):  # 鼠标中键
                            mouse_click_mid(mouse_x, mouse_y)
                        elif click == (False, False, True):  # 鼠标右键
                            mouse_click_right(mouse_x, mouse_y)
                else:  # 当count_click == num_not_bomb,则说明所有非雷的格子全部被点开,游戏胜利
                    game_status('win')
            elif event.type == pygame.MOUSEBUTTONUP:
                mouse_x1, mouse_y1 = pygame.mouse.get_pos()
                if 0 <= mouse_x1 - (15 * num_w + 20 - 45) <= 90 and 10 <= mouse_y1 <= 100:
                    #  鼠标在状态图标位置左击点击时,表示游戏开始
                    return main()  # 游戏开始或者游戏重新开始
if __name__ == '__main__':
    import tkinter
    import PySimpleGUI as sg

    count = range(100)
    for i, item in enumerate(count):
        sg.one_line_progress_meter('扫雷xp', i + 1, len(count), '扫雷xp进度')

        # 假设这代码部分需要0.05s
        time.sleep(0.000001)



    main()

有图和pygame就行

图片:

python扫雷游戏代码,python pygame,pygame,python,游戏

 

python扫雷游戏代码,python pygame,pygame,python,游戏

 

python扫雷游戏代码,python pygame,pygame,python,游戏

 

运行截图:

python扫雷游戏代码,python pygame,pygame,python,游戏

python扫雷游戏代码,python pygame,pygame,python,游戏文章来源地址https://www.toymoban.com/news/detail-764202.html

到了这里,关于用python写扫雷游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python版经典小游戏愤怒的小鸟源代码,基于pygame+pymunk

    Python版经典小游戏愤怒的小鸟源代码,基于pygame+pymunk 程序依赖:pygame 2.0.1, pymunk 5.5.0 直接运行main.py 完整代码下载地址:Python版经典小游戏愤怒的小鸟源代码 tool.py 完整代码下载地址:Python版经典小游戏愤怒的小鸟源代码

    2024年02月16日
    浏览(57)
  • 用matlab写一个扫雷游戏代码

    首先,我们需要初始化一个矩阵来代表游戏的地图。在这个地图中,零代表空地,而数字代表周围有几个地雷。 然后,我们可以使用鼠标点击矩阵中的某个位置。如果点击的是零,我们可以在该位置上显示数字;如果点击的是数字,我们就可以显示该数字;如果点击的是地雷

    2024年02月16日
    浏览(31)
  • 【C语言】扫雷游戏完整代码实现

    目录 1.game.h 2.game.c 3.progress.c 4.运行结果

    2024年02月21日
    浏览(45)
  • Python小游戏——扫雷

    用Python做一个传统的扫雷游戏。 游戏界面和操作 游戏界面:一系列游戏图标 + 时间和剩余旗子数 + (背景音乐)。 操作:开始游戏 / 重新开始游戏 + 退出游戏 + 打开格子 + 标记格子 + 显示格子信息。 游戏状态转化逻辑、游戏赢输规则和游戏界面和事件检测在主程序(main.py

    2024年02月10日
    浏览(45)
  • 用python写扫雷游戏

    有图和pygame就行 图片:       运行截图:

    2024年02月04日
    浏览(30)
  • Python游戏:扫雷 (附源码)

    这次我们基于 pygame 来做一个扫雷,我所有的代码都是基于 python 3.6 的。 下面将一下我的实现逻辑 首先,如何表示雷和非雷,一开始有好多状态,后来一想,干脆就做个类吧。 布雷就很简单了,随机取99个数,从上往下顺序排   点击一个格子的时候,只要根据点击的坐标,

    2024年02月11日
    浏览(31)
  • 打地鼠游戏编程代码,pygame打地鼠游戏代码

    大家好,小编来为大家解答以下问题,打地鼠游戏编程代码,pygame打地鼠游戏代码,今天让我们一起来看看吧! 文章目录 0 项目简介 1 游戏介绍 2 实现效果 3 开发工具 3.1 环境配置 3.2 Pygame介绍 4 具体实现 4.1 实现游戏精灵类 4.2 实现游戏主循环 4.3 制作简易的游戏开始和结束

    2024年01月25日
    浏览(43)
  • C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

    大家好,今天我们将一起用C语言实现一个经典小游戏 – 扫雷,Let is go ! 扫雷游戏相信大家都玩过,上图就是一个网页版的扫雷,它的规则是玩家选择一个方格,若此方格没有地雷,那么该方格会显示与它相邻的八个方格中雷的个数,若此方格有地雷,那么游戏失败,当玩

    2024年02月05日
    浏览(55)
  • 【C语言】代码实现 扫雷 游戏及进阶功能(初学者详解)

    扫雷游戏的起源可以追溯到20世纪60年代,当时这款游戏是由IBM开发出来的。在80年代初,微软公司将其收归旗下,并将其作为Windows操作系统自带的一款游戏。自此以后,扫雷成为了Windows用户最喜欢的休闲游戏之一,也受到了全球范围内的玩家喜爱。 现在,我们使用C语言,来

    2024年01月20日
    浏览(48)
  • 【Pygame实战】变异狗大战:据说是最近还不错的小游戏,这一个个玩到表情崩坏,点开即玩,赶紧来~(Python代码搞笑版本)

    只有你想不到,没有我找不到写不了的好游戏! 哈喽。我是你们的栗子同学啦~ 粉丝白嫖源码福利,请移步至CSDN社区或文末公众hao即可免费。 今天小编去了我朋友家里玩儿,看到了一个敲可爱的小狗狗🐏,是我朋友养的萨摩耶啦。 心里羡慕一下下蛮。嘿嘿,但是我养肯定养

    2024年02月11日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包