懒得玩游戏--帮我做数独

news2024/11/21 2:38:10

目录

  • 简介
  • 自动解数独思路
    • 核心思路
    • 输入
    • 解析
    • 打印
  • 完整代码

简介

最近玩上了一款类似于数独的微信小程序游戏,名字叫数独趣味闯关,过了数独的关卡之后会给拼图,玩了几关之后摸清套路了就有点累了,但是还想集齐拼图,所以就编了个程序自动解数独。

图片
数独的关卡如上图所示,每个位置分为【空】、【□】、【x】三种状态,每行/列开始有个数字,代表该行/列有几个连续的【□】,如果有两个数字就代表这两个连续n个【□】块之间隔了至少一个【x】,规则简单,就是高难度的玩着眼花。

自动解数独思路

核心思路

核心思路就是尝试所有排列组合,记录哪些位置能够确定是【□】或者【x】。例如下图所示,假设共有8个格,该行前数字为【5,1】。则有三种组合方式,以此能推断出位置【1,2,3,4】肯定为【□】,其他为待定,逐行逐列循环以得到所有位置的填充方式。

图片

输入

目前输入只能将每行/列前数字手动输入,为了输入方便,单个数字以整形直接输入,多个数字以字符串形式输入,用空格分割。如下图所示为输入样例

row = [3, 5, 6, 9, 10, 12, '5 3 3', '10 1', '3 5 1', '2 4 1 1', '3 1 3 1', '3 1 1', '3 1', '2 1', 11]
col = [6, 8, '4 5', '5 1', '8 1', '10 1', '6 3 1', '11 1', '9 1', '6 1', '3 1 1', '3 3 1', '3 1 1', '2 1', 7]

row = [[int(i) for i in s.split()] if type(s) is str else [s] for s in row]
col = [[int(i) for i in s.split()] if type(s) is str else [s] for s in col]
图片

解析

  • 对于一个新棋盘,逐行逐列扫描,以得到每个确定的位置。对于不同个数的数字,用不同层数的循环来解析。
  • 具体来说,对于某一行/列,循环得出每个可能的填充方式,用一个长度为行数的列表,列表中每个元素为一个元组来记录每个位置可能的填充,如果该位置只有一种【□】或者【x】,就将其填入到棋盘中。若该位置有两种,则视为不确定,不进行填充。
  • 由于扫描一次之后棋盘上某些位置已经确定填充,若循环得到的填充方式与现有棋盘相悖,则跳过当前循环,以此方式得到最终所有位置的填充。

打印

  • 为了更直观的观看以便自己在手机上通关,所以做的更整齐一些。如下图所示。
图片

完整代码

import numpy as np

row = [3, 5, 6, 9, 10, 12, '5 3 3', '10 1', '3 5 1', '2 4 1 1', '3 1 3 1', '3 1 1', '3 1', '2 1', 11]
col = [6, 8, '4 5', '5 1', '8 1', '10 1', '6 3 1', '11 1', '9 1', '6 1', '3 1 1', '3 3 1', '3 1 1', '2 1', 7]

row = [[int(i) for i in s.split()] if type(s) is str else [s] for s in row]
col = [[int(i) for i in s.split()] if type(s) is str else [s] for s in col]

map_size = len(row)
row_maxlen = max([len(i) for i in row])
col_maxlen = max([len(i) for i in col])
map_default_str = '-'
map = np.full([map_size, map_size], map_default_str)
num = [0]

