python项目事件——pygame扫雷

项目地址:https://github.com/ListeningRift/Minesweeper

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

我自己的界面设计的能力有点差,所以在界面设计部分我借鉴了《python写扫雷小游戏(pygame)》—— 在校学渣一枚这位朋友的,再次表示十分感谢
原文:https://blog.csdn.net/qq_42847252/article/details/83153696

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

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

  1. 难度选择界面
    python项目事件——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

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

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

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

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=0 and map1[i][j-1] == '9':
		count += 1
	if j+1=0 and map1[i+1][j-1] == '9':
		count += 1
	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=0 and len(map1[i][j-1]) == 0 and map2[i][j-1] == '':
				arround(screen,i,j-1,map1,map2)
			if 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

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

  • a、最初,当计算周围的时候在周围的两个空格子无限死循环下去。解决方法:将为零的格子转换为空格,只计算内部内容有长度的格子。
  • b、但是,之后发现int变量是没有长度的,就只好将所有的内容全部变为字符串,原本用9表示雷,现在则用’9’表示。

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

  1. 主体游戏
    好吧,我承认我的架构思路确实略有问题,原本是想把不同部分分开的后来在调试优化过程中,就逐渐的加到一起了。。。
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

python项目事件——pygame扫雷_第2张图片
游戏主体部分包含胜负判断
最大的问题在于、标记时会影响判断,最一开始的标记是把二维列表中的值改编为10就会影响每个格子里的值,所以后来我又建立了另一张二维列表,专门存放旗子,这样就可以将他标记完成并不影响值。

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

你可能感兴趣的:(Python学习)