You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
11 KiB

# -*- encoding: utf-8 -*-
'''
@File : gameui.py
@License : (C)Copyright 2018-2022
@Modify Time @Author @Version @Desciption
------------ ------- -------- -----------
2022/12/22 10:01 zart20 1.0 None
'''
import time
from data import *
import pygame
# 定义颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
ORANGE = (255, 140, 0) # 橘色
YELLOW = (250, 224, 103) # 蛋黄
SILVER = (192, 192, 192) # 银色
RED = (200, 0, 0)
bc = 40 # 定义全局边长
class MyTimer:
def __init__(self):
self.elapsed = 0.0
self.running = False
self.last_start_time = None
def start(self):
if not self.running:
self.running = True
self.last_start_time = time.time()
def pause(self):
if self.running:
self.running = False
self.elapsed += time.time() - self.last_start_time
def get_elapsed(self):
elapsed = self.elapsed
if self.running:
elapsed += time.time() - self.last_start_time
return '{:>2.0f}{:>2.0f}'.format(elapsed // 60, elapsed % 60)
def GuiForm():
pygame.init() # pygame 的初始化
pygame.display.set_caption("数独")
form = pygame.display.set_mode((840, 610)) # 主窗口
form.fill(ORANGE) # 填充橘色
pygame.display.update()
return form
# form = GuiForm()
def rect_draw(bc, row, col):
'''画一个小方格对象'''
# row = row-1
# col = col-1
face = pygame.Surface((bc, bc)) # 创建一个Surface对象
block_color = [3, 4, 5] # 显色宫格依据
logi_row = row in block_color and col in block_color # 显色逻辑
logi_col = row in block_color or col in block_color # 显色逻辑
if not logi_row and logi_col:
face.fill(YELLOW)
else:
face.fill(WHITE) # 为对象填充颜色
return face
def show_face(form, face, bc, row, col, ):
"""将小方格face在form上显示出来"""
form.blit(face, (row * (bc + 3) + 50, col * (bc + 3) + 50))
pygame.display.update()
def refresh(form:pygame.Surface,martix,u_martix, note_martix):
# 将整个数组刷新一遍
for i in range(9):
for j in range(9):
face = rect_draw(40, i, j) # 创建一个基于位置的小方格
if u_martix[j][i] != 0:
if u_martix[j][i] != 11:
face1 = number_draw(face, martix, u_martix, bc, i, j)
else:
face.fill(SILVER)
for note in note_martix: # 如果这个空格有笔记直接覆盖清空笔记
if note[0] == i and note[1] == j:
possible = note[2]
face1 = possible_num(bc, i, j, possible)
show_face(form, face1, bc, i, j)
else:
show_face(form, face, bc, i, j)
def xianse(form,martix, u_martix, x, y, note_martix=None):
# 更新单个单元格为银色
if note_martix is None:
note_martix = list()
if x >= 1 and y >= 1:
i = x - 1 # 映射坐标时加了一现在要减掉
j = y - 1
face = rect_draw(bc, i, j) # 创建一个基于位置的小方格
face.fill(SILVER, (3, 3, 34, 34))
if u_martix[j][i] != 0:
if u_martix[j][i] != 11:
number_draw(face, martix, u_martix, bc, i, j)
else:
# face.fill(SILVER)
for note in note_martix: # 如果这个空格有笔记直接覆盖清空笔记
if note[0] == i and note[1] == j:
possible = note[2]
face = possible_num(bc, x, y, possible)
# show_face(form,face,bc,i,j)
show_face(form, face, bc, i, j)
def mini_rect_draw(face, bc, possible):
"""单独一个格子里的小数字"""
num_font = pygame.font.SysFont('幼圆', 16, True) # 加载系统字体
bc1 = bc # 当出现空集时用于定位
bc = int(bc / 3)
n = 1
for i in range(3):
for j in range(3):
mini = pygame.Surface((bc, bc)) # 创建Surface对象
mini.set_colorkey([0, 0, 0]) # 设置透明色
mini = mini.convert_alpha() # 设置透明色
if possible: # 在用户已填的部分有可能导致部分格子无解,所以先加一个判断
for k in possible:
if n == k:
num_text = num_font.render(f"{k}", False, (109, 45, 250)) # 创建字体
rel = num_text.get_rect()
mini.blit(num_text, (int((bc - rel[2]) / 2), int((bc - rel[3]) / 2))) # 数字显示居中
n += 1
face.blit(mini, (i * bc, j * bc))
else:
num_text = num_font.render(f"{None}", False, (109, 45, 250))
rel = num_text.get_rect()
face.blit(num_text, (int((bc1 - rel[2]) / 2), int((bc1 - rel[3]) / 2)))
return face
def possible_num(bc, row, col, possible):
"""显示一个格子的可能值"""
row = row - 1
col = col - 1
face = rect_draw(bc, row, col)
face.fill(SILVER)
mface = mini_rect_draw(face, bc, possible)
return mface
def number_draw(face, martix, u_martix, bc, row, col):
"""向小格子里画数字"""
num_font = pygame.font.SysFont('幼圆', 32, True) # 加载系统字体
if martix[col,row] == 0:
if u_martix[col,row] not in GetPossible(martix,col,row): # 判断是否符合数组要求
print((col,row), GetPossible(martix, col, row))
num_text = num_font.render(f"{u_martix[col][row]}", True, RED) # 不符合要求显示红色
else:
num_text = num_font.render(f"{u_martix[col][row]}", True, BLACK) # 创建字体
else:
num_text = num_font.render(f"{u_martix[col][row]}", True, BLACK) # 创建字体
rect_l = num_text.get_rect() # 获取字体边长大小
face.blit(num_text, (int((bc - rect_l[2]) / 2), int(bc - rect_l[3]) / 2)) # 数字显示居中
return face
def control_number(form, bc, color1=SILVER, color2=WHITE):
# 0-9 按键控制
for num in range(9):
control_number_xs(form, bc, num, color1, color2)
def control_number_xs(form, bc, num, color1=SILVER, color2=WHITE):
ck = 6 # 边框
num_font = pygame.font.SysFont('幼圆', 32, True) # 加载系统字体
face = pygame.Surface((bc, bc))
# face1 = pygame.Surface((bc-ck, bc-ck))
face.fill(color1) # 外层银色
face.fill(color2, (ck // 2, ck // 2, bc - ck, bc - ck)) # 里层白色
num_text = num_font.render(f"{num + 1}", True, (0, 0, 0)) # 创建字体
rect_l = num_text.get_rect() # 获取字体边长大小
face.blit(num_text, (int((bc - rect_l[2]) / 2), int(bc - rect_l[3]) / 2)) # 数字显示居中
# face.blit(face,(int(ck/2),int(ck/2)))
form.blit(face, (num * (bc + 3) + 50, (bc + 3) * 12 + 10))
def control(form, bc):
# 5个控制按键
lon = 9 * (bc + 3) + 50
lon = lon // 5 - 12 # 控制按键长度
num_font = pygame.font.SysFont('幼圆', 18, True) # 加载系统字体
ctl = ["撤回", "擦除", "笔记", "一键笔记", "提示"]
for i in range(5):
face = pygame.Surface((lon, bc))
# face.set_colorkey([0,0,0])
# face = face.convert_alpha() # 透明色
face.fill(WHITE)
num_text = num_font.render(f"{ctl[i]}", False, (0, 0, 0)) # 创建字体
rel = num_text.get_size()
face.blit(num_text, (int((lon - rel[0]) / 2), int((bc - rel[1]) / 2))) # 数字显示居中
form.blit(face, ((lon + 2) * i + 50, (bc + 3) * 11 + 8))
def control_xs(form, bc, i):
lon = 9 * (bc + 3) + 50
lon = lon // 5 - 12 # 控制按键长度
num_font = pygame.font.SysFont('幼圆', 18, True) # 加载系统字体
ctl = ["撤回", "擦除", "笔记", "一键笔记", "提示"]
face = pygame.Surface((lon, bc))
face.fill(SILVER)
num_text = num_font.render(f"{ctl[i]}", False, (0, 0, 0)) # 创建字体
rel = num_text.get_size()
face.blit(num_text, (int((lon - rel[0]) / 2), int((bc - rel[1]) / 2))) # 数字显示居中
form.blit(face, ((lon + 2) * i + 50, (bc + 3) * 11 + 8))
def text_enter(bc):
"""文字框"""
top_x = (bc + 3) * 11 # 文本框顶点x
top_y = 50 # 文本框顶点y
bc_x = (bc + 3) * 7 + 20 # 文本框宽度
bc_y = (bc + 3) * 12 # 文本框高度
ck = 6 # 间隔
face = pygame.Surface((bc_x, bc_y))
face.fill(SILVER)
face.fill(WHITE, (ck // 2, ck // 2, bc_x - ck, bc_y - ck))
return face, (top_x, top_y)
def timer(face, time1, empty, *args):
"""
时间难度显示:
:param face:
:param time1: 时间
:param empty: 原始空格数目
:return:
"""
num_font = pygame.font.SysFont('幼圆', 18, True) # 加载系统字体
info_time = num_font.render(f"运行时间:{time1.get_elapsed()}", False, BLACK)
w, h = info_time.get_size()
face.blit(info_time, (5, 5))
info_level = num_font.render("难度:{:.2f}".format(empty / 81), False, BLACK)
face.blit(info_level, (15 + w, 5))
return face
def noter(face, tag):
"""显示笔记提示"""
num_font = pygame.font.SysFont('幼圆', 18, True) # 加载系统字体
note_help1 = num_font.render(f"False 时保存笔记,当前笔记:{tag}", False, RED)
w1, h1 = note_help1.get_size()
face.blit(note_help1, (5, 15 + h1))
# note_tag = num_font.render(f"笔记模式:{tag}", False, BLACK)
# face.blit(note_tag, (5, 31+10+h1)) #
return face
def seq_recode(face: pygame.Surface, STEP):
num_font = pygame.font.SysFont('幼圆', 18, True) # 加载系统字体
note_help1 = num_font.render(f"步骤记录:", False, BLACK)
w1, h1 = note_help1.get_size()
face.blit(note_help1, (5, 15 + (3 + h1) * 2))
for i in range(len(STEP)):
if i != 0:
step = num_font.render(f"{STEP[i][:3]}", False, BLACK)
w, h = step.get_size()
wf, wh = face.get_size()
if 15 + (3 + h) * (i + 2) < wh:
face.blit(step, (5, 15 + (3 + h) * (i + 2)))
else:
face.blit(step, (15 + w, 16+h+(3 + h) * (i + 2 -22)))
return face
def win(face: pygame.Surface, u_martix, timer: MyTimer):
count = 0 # 计数
num_font = pygame.font.SysFont('幼圆', 18, True) # 加载系统字体
win_words = num_font.render(f"游戏结束,恭喜通过", False, BLACK)
w1, h1 = win_words.get_size()
for i in range(9):
for j in range(9):
if u_martix[i][j] == 0 or u_martix[i][j] == 11:
count += 1
if count == 0:
if Judge(u_martix):
time1 = timer.get_elapsed()
timer.pause()
time1_words = num_font.render(f"耗时:{time1}", False, BLACK)
wt, ht = time1_words.get_size()
face.fill(WHITE)
w, h = face.get_size()
face.blit(win_words, ((w - w1) // 2, (h - h1) // 2))
face.blit(time1_words, ((w - wt) // 2, (h - ht) // 2 - h1 - 5))
return face