def map_print():
    candi_list = [1] * map_size  # col中是否有超过10的数字,需要额外多一个空格
    for i in range(map_size):
        for j in col[i]:
            if j >= 10:
                candi_list[i] = 2

    f = ''
    for i in range(1, col_maxlen + 1):
        cur_num_str = ''
        for j in range(map_size):
            if len(col[j]) >= i:
                cur_num_str += str(col[j][-i]) + ' ' + ' ' * candi_list[j]
                if col[j][-i] >= 10:
                    cur_num_str = cur_num_str[:-1]
            else:
                cur_num_str += ' ' * 2 + ' ' * candi_list[j]
        f = '     ' + '   ' * (row_maxlen - 1) + cur_num_str + '\n' + f
    print(f)

    f = ''
    for i in range(map_size):
        cur_num_str = ''
        for j in range(row_maxlen):
            if len(row[i]) >= row_maxlen - j:
                if row[i][j + len(row[i]) - row_maxlen] >= 10:
                    cur_num_str = cur_num_str[:-1]
                cur_num_str += str(row[i][j + len(row[i]) - row_maxlen]) + ' ' * 2
            else:
                cur_num_str += ' ' * 2 + ' ' * candi_list[j]
        cur_num_str += ' '
        for j in range(map_size):
            # cur_num_str += str(int(map[i][j])) + '  '
            cur_num_str += ' ' * candi_list[j] + map[i][j] + ' '
        f += cur_num_str + '\n'
    print(f)

def simple_scan(idx, is_row=True):
    map_list_tmp = np.full(map_size, 'x')  # 当前行或列的值,用'x'初始化后,循环用'o'替换
    cur_list = [set() for _ in range(map_size)]  # 扫描多次保存可能填充的值
    if is_row:
        row_col_tmp = row.copy()
        map_row_col = map[idx]
    else:
        row_col_tmp = col.copy()
        map_row_col = map[:, idx]

    if len(row_col_tmp[idx]) == 1:
        for i in range(map_size - sum(row_col_tmp[idx]) + 1):
            map_list_tmp[i: i + row_col_tmp[idx][0]] = 'o'
            if is_require(map_list_tmp, map_row_col):
                cur_list = merge_list(cur_list, map_list_tmp)
            map_list_tmp = np.full(map_size, 'x')
    elif len(row_col_tmp[idx]) == 2:
        for i in range(map_size - sum(row_col_tmp[idx]) + 1 - len(row_col_tmp[idx]) + 1):
            for j in range(i + row_col_tmp[idx][0] + 1, map_size - row_col_tmp[idx][1] + 1):
                map_list_tmp[i: i + row_col_tmp[idx][0]] = 'o'
                map_list_tmp[j: j + row_col_tmp[idx][1]] = 'o'
                if is_require(map_list_tmp, map_row_col):
                    cur_list = merge_list(cur_list, map_list_tmp)
                map_list_tmp = np.full(map_size, 'x')
    elif len(row_col_tmp[idx]) == 3:
        for i in range(map_size - sum(row_col_tmp[idx]) + 1 - len(row_col_tmp[idx]) + 1):  # 8-2+1-2+1
            for j in range(i + row_col_tmp[idx][0] + 1, map_size - sum(row_col_tmp[idx][1:]) + 1 - len(row_col_tmp[idx][1:]) + 1):
                for k in range(j + row_col_tmp[idx][1] + 1, map_size - sum(row_col_tmp[idx][2:]) + 1 - len(row_col_tmp[idx][2:]) + 1):
                    map_list_tmp[i: i + row_col_tmp[idx][0]] = 'o'
                    map_list_tmp[j: j + row_col_tmp[idx][1]] = 'o'
                    map_list_tmp[k: k + row_col_tmp[idx][2]] = 'o'
                    if is_require(map_list_tmp, map_row_col):
                        cur_list = merge_list(cur_list, map_list_tmp)
                    map_list_tmp = np.full(map_size, 'x')
    elif len(row_col_tmp[idx]) == 4:
        for i in range(map_size - sum(row_col_tmp[idx]) + 1 - len(row_col_tmp[idx]) + 1):  # 8-2+1-2+1
            for j in range(i + row_col_tmp[idx][0] + 1, map_size - sum(row_col_tmp[idx][1:]) + 1 - len(row_col_tmp[idx][1:]) + 1):
                for k in range(j + row_col_tmp[idx][1] + 1, map_size - sum(row_col_tmp[idx][2:]) + 1 - len(row_col_tmp[idx][2:]) + 1):
                    for l in range(j + row_col_tmp[idx][2] + 1, map_size - sum(row_col_tmp[idx][3:]) + 1 - len(row_col_tmp[idx][3:]) + 1):
                        map_list_tmp[i: i + row_col_tmp[idx][0]] = 'o'
                        map_list_tmp[j: j + row_col_tmp[idx][1]] = 'o'
                        map_list_tmp[k: k + row_col_tmp[idx][2]] = 'o'
                        map_list_tmp[l: l + row_col_tmp[idx][3]] = 'o'
                        if is_require(map_list_tmp, map_row_col):
                            cur_list = merge_list(cur_list, map_list_tmp)
                        map_list_tmp = np.full(map_size, 'x')

    for i in range(map_size):
        if is_row:
            if len(cur_list[i]) == 1 and map[idx][i] == map_default_str:
                map[idx][i] = list(cur_list[i])[0]
                num[0] += 1
        else:
            if len(cur_list[i]) == 1 and map[i][idx] == map_default_str:
                map[i][idx] = list(cur_list[i])[0]
                num[0] += 1

