python就是玩具_python玩具——pygame扫雷

**其实扫雷说是使用pygame写游戏,但其实这非常锻炼思维,一个编程与解决问题的思路的养成非常重要,这篇文章的主要内容不是讲解功能的实现方式,而是介绍我遇到的一些问题**

我自己的界面设计的能力有点差,所以在界面设计部分我借鉴了《python写扫雷小游戏(pygame)》—— 在校学渣一枚这位朋友的,再次表示十分感谢

好了,闲言少叙,一部分一部分的上

这个扫雷的主要实现思路就是用pygame划出格子后,界面上格子的行数列数,与另外一个二维列表的对应关系。

1. 难度选择界面

import pygame

import sys

import main_game

from pygame.locals import *

#初始化模块

pygame.init()

pygame.mixer.init()

#音效加载

button_sound = pygame.mixer.Sound('material/sound/button.wav')

button_sound.set_volume(0.2)

background_sound = pygame.mixer.music.load('material/sound/background.ogg')

pygame.mixer.music.set_volume(0.3)

sys.setrecursionlimit(2000)

#画出主界面

def draw_choose_interface(level):

#level为难度等级,prompt为显示界面所显示的文字

bg_size = width,height = 450,700

screen = pygame.display.set_mode(bg_size)

screen.fill((237,237,237))

#画出选择框

pygame.draw.rect(screen,(0,0,0),[175,100,100,300],5)

#分割出三部分存放+,-和等级的位置

pygame.draw.line(screen,(0,0,0),(175,200),(275,200),5)

pygame.draw.line(screen,(0,0,0),(175,300),(275,300),5)

#画出+的横线以及-

pygame.draw.line(screen,(0,0,0),(195,150),(255,150),20)

pygame.draw.line(screen,(0,0,0),(195,350),(255,350),20)

#画出+的竖线

pygame.draw.line(screen,(0,0,0),(225,120),(225,180),20)

#开始游戏的选择框

pygame.draw.rect(screen,(0,0,0),[100,450,250,100],5)

#定义字体跟大小

s_font1=pygame.font.Font('material/benmoyouyuan.ttf',50)

s_font2=pygame.font.Font('material/benmoyouyuan.ttf',16)

s_font3=pygame.font.Font('material/benmoyouyuan.ttf',34)

#文本确定

s_text1=s_font1.render(str(level),True,(0,0,0))

s_text2=s_font1.render("开始游戏",True,(0,0,0))

s_text3=s_font2.render('Listening_Rift',True,(0,0,0))

s_text4=s_font3.render('难度选择:',True,(255,0,0))

#将字放在窗口指定位置

screen.blit(s_text1,(200,220))

screen.blit(s_text2,(120,470))

screen.blit(s_text3,(22,650))

screen.blit(s_text4,(100,50))

pygame.display.set_caption('难度选择')

pygame.display.flip()

def _interface():

level = '低'

pygame.mixer.music.play(-1)

draw_choose_interface(level)

while True:

for event in pygame.event.get():

if event.type == QUIT:

pygame.quit()

sys.exit()

elif event.type == MOUSEBUTTONDOWN:

if event.button == 1:

if 175

if level == '低':

level = '中'

button_sound.play()

draw_choose_interface(level)

elif level == '中':

level = '高'

button_sound.play()

draw_choose_interface(level)

elif level == '高':

level = '低'

button_sound.play()

draw_choose_interface(level)

elif 175

if level == '高':

level = '中'

button_sound.play()

draw_choose_interface(level)

elif level == '中':

level = '低'

button_sound.play()

draw_choose_interface(level)

elif level == '低':

level = '高'

button_sound.play()

draw_choose_interface(level)

elif 100

button_sound.play()

main_game.game_main(level)

if __name__ == '__main__':

_interface()

这部分其实就主要是界面的绘制以及事件的确定,本身没有什么难度,都是一些简单的用法,整体在不到100行,这也是扫雷游戏的登入部分。

2. 接下来就要将整个游戏分块考虑并且编写,首先我把布雷部分写出来,这部分并不是很难,甚至可以说是最简单的,我是个初学者,五六十行就可以实现。

import random

def lay_mines(level,map1):

if level == '低':

a = 0

while a<10:

x = random.randint(0,9)

y = random.randint(0,9)

map1[x][y] = '9'

print('布雷功能运行正常')

a = 0

for i in range(10):

for j in range(10):

if map1[i][j] == '9':

a += 1

print(a)

elif level == '中':

a = 0

while a<40:

x = random.randint(0,15)

y = random.randint(0,15)

map1[x][y] = '9'

print('布雷功能运行正常')

a = 0

for i in range(16):

for j in range(16):

if map1[i][j] == '9':

a += 1

print(a)

elif level == '高':

a = 0

while a<99:

x = random.randint(0,31)

y = random.randint(0,15)

map1[x][y] = '9'

print('布雷功能运行正常')

a = 0

for i in range(32):

for j in range(16):

