# -*- 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