def merge_list(l, n):
    for i in range(len(l)):
        l[i] = l[i].union(set(n[i]))
    return l

def is_require(l1, l2):
    for i in range(map_size):
        if l2[i] != map_default_str and l1[i] != l2[i]:
            return False
    return True

if __name__ == '__main__':
    while True:
        for i in range(map_size):
            simple_scan(i, is_row=True)
        for j in range(map_size):
            simple_scan(j, is_row=False)
        map_print()
        if num[0] == map_size * map_size:
            break

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1383986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows之任意文件删除到提权

前言 ZDI 发表过从任意文件夹删除到提权的利用过程,还提供了任意文件删除到提权的利用过程,所以一字之差但是漏洞利用方式也是有细微偏差的。 这里把任意文件删除和任意文件夹删除漏洞提权结合起来分析,是因为其最后的利用过程是一样的&…

MongoDB - 索引底层原理和使用,聚合的使用(案例 + 演示)

目录 一、MongoDB 索引 1.1、说明 1.2、原理 1.3、操作 1.3.1、创建索引 1.3.2、查看集合索引列表 1.3.3、查看集合索引大小 1.3.4、删除集合所有索引 1.3.5、删除集合指定索引 1.3.6、创建复合索引 1.4、聚合 a) 统计每个作者写的文章数 b&#xff09…

【NI国产替代】PXIe‑6375,208路AI(16位,3.8 MS/s),2路AO,24路DIO,PXI多功能I/O模块

PXIe,208路AI(16位,3.8 MS/s),2路AO,24路DIO,PXI多功能I/O模块 PXIe‑6375提供了模拟I/O、数字I/O和四个32位计数器/定时器,用于PWM、编码器、频率、事件计数等应用。 该设备利用高吞…

通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象

文/朱季谦 这是我很多年前的第一篇技术博客,当时作为一名技术小菜鸟,总体而言显得很拙见,但也算是成长路上的一个小脚印,希望能在以后的日子里,可以对JAVA技术有一个更加深入的思考与认识。 前几天我在逛论坛的时候&a…

webpack执行流程知识点总结

webpack的运行流程 Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程: 在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 We…

网工内推 | 信息安全主管,CISP/CISSP认证优先,最高25K

01 武汉华康世纪医疗股份有限公司 招聘岗位:网络安全主管 职责描述: 1、推进公司信息/网络安全管理体系规划、建设、持续改进,促进信息安全管理的推行落地,保障网络、系统与数据安全; 2、维护管理信息/网络管理软件,设…

Centos7,Python3.7.6安装模块Crypto,pycryptodome,ibm_db,requests,requests_pkcs12

Centos7,Python3.7.6安装模块Crypto,pycryptodome,ibm_db,requests,requests_pkcs12 Python版本:python3.7.6 对应的各种模块 前言:把python项目放到linux上运行时,提示缺少各种模块,安装命令…

openFeign 多模块调用失败问题

第一次做一个完整的SpringCloud微服务项目,踩了好多好多坑,都记录下来! openFeign 多模块调用失败 排错第一阶段 创建一个openfeign服务,并把它注册到nacos上去 然后A模块通过Feign调用B模块 但是我在A模块实现AdminArticleServiceFeignClient这个接口,报错: 后面我查找这个问…

OSPF : 区域 / 为什么非骨干互访需要经过骨干