if map1[i][j] == '9':

a += 1

print(a)

布雷的部分实际上就是分等级并排出不同数量的雷

这里我遇到最大的问题就是“a = 0” 这一句,这里是想通过一个遍历的方法,数出十个雷,确保没有重复,但实际上random好像是有这个函数的,但是也有一定bug,还是要通过一些方法规避,如果没有这一句的话,a实际上是一个类加量,并不会真正布十个雷,初级4个,中级9个,高级14个,所以在计算之前一定要将其初始化为0

3. 点开事件

在扫雷游戏中,我们在点到一个非雷格子的时候,有的会出现数字有的会直接点开一片,在明确这个规则之后,我们就可以开始编写了

import pygame

import main_game

from pygame.locals import *

pygame.mixer.init()

boom_sound = pygame.mixer.Sound('material/sound/BOOM.wav')

boom_sound.set_volume(0.2)

#比较得出数字

def _digital(i,j,map1):

count = 0

if i-1>=0 and j-1>=0 and map1[i-1][j-1] == '9':

count += 1

if i-1>=0 and map1[i-1][j] == '9':

count += 1

if i-1>=0 and j+1

count += 1

if j-1>=0 and map1[i][j-1] == '9':

count += 1

if j+1

count += 1

if i+1=0 and map1[i+1][j-1] == '9':

count += 1

if i+1

count += 1

if i+1

count += 1

return count

#周围判断

def arround(screen,i,j,map1,map2):

if map1[i][j] == '9':

omine_image = pygame.image.load('material/picture/mine.gif').convert()

mine_image = pygame.transform.scale(omine_image,(22,22))

screen.blit(mine_image,(i*30+3,j*30+3))

boom_sound.play()

pygame.display.flip()

for x in range(len(map1)):

for y in range(len(map1[0])):

if map1[x][y] == '9':

screen.blit(mine_image,(x*30+3,y*30+3))

pygame.display.flip()

pygame.time.delay(100)

result = '游戏失败'

pygame.time.delay(1000)

main_game.result_screen(result)

#显示lose

else:

digital = _digital(i,j,map1)

map1[i][j] = str(digital)

print('内容填写部分正常')

if map1[i][j] == '0':

print('判断成功')

map1[i][j] = ' '

if i-1>=0 and j-1>=0 and len(map1[i-1][j-1]) == 0 and map2[i-1][j-1] == '':

arround(screen,i-1,j-1,map1,map2)

if i-1>=0 and len(map1[i-1][j]) == 0 and map2[i-1][j] == '':

arround(screen,i-1,j,map1,map2)

if i-1>=0 and j+1

arround(screen,i-1,j+1,map1,map2)

if j-1>=0 and len(map1[i][j-1]) == 0 and map2[i][j-1] == '':

arround(screen,i,j-1,map1,map2)

if j+1

arround(screen,i,j+1,map1,map2)

if i+1=0 and len(map1[i+1][j-1]) == 0 and map2[i+1][j-1] == '':

arround(screen,i+1,j-1,map1,map2)

if i+1

arround(screen,i+1,j,map1,map2)

if i+1

arround(screen,i+1,j+1,map1,map2)

s_font = pygame.font.Font('material/benmoyouyuan.ttf',19)

if map1[i][j] == '1':

color = (86,98,166)

elif map1[i][j] == '2':

color = (67,106,62)

elif map1[i][j] == '3':

color = (15,170,209)

else:

color = (222,29,90)

s_text = s_font.render(str(map1[i][j]),True,color)

#将字放在窗口指定位置

screen.blit(s_text,(i*30+9,j*30+3))

#将为零的格子填充为新颜色

for i in range(len(map1)):

for j in range(len(map1[0])):

if map1[i][j] == ' ':

pygame.draw.rect(screen,(200,200,200),[i*30,j*30,29,29])

靠通过审查周围雷的数量填入数字,如果为零就计算他周围的进行循环计算,这样就可以实现点开一大片。

问题:

- [ ] a、最初,当计算周围的时候在周围的两个空格子无限死循环下去。**解决方法:将为零的格子转换为空格,只计算内部内容有长度的格子。**

- [ ] b、但是,之后发现int变量是没有长度的,**就只好将所有的内容全部变为字符串,原本用9表示雷,现在则用'9'表示。**

这个部分实际上最重要的就是判断标准的确定,需要仔细地进行思考。

4. 主体游戏

好吧,我承认我的架构思路确实略有问题,原本是想把不同部分分开的后来在调试优化过程中,就逐渐的加到一起了。。。

import pygame

import traceback

import sys

import random

import choose

import lay_mines

import open_event

from pygame.locals import *

#9代表雷

#10代表旗帜

sys.setrecursionlimit(1000)

#板块初始化

pygame.init()

#音效载入,背景音乐,点击音效,爆炸音效,音量均为0.2

pygame.mixer.init()

button_sound = pygame.mixer.Sound('material/sound/button.wav')

button_sound.set_volume(0.2)

