import pygame,sys,random
from pygame.locals import *
# 默认窗口大小
windowWidth = 800
windowHeight = 800
#默认方格大小
rectSize = 39
#颜色常量
fontColor = pygame.Color("red")
inputBoxColor = pygame.Color("white")
backgroundColor = pygame.Color("black")
defaultColor = pygame.Color("gray")
promptColor = pygame.Color("pink")
warningColor = pygame.Color("red")
safeColor = pygame.Color("green")
#常量字符串
captionString = "扫雷游戏"
welcomeString = "请输入扫雷的宽,高,和雷的数量,用','将不同数据隔开"
failureString = "你踩到了雷,GAME OVER,按ENTER返回开始界面"
successString = "你已找出所有雷,游戏通关,按ENTER返回开始界面"
#输入框常量
inputSurfaceWidth = 600
#最大值限制
MaxNum = 20
#初始化
pygame.init()
#宽和高 雷的数量
width = 0
height = 0
mineNum = 0
# 初始化面板
screen = pygame.display.set_mode((windowWidth, windowHeight))
initSurface = pygame.Surface((windowWidth, windowHeight), flags=pygame.HWSURFACE)
pygame.display.set_caption(captionString)
# 游戏状态 0为欢迎界面,1为游戏界面,2为失败结束界面,3为成功结束界面
mode = 0
# 字体管理
font = pygame.font.SysFont("华文楷体", size=30, bold=True)
inputFont = pygame.font.SysFont("华文楷体", size=30, bold=False)
welcome = font.render(welcomeString, True, fontColor, backgroundColor)
failure = font.render(failureString, True, fontColor, backgroundColor)
success = font.render(successString, True, fontColor, backgroundColor)
# 获得渲染后的rect
welcome_rect = welcome.get_rect()
failure_rect = failure.get_rect()
success_rect = success.get_rect()
# rect居中
welcome_rect.center = (windowWidth // 2, windowHeight // 2)
failure_rect.center = (windowWidth // 2, windowHeight // 2)
success_rect.center = (windowWidth // 2, windowHeight // 2)
#输入框
inputSurface = pygame.Surface((inputSurfaceWidth, welcome_rect.height), flags=pygame.HWSURFACE)
inputSurface.fill(color = inputBoxColor)
#算的是左上角坐标
inputSurfacePos = (windowWidth // 2 - inputSurfaceWidth // 2, windowHeight // 2 - welcome_rect.height // 2 - welcome_rect.height)
inputText = ""
hintText = ""
#基础面板常量 默认展现的方块
defaultRect = pygame.Surface((rectSize, rectSize), flags=pygame.HWSURFACE)
defaultRect.fill(color = defaultColor)
#被标记为雷的方块
warningRect = pygame.Surface((rectSize, rectSize), flags=pygame.HWSURFACE)
warningRect.fill(color = warningColor)
resultRect = [0] * 10
#数量为0的贴图
resultRect[0] = pygame.Surface((rectSize, rectSize), flags=pygame.HWSURFACE)
resultRect[0].fill(color = safeColor)
#数量为1-9的贴图 所有展示为数字的方块必定已被确认为非雷
for i in range(9):
resultRect[i + 1] = pygame.Surface((rectSize, rectSize), flags=pygame.HWSURFACE)
resultRect[i + 1].fill(color = promptColor)
numPrompt = inputFont.render(str(i + 1), True, fontColor, promptColor)
numPromptRect = numPrompt.get_rect()
numPromptRect.center = ((rectSize + 1) // 2, (rectSize + 1) // 2)
resultRect[i + 1].blit(numPrompt, numPromptRect)
#关键全局变量
mineMap = {}
stateList = []#代表当前展示的状态 0为默认 1为被标记 2为已确认非雷
mineNumList = []
startPos = [0, 0]
changeMap = {}#代表当前展示的状态 0为默认 1为被标记 2为已确认非雷
init = False
#初始化雷的分布集合
def initMineMap():
global mineMap, mineNum
maxNum = height * width
for i in range(mineNum):
index = random.randrange(0, maxNum)
while index in mineMap:
index = random.randrange(0, maxNum)
mineMap[index] = 1
#初始化雷的分布数组
def initMineNumList():
global mineNumList,height,width
for index in range(height * width):
#计数时存在的情况 当位于四个角时
if index == 0:#左上角
mineNumList[0] = mineMap.get(0, 0) + mineMap.get(1, 0) + mineMap.get(width, 0) + mineMap.get(width + 1, 0)
elif index == width - 1:#右上角
mineNumList[width - 1] = mineMap.get(width - 2, 0) + mineMap.get(width - 1, 0) + mineMap.get(width * 2 - 2, 0) + mineMap.get(width * 2 - 1, 0)
elif index == width * (height - 1):#左下角
mineNumList[width * (height - 1)] = mineMap.get(width * (height - 1), 0) + mineMap.get(width * (height - 1) + 1, 0) + mineMap.get(width * (height - 2), 0) + mineMap.get(width * (height - 2) + 1, 0)
elif index == width * height - 1:#右下角
mineNumList[width * height - 1] = mineMap.get(width * height - 1, 0) + mineMap.get(width * height - 2, 0) + mineMap.get(width * (height - 1) - 1, 0) + mineMap.get(width * (height - 1) - 2, 0)
elif index >0 and index < width - 1:#顶边 去掉-width部分
mineNumList[index] = mineMap.get(index, 0) + mineMap.get(index + 1, 0) + mineMap.get(index - 1, 0) + \
mineMap.get(index + width, 0) + mineMap.get(index + 1 + width, 0) + mineMap.get(index - 1 + width, 0)
elif index > width * (height - 1) and index < width * height - 1:#底边 去掉+width部分
mineNumList[index] = mineMap.get(index, 0) + mineMap.get(index + 1, 0) + mineMap.get(index - 1, 0) + \
mineMap.get(index - width, 0) + mineMap.get(index + 1 - width, 0) + mineMap.get(index - 1 - width, 0)
elif index % width == 0 and index > 0 and index < width * (height - 1):#左侧边 去掉-1部分
mineNumList[index] = mineMap.get(index, 0) + mineMap.get(index + 1, 0) + mineMap.get(index + width, 0) + \
mineMap.get(index + 1 + width, 0) + mineMap.get(index - width, 0) + mineMap.get(index + 1 - width, 0)
elif index % width == width - 1 and index > 0 and index < width * (height - 1):#右侧边 去掉+1部分
mineNumList[index] = mineMap.get(index, 0) + mineMap.get(index - 1, 0) + mineMap.get(index + width, 0) + \
mineMap.get(index - 1 + width, 0) + mineMap.get(index - width, 0) + mineMap.get(index - 1 - width, 0)
else :#中间部分
mineNumList[index] = mineMap.get(index, 0) + mineMap.get(index + 1, 0) + mineMap.get(index - 1, 0) + \
mineMap.get(index + width, 0) + mineMap.get(index + 1 + width, 0) + mineMap.get(index - 1 + width, 0) + \
mineMap.get(index - width, 0) + mineMap.get(index + 1 - width, 0) + mineMap.get(index - 1 - width, 0)
#初始化游戏
def initGame():
global mineMap, stateList, mineNumList, startPos, height, width, mineNum, init
mineMap.clear()
changeMap.clear()
startPos[0] = (windowWidth - width * 40) // 2
startPos[1] = (windowHeight - height * 40) // 2
stateList = [0] * height * width
mineNumList = [0] * height * width
initMineMap()
initMineNumList()
init = True
print(mineMap)
print(mineNumList)
def pushIndex(indexNum):
#将它放入变化表中
changeMap[indexNum] = 2
#确认为非雷
stateList[indexNum] = 2
#print(indexNum)
#要求 范围在[0, width * height]之间 雷的数量为0 且未被标记为已确认非雷(防止递归死循环)
if indexNum >= 0 and indexNum < width * height and mineNumList[indexNum] == 0:
if indexNum == 0:#左上角
if stateList[indexNum + width] != 2:
pushIndex(indexNum + width)
if stateList[indexNum + 1] != 2:
pushIndex(indexNum + 1)
if stateList[indexNum + width + 1] != 2:
pushIndex(indexNum + width + 1)
elif indexNum == width - 1:#右上角
if stateList[indexNum - 1] != 2:
pushIndex(indexNum - 1)
if stateList[indexNum + width - 1] != 2:
pushIndex(indexNum + width - 1)
if stateList[indexNum + width] != 2:
pushIndex(indexNum + width)
elif indexNum == width * (height - 1):#左下角
if stateList[indexNum - width + 1] != 2:
pushIndex(indexNum - width + 1)
if stateList[indexNum + 1] != 2:
pushIndex(indexNum + 1)
if stateList[indexNum - width] != 2:
pushIndex(indexNum - width)
elif indexNum == width * height - 1:#右下角
if stateList[indexNum - width - 1] != 2:
pushIndex(indexNum - width - 1)
if stateList[indexNum - 1] != 2:
pushIndex(indexNum - 1)
if stateList[indexNum - width] != 2:
pushIndex(indexNum - width)
elif indexNum >0 and indexNum < width - 1:#顶边 去掉-width部分
if stateList[indexNum - 1] != 2:
pushIndex(indexNum - 1)
if stateList[indexNum + width - 1] != 2:
pushIndex(indexNum + width - 1)
if stateList[indexNum + width] != 2:
pushIndex(indexNum + width)
if stateList[indexNum + 1] != 2:
pushIndex(indexNum + 1)
if stateList[indexNum + width + 1] != 2:
pushIndex(indexNum + width + 1)
elif indexNum > width * (height - 1) and indexNum < width * height - 1:#底边 去掉+width部分
if stateList[indexNum - width - 1] != 2:
pushIndex(indexNum - width - 1)
if stateList[indexNum - 1] != 2:
pushIndex(indexNum - 1)
if stateList[indexNum - width] != 2:
pushIndex(indexNum - width)
if stateList[indexNum - width + 1] != 2:
pushIndex(indexNum - width + 1)
if stateList[indexNum + 1] != 2:
pushIndex(indexNum + 1)
elif indexNum % width == 0 and indexNum > 0 and indexNum < width * (height - 1):#左侧边 去掉-1部分
if stateList[indexNum - width] != 2:
pushIndex(indexNum - width)
if stateList[indexNum + width] != 2:
pushIndex(indexNum + width)
if stateList[indexNum - width + 1] != 2:
pushIndex(indexNum - width + 1)
if stateList[indexNum + 1] != 2:
pushIndex(indexNum + 1)
if stateList[indexNum + width + 1] != 2:
pushIndex(indexNum + width + 1)
elif indexNum % width == width - 1 and indexNum > 0 and indexNum < width * (height - 1):#右侧边 去掉+1部分
if stateList[indexNum - width - 1] != 2:
pushIndex(indexNum - width - 1)
if stateList[indexNum - 1] != 2:
pushIndex(indexNum - 1)
if stateList[indexNum + width - 1] != 2:
pushIndex(indexNum + width - 1)
if stateList[indexNum - width] != 2:
pushIndex(indexNum - width)
if stateList[indexNum + width] != 2:
pushIndex(indexNum + width)
else :#中间部分
if stateList[indexNum - width - 1] != 2:
pushIndex(indexNum - width - 1)
if stateList[indexNum - 1] != 2:
pushIndex(indexNum - 1)
if stateList[indexNum + width - 1] != 2:
pushIndex(indexNum + width - 1)
if stateList[indexNum - width] != 2:
pushIndex(indexNum - width)
if stateList[indexNum + width] != 2:
pushIndex(indexNum + width)
if stateList[indexNum - width + 1] != 2:
pushIndex(indexNum - width + 1)
if stateList[indexNum + 1] != 2:
pushIndex(indexNum + 1)
if stateList[indexNum + width + 1] != 2:
pushIndex(indexNum + width + 1)
def checkSuccess():
print(len(mineMap), width * height)
if stateList.count(2) + len(mineMap) == width * height:
return True
else:
return False
#导入pygame 库
# python F:\游戏开发\扫雷\main.py
if __name__ == '__main__':
mode = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
# 卸载所有模块
pygame.quit()
# 终止程序,确保退出程序
sys.exit()
elif event.type == pygame.KEYDOWN:
#只有初始态支持输入
if mode == 0 and ((event.unicode <= '9' and event.unicode >= '0') or event.unicode == ','):
inputText = inputText + event.unicode
elif mode == 0 and event.unicode == '\b':#只有初始态支持输入
inputText = inputText[0:-1]
elif event.key == pygame.K_RETURN:
if mode == 0:
if inputText == "":
hintText = "输入数据为空"
else :
inputData = inputText.split(',')
if len(inputData) != 3:
hintText = "输入数据数量不正确"
else :
try:
height = int(inputData[0])
width = int(inputData[1])
mineNum = int(inputData[2])
if width > MaxNum or height > MaxNum or mineNum >= height * width - 1 or width < 3 or height < 3:
hintText = "输入数据范围不正确,宽高,最小数量为3,最大数量均为" + str(MaxNum)
else:
hintText = ""
mode = 1
initGame()
except:
hintText = "输入数据格式不正确"
else:
mode = 0
#mode = (mode + 1) % 3
#event.pos 事件坐标 event.button 左键为1,右键为3,中键为2
elif event.type == pygame.MOUSEBUTTONDOWN:
if mode == 1:
index = ((event.pos[0] - startPos[0]) // 40, (event.pos[1] - startPos[1]) // 40)
indexNum = index[0] + index[1] * width
if event.button == 1:
#只有在默认状态下可踩雷
if stateList[indexNum] == 0:
#踩到雷,失败
if mineMap.get(indexNum, 0) == 1:
mode = 2
else:
pushIndex(indexNum)
if checkSuccess():
mode = 3
else:
print("该点击无效")
elif event.button == 3:
#增加和删除标记
if stateList[indexNum] == 0:
changeMap[indexNum] = 1
stateList[indexNum] = 1
elif stateList[indexNum] == 1:
changeMap[indexNum] = 0
stateList[indexNum] = 0
else:
print("该点击无效")
if mode == 0:# 转为黑色背景
initSurface.fill(color=backgroundColor)
screen.blit(initSurface, (0, 0))
hintTextSurf = font.render(hintText, True, fontColor, backgroundColor)
inputTextSurf = inputFont.render(inputText, True, backgroundColor, inputBoxColor)
hintTextRect = hintTextSurf.get_rect()
hintTextRect.center = (windowWidth // 2 , windowHeight // 2 - welcome_rect.height // 2 - welcome_rect.height - hintTextRect.height // 2)
screen.blit(hintTextSurf, hintTextRect)
screen.blit(welcome, welcome_rect)
screen.blit(inputSurface, inputSurfacePos)
screen.blit(inputTextSurf, inputSurfacePos)
elif mode == 1:
if init:
initSurface.fill(color=backgroundColor)
screen.blit(initSurface, (0, 0))
for i in range(width):
for j in range(height):
screen.blit(defaultRect, (startPos[0] + i * 40, startPos[1] + j * 40))
init = False
else :
for i in changeMap.keys():
x = i % width
y = i // width
if changeMap[i] == 1:
screen.blit(warningRect, (startPos[0] + x * 40, startPos[1] + y * 40))
elif changeMap[i] == 0:
screen.blit(defaultRect, (startPos[0] + x * 40, startPos[1] + y * 40))
elif changeMap[i] == 2:
screen.blit(resultRect[mineNumList[i]], (startPos[0] + x * 40, startPos[1] + y * 40))
changeMap.clear()
elif mode == 2:
initSurface.fill(color=backgroundColor)
screen.blit(initSurface, (0, 0))
screen.blit(failure, failure_rect)
elif mode == 3:
initSurface.fill(color=backgroundColor)
screen.blit(initSurface, (0, 0))
screen.blit(success, success_rect)
pygame.display.update()
简单脚本分享--扫雷
最新推荐文章于 2024-04-09 19:39:21 发布