概述 OSPF系列第二篇 , 今天来围绕着区域这个概念展开写一篇博客 分区背景 先来讨论一下技术背景 , 也就是为什么要分区 ? 所有设备都在一个区域不行吗 会有什么问题呢 . 首先明确一个知识点 : 正常状态下一个区域内的所有设备的LSDB都是一样的.区域内的路由器必须为所属的…

小程序基础学习(请求封装)(重点,核心)

目录 首先: 封装一个request请求的js文件,用的是Promise 然后: 请求编写 原理:首先在页面加载完成以后发送一次请求数据,由于请求的数据会反复使用,直接把他抽离到外面,以后直接调用。在使用a…

如何用MetaGPT帮你写一个贪吃蛇的小游戏项目

如何用MetaGPT帮你写一个贪吃蛇的小游戏项目 MetaGPT是基于大型语言模型(LLMs)的多智能体写作框架,目前在Github开源,其Start数量也是比较高的,是一款非常不错的开源框架。 下面将带你进入MetaGPT的大门,开启MetaGPT的体验之旅。…

使用android studio编译app到自己的手机上运行,却读取不了手机里面的图片

问题描述: 使用android studio编译app到自己的手机上运行,却读取不了手机里面的图片 问题分析: 这个是由于这个app没有申请手机端的 媒体文件访问权限,所以读取不了 解决:(我的是Android 10,新版…

数据结构学习之对单向链表进行快速高效的排序(排序链表)

实例要求:1、给定一个链表的头结点 head ,请将其按升序排列并返回排序后的链表 ;2、链表中节点的数目的范围为 [0, 5 * 104] ;实例分析:1、引入qsort函数和自定义cmp函数解决问题;2、借助自定义指针作为中间…

Android Studio下载gradle反复失败

我的版本:gradle-5.1.1 首先检查设置路径是否正确,参考我的修改! 解决方案 1.手动下载Gradle.bin Gradle Distributions 下载地址 注意根据编译器提示下载,我这要求下载的是bin 而不是all 2.把下载好的整个压缩包放在C:\Users\…

jenkins-cl参数化构建

pipeline片段(对应jenkins-cli -p参数的BRANCHdevelop) parameters {string(name: BRANCH, defaultValue: master, description: Enter the branch name)}stages {stage(Get Code) {steps {script {def branch params.BRANCHcheckout scmGit(branches: …

【Python】使用pyinstaller打包为Windows平台的xxx.exe方法步骤

pyinstaller 是一个用于将 Python 代码打包成独立可执行文件的工具,它可以将 Python 代码打包成 Windows、Linux、Mac 等平台的可执行文件,方便用户在不同环境中运行。 pyinstaller用法: 1.安装pyinstaller库,这里以PyCharm环境为…

Git与VScode联合使用详解

目录 Git与VScode联合使用 方式一 1. 用vscode打开文件夹,如图点击初始化仓库,把此仓库初始为git仓库。 2. 提交文件到本地仓库 3. vscode与github账号绑定 4. 在github中建立远程仓库 5. 本地仓库与远程仓库绑定 方式二 1. 在github上建立远程仓…

Nginx的安装配置和使用

最近有好几个地方用到了nginx,但是一直还没时间记录下nginx的安装、配置和使用,这篇文章可以将这块内容整理出来,方便大家一起学习~ 安装 安装是相对简单一些的,直接使用yum即可。 yum install -y nginx 默认安装位置在/usr/sb…

flutter 打包IOS及常用配置

修改APP名称 项目名字配置是在 ios/Runner/Info.plist 文件中的 dict 下的 CFBundleName testapp 。如下图所示: String里面就可以修改名称 修改项目 (testapp)的 Logo 图标 iOS 项目 Logo的配置是在 ios/Runner/Assets.xcassets/AppIcon.appiconset 文…

单表的查询练习

一、单表查询 素材: 表名:worker-- 表中字段均为中文,比如 部门号 工资 职工号 参加工作 等 显示所有职工的基本信息。 mysql8.0 [chap03]>select * from worker; 查询所有职工所属部门的部门号,不显示重复的部门号。 mysq…