boom_sound = pygame.mixer.Sound('material/sound/BOOM.wav')

boom_sound.set_volume(0.2)

background_sound = pygame.mixer.music.load('material/sound/background.ogg')

pygame.mixer.music.set_volume(0.2)

#判定结果

def result_judge(map1,map2):

mine = []

flag = []

for x in range(len(map1)):

for y in range(len(map1[0])):

if map1[x][y] == '9':

mine.append((x,y))

if map2[x][y] == '10':

flag.append((x,y))

if mine == flag:

result = '游戏胜利'

else:

result = '游戏失败'

return result

def result_screen(result):

#建立界面

bg_size = width,height = 450,700

r_screen = pygame.display.set_mode(bg_size)

r_screen.fill((237,237,237))

r_font1 = pygame.font.Font('material/benmoyouyuan.ttf',67)

r_font2 = pygame.font.Font('material/benmoyouyuan.ttf',50)

pygame.draw.rect(r_screen,(0,0,0),[100,450,250,100],5)

r_text1 = r_font1.render(str(result),True,(0,0,0))

r_text2 = r_font2.render("继续游戏",True,(0,0,0))

r_screen.blit(r_text1,(90,100))

r_screen.blit(r_text2,(120,470))

pygame.display.set_caption('游戏结束')

pygame.display.flip()

while True:

for event in pygame.event.get():

if event.type == QUIT:

pygame.quit()

sys.exit()

elif event.type == MOUSEBUTTONDOWN:

if event.button == 1:

if 100

pygame.display.quit()

choose._interface()

def game_main(level):

#生成主界面

if level == '低':

bg_size = width,height = 300,300

elif level == '中':

bg_size = width,height = 480,480

elif level == '高':

bg_size = width,height = 960,480

screen_main = pygame.display.set_mode(bg_size)

screen_main.fill((237,237,237))

pygame.display.set_caption('L_R扫雷:%s级模式'%level)

pygame.mixer.music.play(-1)

#画格子

for x in range(width//30):

for y in range(height//30):

pygame.draw.rect(screen_main,(0,0,0),[x*30,y*30,29,29],1)

pygame.display.flip()

#初始化地图二维列表

if level == '低':

map1 = [[0 for col in range(10)] for row in range(10)]

map2 = [[0 for col in range(10)] for row in range(10)]

for i in range(10):

for j in range(10):

map1[i][j] = ''

map2[i][j] = ''

elif level == '中':

map1 = [[0 for col in range(16)] for row in range(16)]

map2 = [[0 for col in range(16)] for row in range(16)]

for i in range(16):

for j in range(16):

map1[i][j] = ''

map2[i][j] = ''

elif level == '高':

map1 = [[0 for col in range(16)] for row in range(32)]

map2 = [[0 for col in range(16)] for row in range(32)]

for i in range(32):

for j in range(16):

map1[i][j] = ''

map2[i][j] = ''

#布雷

lay_mines.lay_mines(level,map1)

while True:

for event in pygame.event.get():

if event.type == QUIT:

pygame.quit()

sys.exit()

elif event.type == MOUSEBUTTONDOWN:

if event.button == 1:

button_sound.play()

i = event.pos[0]//30

j = event.pos[1]//30

if (map1[i][j] == '' or map1[i][j] == '9') and map2[i][j] == '':

open_event.arround(screen_main,i,j,map1,map2)

print('翻开成功')

pygame.display.flip()

elif event.button == 3:

button_sound.play()

i = event.pos[0]//30

j = event.pos[1]//30

if (map1[i][j] == '' or map1[i][j] == '9') and map2[i][j] == '':

map2[i][j] = '10'

oflag = pygame.image.load('material/picture/flag.gif')

flag = pygame.transform.scale(oflag,(22,22))

screen_main.blit(flag,(i*30+3,j*30+3))

print('标记成功')

pygame.display.flip()

elif (map1[i][j] == '' or map1[i][j] == '9') and map2[i][j] == '10':

map2[i][j] = ''

print('取消标记')

oblank = pygame.image.load('material/picture/blank.gif')

flag = pygame.transform.scale(oblank,(22,22))

screen_main.blit(flag,(i*30+3,j*30+3))

pygame.display.flip()

if level == '低':

mines = 10

elif level == '中':

mines = 40

elif level == '高':

mines = 99

flags = 0

for x in range(len(map2)):

for y in range(len(map2[0])):

if map2[x][y] == '10':

flags += 1

if flags == mines:

result = result_judge(map1,map2)

pygame.time.delay(1000)

result_screen(result)

游戏主体部分包含胜负判断

最大的问题在于、标记时会影响判断,最一开始的标记是把二维列表中的值改编为10就会影响每个格子里的值,所以后来我又建立了另一张二维列表,专门存放旗子,这样就可以将他标记完成并不影响值。

最终还想实现战绩记录,每个模式的最短时间,以及胜率。这个部分连上界面优化就比较简单了,所以就日后慢慢进行吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值