亲宝软件园·资讯

展开

150+行Python代码实现带界面的数独游戏

HoLoong 人气:0
# 150行代码实现图形化数独游戏 [Github地址](https://github.com/NemoHoHaloAi/Sudoku--),欢迎各位大佬们fork、star啥的,感谢; 今天闲着没事干,以前做过html+js版的数独,这次做个python版本的,界面由pygame完成,数独生成由递归算法实现,由shuffle保证每次游戏都是不一样的情况,have fun; 功能列表: - 图形化的数独游戏; - python实现,依赖pygame库; - 随机生成游戏,每次运行都不一样; - 数字填入后的正确性判断以及颜色提示; - 显示剩余需填入的空格,已经操作的次数; - 难度可选,通过修改需要填入的空的数量; ## 游戏界面 ### 初始界面 ![](https://img2020.cnblogs.com/blog/666842/202004/666842-20200403171058376-562210167.png) ### 过程中界面 ![](https://img2020.cnblogs.com/blog/666842/202004/666842-20200403171157975-1073503274.png) ## 运行方式 ```python python main.py 15 ``` 这里的15表示需要填入的空格数量为15,理论上这个值越大,难度就越高,大家可以随机调整,或者设置容易、简单、困难、地狱等对应不同的值即可,很方便修改; ## 程序分析 ### 界面部分 这部分很简单的通过pygame来实现,主要使用了其中的主循环、鼠标键盘监听、画矩形线条、字体、颜色控制等,理解起来很容易,对于这部分不太熟悉的同学,这样理解就好:**pygame的主循环中一方面负责接收用户输入,一般就是鼠标和键盘,另一方面负责实时更新界面显示内容**; #### 对于界面上各部分内容的绘制的函数封装 ```python # 绘制背景部分,这里就是9*9的九宫格 def draw_background(): # white background screen.fill(COLORS['white']) # draw game board pygame.draw.rect(screen,COLORS['black'],(0,0,300,900),5) pygame.draw.rect(screen,COLORS['black'],(300,0,300,900),5) pygame.draw.rect(screen,COLORS['black'],(600,0,300,900),5) pygame.draw.rect(screen,COLORS['black'],(0,0,900,300),5) pygame.draw.rect(screen,COLORS['black'],(0,300,900,300),5) pygame.draw.rect(screen,COLORS['black'],(0,600,900,300),5) # 将用户选中的各自背景改为蓝色块表示选中 def draw_choose(): pygame.draw.rect(screen,COLORS['blue'],(cur_j*100+5,cur_i*100+5,100-10,100-10),0) # 绘制九宫格中的数字,包括本来就有的,以及用户填入的,本来就在的用灰色,用户填入的如何合法则为绿色,否则为红色,是一种提示 def draw_number(): for i in range(len(MATRIX)): for j in range(len(MATRIX[0])): _color = check_color(MATRIX,i,j) if (i,j) in BLANK_IJ else COLORS['gray'] txt = font80.render(str(MATRIX[i][j] if MATRIX[i][j] not in [0,'0'] else ''),True,_color) x,y = j*100+30,i*100+10 screen.blit(txt,(x,y)) # 绘制最下方的当前空格子数量以及用户的操作数量 def draw_context(): txt = font100.render('Blank:'+str(cur_blank_size)+' Change:'+str(cur_change_size),True,COLORS['black']) x,y = 10,900 screen.blit(txt,(x,y)) ``` #### 主循环中对上述函数的调用以及鼠标键盘事件处理 ```python # 主循环,负责监听鼠标键盘时间,以及刷新界面内容,以及检查是否赢得了游戏 running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False break elif event.type == pygame.MOUSEBUTTONDOWN: cur_j,cur_i = int(event.pos[0]/100),int(event.pos[1]/100) elif event.type == event.type == pygame.KEYUP: if chr(event.key) in ['1','2','3','4','5','6','7','8','9'] and (cur_i,cur_j) in BLANK_IJ: MATRIX[cur_i][cur_j] = int(chr(event.key)) cur_blank_size = sum([1 if col==0 or col=='0' else 0 for row in MATRIX for col in row]) cur_change_size +=1 # background draw_background() # choose item draw_choose() # numbers draw_number() # point draw_context() # flip pygame.display.flip() # check win or not if check_win(MATRIX_ANSWER,MATRIX): print('You win, smarty ass!!!') break pygame.quit() ``` ### 生成表示数独的二维数组 相对于界面部分,这部分在逻辑上要难一些,思路以递归为核心,辅以随机性,得到一个每次生成都不一致的数独游戏,生成思路简单描述如下: 1. 遍历每个空格,填入目前为止合法的数字; 2. 如果有数字可以填入,则继续向下一个空格; 3. 如果没有数字可以填入,表示之前的数字有问题,则结束递归; 4. 当递归到最后一个格子的下一个时,表示已经生成完毕,返回即可; 5. 这个过程中对1~9这九个数字的遍历数字会经过shuffle处理,保证随机性而不是每次都得到同一个合法的数独数组; #### 生成过程代码 递归的一个优势是通常代码都很短,当然阅读性不强,欢迎大佬们改为循环; ```python def shuffle_number(_list): random.shuffle(_list) return _list def check(matrix,i,j,number): if number in matrix[i]: return False if number in [row[j] for row in matrix]: return False group_i,group_j = int(i/3),int(j/3) if number in [matrix[i][j] for i in range(group_i*3,(group_i+1)*3) for j in range(group_j*3,(group_j+1)*3)]: return False return True def build_game(matrix,i,j,number): if i>8 or j>8: return matrix if check(matrix,i,j,number): _matrix = [[col for col in row] for row in matrix] _matrix[i][j] = number next_i,next_j = (i+1,0) if j==8 else (i,j+1) for _number in shuffle_number(number_list): __matrix = build_game(_matrix,next_i,next_j,_number) if __matrix and sum([sum(row) for row in __matrix])==(sum(range(1,10))*9): return __matrix return None ``` #### 随机覆盖数独数组中的N个位置 - matrix_all表示整个数独数组 - matrix_blank表示部分被替换为0的用于显示的数组 - blank_ij表示被覆盖位置的i和j ```python def give_me_a_game(blank_size=9): matrix_all = build_game(matrix,0,0,random.choice(number_list)) set_ij = set() while len(list(set_ij))8 or j>8: return matrix if check(matrix,i,j,number): _matrix = [[col for col in row] for row in matrix] _matrix[i][j] = number next_i,next_j = (i+1,0) if j==8 else (i,j+1) for _number in shuffle_number(number_list): #_matrixs.append(build_game(_matrix,next_i,next_j,_number)) __matrix = build_game(_matrix,next_i,next_j,_number) if __matrix and sum([sum(row) for row in __matrix])==(sum(range(1,10))*9): return __matrix #return _matrixs return None def give_me_a_game(blank_size=9): matrix_all = build_game(matrix,0,0,random.choice(number_list)) set_ij = set() while len(list(set_ij))

加载全部内容

相关教程
猜你喜欢
用户评论