150+行Python代码实现带界面的数独游戏!益智烧脑了解一下!

2024-03-24 17:30

本文主要是介绍150+行Python代码实现带界面的数独游戏!益智烧脑了解一下!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

150行代码实现图形化数独游戏

Github地址 ,欢迎各位大佬们fork、star啥的,感谢;

今天闲着没事干,以前做过html+js版的数独,这次做个python版本的,界面由pygame完成,数独生成由递归算法实现,由shuffle保证每次游戏都是不一样的情况,have fun;

功能列表:

  • 图形化的数独游戏;
  • python实现,依赖pygame库;
  • 随机生成游戏,每次运行都不一样;
  • 数字填入后的正确性判断以及颜色提示;
  • 显示剩余需填入的空格,已经操作的次数;
  • 难度可选,通过修改需要填入的空的数量;

游戏界面

初始界面

过程中界面

运行方式

python main.py 15

这里的15表示需要填入的空格数量为15,理论上这个值越大,难度就越高,大家可以随机调整,或者设置容易、简单、困难、地狱等对应不同的值即可,很方便修改;

程序分析

界面部分

这部分很简单的通过pygame来实现,主要使用了其中的主循环、鼠标键盘监听、画矩形线条、字体、颜色控制等,理解起来很容易,对于这部分不太熟悉的同学,这样理解就好: pygame的主循环中一方面负责接收用户输入,一般就是鼠标和键盘,另一方面负责实时更新界面显示内容;

对于界面上各部分内容的绘制的函数封装

# 绘制背景部分,这里就是9*9的九宫格
def draw_background():# white backgroundscreen.fill(COLORS['white'])# draw game boardpygame.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+10screen.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,900screen.blit(txt,(x,y))

主循环中对上述函数的调用以及鼠标键盘事件处理

# 主循环,负责监听鼠标键盘时间,以及刷新界面内容,以及检查是否赢得了游戏
running = True
while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsebreakelif 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# backgrounddraw_background()# choose itemdraw_choose()# numbersdraw_number()# pointdraw_context()# flippygame.display.flip()# check win or notif check_win(MATRIX_ANSWER,MATRIX):print('You win, smarty ass!!!')breakpygame.quit()

生成表示数独的二维数组

相对于界面部分,这部分在逻辑上要难一些,思路以递归为核心,辅以随机性,得到一个每次生成都不一致的数独游戏,生成思路简单描述如下:

  1. 遍历每个空格,填入目前为止合法的数字;
  2. 如果有数字可以填入,则继续向下一个空格;
  3. 如果没有数字可以填入,表示之前的数字有问题,则结束递归;
  4. 当递归到最后一个格子的下一个时,表示已经生成完毕,返回即可;
  5. 这个过程中对1~9这九个数字的遍历数字会经过shuffle处理,保证随机性而不是每次都得到同一个合法的数独数组;

生成过程代码

递归的一个优势是通常代码都很短,当然阅读性不强,欢迎大佬们改为循环;

def shuffle_number(_list):random.shuffle(_list)return _listdef check(matrix,i,j,number):if number in matrix[i]:return Falseif number in [row[j] for row in matrix]:return Falsegroup_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 Falsereturn Truedef build_game(matrix,i,j,number):if i>8 or j>8:return matrixif check(matrix,i,j,number):_matrix = [[col for col in row] for row in matrix]_matrix[i][j] = numbernext_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 __matrixreturn None

随机覆盖数独数组中的N个位置

  • matrix_all表示整个数独数组
  • matrix_blank表示部分被替换为0的用于显示的数组
  • blank_ij表示被覆盖位置的i和j
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))<blank_size:set_ij.add(str(random.choice([0,1,2,3,4,5,6,7,8]))+','+str(random.choice([0,1,2,3,4,5,6,7,8])))matrix_blank = [[col for col in row] for row in matrix_all]blank_ij = []for ij in list(set_ij):i,j = int(ij.split(',')[0]),int(ij.split(',')[1])blank_ij.append((i,j))matrix_blank[i][j] = 0return matrix_all,matrix_blank,blank_ij

最后附上全部代码

大家也可以直接从我的 Github仓库 fork下来直接运行;

main.py:主流程+界面+执行

import sysimport pygame
from pygame.color import THECOLORS as COLORSfrom build import print_matrix,give_me_a_game,checkdef draw_background():# white backgroundscreen.fill(COLORS['white'])# draw game boardpygame.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 check_win(matrix_all,matrix):if matrix_all == matrix:return Truereturn Falsedef check_color(matrix,i,j):_matrix = [[col for col in row]for row in matrix]_matrix[i][j] = 0if check(_matrix,i,j,matrix[i][j]):return COLORS['green']return COLORS['red']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+10screen.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,900screen.blit(txt,(x,y))if __name__ == "__main__":# init pygamepygame.init()# contantSIZE = [900,1000]font80 = pygame.font.SysFont('Times', 80)font100 = pygame.font.SysFont('Times', 90)# create screen 500*500screen = pygame.display.set_mode(SIZE)# variable parametercur_i, cur_j = 0,0cur_blank_size = int(sys.argv[1])cur_change_size = 0# matrix abountMATRIX_ANSWER,MATRIX,BLANK_IJ = give_me_a_game(blank_size=cur_blank_size)print(BLANK_IJ)print_matrix(MATRIX)# main looprunning = Truewhile running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsebreakelif 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# backgrounddraw_background()# choose itemdraw_choose()# numbersdraw_number()# pointdraw_context()# flippygame.display.flip()# check win or notif check_win(MATRIX_ANSWER,MATRIX):print('You win, smarty ass!!!')breakpygame.quit()

build.py:生成数独数组部分

import randomdef print_matrix(matrix):print('—'*19)for row in matrix:print('|'+' '.join([str(col) for col in row])+'|')print('—'*19)def shuffle_number(_list):random.shuffle(_list)return _listdef check(matrix,i,j,number):if number in matrix[i]:return Falseif number in [row[j] for row in matrix]:return Falsegroup_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 Falsereturn Truedef build_game(matrix,i,j,number):if i>8 or j>8:return matrixif check(matrix,i,j,number):_matrix = [[col for col in row] for row in matrix]_matrix[i][j] = numbernext_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 _matrixsreturn Nonedef 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))<blank_size:set_ij.add(str(random.choice([0,1,2,3,4,5,6,7,8]))+','+str(random.choice([0,1,2,3,4,5,6,7,8])))matrix_blank = [[col for col in row] for row in matrix_all]blank_ij = []for ij in list(set_ij):i,j = int(ij.split(',')[0]),int(ij.split(',')[1])blank_ij.append((i,j))matrix_blank[i][j] = 0return matrix_all,matrix_blank,blank_ijnumber_list = [1,2,3,4,5,6,7,8,9]
matrix = [([0]*9) for i in range(9)]
if __name__ == "__main__":print_matrix(build_game(matrix,0,0,random.choice(number_list)))

总结

如果刻意减少代码的话,实际应该控制在100行以内,这也充分表达了python的强大,确实可以在很短的时间内完成一些看似复杂的工作,这个例子供一些同学上手python个人觉得还是不错的,没有太复杂的用法,对界面开发有一点点了解,对递归有一些理解基本就能完全掌握这份代码,希望大家玩的开心,挑战一下50个空格呗,哈哈,反正我没通过,太难了。。。。

最后

大家可以到我的Github上看看有没有其他需要的东西,目前主要是自己做的机器学习项目、Python各种脚本工具、有意思的小项目以及Follow的大佬、Fork的项目等:

这篇关于150+行Python代码实现带界面的数独游戏!益智烧脑了解一下!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/842257

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形