【教学类-52-17】20250803动物数独_空格尽量分散_只有一半关卡数(N宫格通用版3-10宫格)0图、1图、2图、6图、有答案、无答案 组合版24套

发布于:2025-08-05 ⋅ 阅读:(12) ⋅ 点赞:(0)

前文提到了 5宫格(25格子,1-12空格散开,12和13是棋盘样式,13以后不明显)

1.(越往后实际可以排序的答案样式也越多。预设答案只是其中一种)

2.超过一半的关卡时,空格就不是分散的了(超过一半数量),不容易做。

【教学类-52-17】20250803动物数独_空格尽量分散(N宫格通用版3-10宫格)0图、1图、2图、6图、有答案、无答案 组合版24套-CSDN博客文章浏览阅读521次,点赞11次,收藏2次。【教学类-52-17】20250803动物数独_空格尽量分散(N宫格通用版3-10宫格)0图、1图、2图、6图、有答案、无答案 组合版24套 https://blog.csdn.net/reasonsummer/article/details/149878582?spm=1011.2415.3001.5331

所以我不想做全部关卡,就做一半。

一、棋盘测试

可以看到,这是分散样式,类似棋盘,这是空格最多的棋盘样式。

用Python做棋盘,了解1-10宫格中每种最多的棋盘样式

'''
python制作数独宫格的棋盘样式宫格1-宫格10
deepseek,阿夏
20250803
'''
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.gridspec import GridSpec

def create_chessboard(n, top_left_white=True):
    """创建n x n的棋盘,返回矩阵和白色格子数量"""
    board = np.zeros((n, n))
    white_count = 0
    
    for i in range(n):
        for j in range(n):
            if (i + j) % 2 == (0 if top_left_white else 1):
                board[i, j] = 1  # 白色
                white_count += 1
            else:
                board[i, j] = 0  # 黑色
    return board, white_count

# 创建一个大图来显示所有棋盘
plt.figure(figsize=(15, 12))
plt.suptitle("Chessboards from 1x1 to 10x10 with Maximum White Squares", fontsize=16)

# 使用GridSpec来布局子图
gs = GridSpec(4, 5, width_ratios=[1]*5, height_ratios=[1]*4)

max_white_counts = []

for size in range(1, 11):
    # 计算两种排列方式的白格子数量
    board1, white_count1 = create_chessboard(size, True)
    board2, white_count2 = create_chessboard(size, False)
    
    # 选择白格子数量较多的排列方式
    if white_count1 >= white_count2:
        board = board1
        white_count = white_count1
        top_left_color = "White"
    else:
        board = board2
        white_count = white_count2
        top_left_color = "Black"
    
    max_white_counts.append((size, white_count))
    
    # 添加子图
    ax = plt.subplot(gs[(size-1)//3, (size-1)%3 + ((size-1)//3)*2])
    ax.imshow(board, cmap='binary', vmin=0, vmax=1)
    ax.set_title(f"{size}x{size}\nWhite: {white_count}", pad=10)
    ax.set_xticks([])
    ax.set_yticks([])
    
    # 在左上角标记颜色
    ax.text(0, 0, top_left_color[0], ha='center', va='center', 
            color='red' if top_left_color == "White" else 'blue',
            fontsize=10, fontweight='bold')

plt.tight_layout()
plt.show()

# 打印最大白格子数量表
print("\nMaximum white squares for each board size:")
print("-" * 40)
print("| Size | White Squares (max) | Formula       |")
print("-" * 40)
for size, count in max_white_counts:
    if size % 2 == 0:
        formula = f"n²/2 = {size*size//2}"
    else:
        formula = f"(n²+1)/2 = {(size*size+1)//2}"
    print(f"| {size}x{size:<3} | {count:<19} | {formula:<13} |")
print("-" * 40)

结果显示:

奇数宫格的最大数量是:"(奇数*奇数+1)/2

偶数宫格的最大数量是:"(偶数*偶数)/2

修改代码

把原来的动物数独代码与奇偶规律合并。

测试了一上午,deepseek写了20多条,终于可以用了

# -*- coding:utf-8 -*-
 
'''
制作动物/脸谱数独N宫格通用版(3-10的黏贴关卡 A4 1图2图6图的所有组合 还有一个限定A4大小的0图(3-6宫格)
1.无答案:9种3:3,两两组合
2.有答案:27种 3:3:3,三三组合(实际需要其中9种)
3.横竖两个不能都是空格,空格尽量分散排列,如9格,目前1-5可以分散,空额不相连,6-9不行)
4.奇数宫格:(奇数*奇数+1)/2;偶数宫格:(偶数*偶数+1)/2
作者:AI对话大师,deepseek、阿夏
时间:2025年08月03日
'''
 
 
 
import os
import time
from docx import Document
from docx.shared import Cm, Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docxtpl import DocxTemplate
import pandas as pd
from docx2pdf import convert
from win32com.client import constants, gencache
from win32com.client.gencache import EnsureDispatch
from datetime import datetime
import random
import shutil
import xlwt
import xlrd
from PyPDF2 import PdfMerger
from docx.shared import Pt, Cm, RGBColor
from docx.oxml.shared import qn
 
 
num=1
hsall=int(input('几宫格?(3-10)\n'))
start=0
end=hsall
start_time = datetime.now()
hs=hsall
 
path=fr'C:\Users\jg2yXRZ\OneDrive\桌面\20250803动物数独N宫格原始6图'
 
A4size=[6.5,4.88,3.9,3.25,2.79,2.44,2.17]
A4gz=[3,4,5,6,7,8,9]
A4pg=[3,4,5,6,7,8,9]
A4gzs=[3,4,5,6,7,8,9]
 
psize=[19.6,14.1,9.39]
gzsize=[6.4,4.8,3.84,3.2,2.74,2.39,2.12,1.91]
gzsgg=list(range(3, 10))
pg=[1,2,6]
gzs=[1,2,2]
 
print('-----第一板块、动物操作卡(大图片卡一页1图、1页2图 一页6图)-------')
 
# Get page settings based on hs value
for w in range(len(A4gz)):
    if hs == A4gz[w]:
        psize.append(A4size[w])
        pg = [1, 2, 6, A4pg[w]]
        gzs = [1, 2, 2, A4gzs[w]]
 
k = ['1图关卡', '2图关卡', '6图关卡', f'A4的{hs}图卡片']
print(k)
 
for pt in range(len(pg)):
    # Create temp folders
    temp_word_path = os.path.join(path, '零时Word')
    temp_pdf_path = os.path.join(path, '05操作卡pdf')
    os.makedirs(temp_word_path, exist_ok=True)
    os.makedirs(temp_pdf_path, exist_ok=True)
 
    # Load template document
    doc = Document(os.path.join(path, f'动物数独({k[pt]}).docx'))
    table = doc.tables[0]
    
    # Get animal images
    pic_folder = os.path.join(path, '02动物图片')
    pic_list = [os.path.join(pic_folder, f) for f in os.listdir(pic_folder)][start:end] * hs
    
    # Group images based on layout
    group_size = pg[pt]*pg[pt] if pt == 3 else pg[pt]
    groups = [pic_list[i:i + group_size] for i in range(0, len(pic_list), group_size)]
    
    for group_idx, group in enumerate(groups):
        doc = Document(os.path.join(path, f'动物数独({k[pt]}).docx'))
        table = doc.tables[0]
        
        for cell_idx, img_file in enumerate(group):
            row = int(cell_idx / gzs[pt])
            col = cell_idx % gzs[pt]
            cell = table.cell(row, col)
            cell.paragraphs[0].clear()
            
            if os.path.exists(img_file):
                run = cell.paragraphs[0].add_run()
                run.add_picture(img_file, width=Cm(psize[pt]), height=Cm(psize[pt]))
                cell.paragraphs[0].alignment = 1
        
        # Add title for A4 layout
        if pt == 3:
            title_table = doc.tables[1]
            title_cell = title_table.cell(0, 0)
            title_cell.text = f'动物数独 {hs}*{hs}   操作卡'
            para = title_cell.paragraphs[0]
            para.alignment = WD_ALIGN_PARAGRAPH.CENTER
            run = para.runs[0]
            run.font.name = '黑体'
            run.font.size = Pt(35)
            run.font.color.rgb = RGBColor(0, 0, 0)
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
        
        # Save and convert to PDF
        doc.save(os.path.join(temp_word_path, f'{group_idx+1:02d}页.docx'))
        convert(os.path.join(temp_word_path, f'{group_idx+1:02d}页.docx'), 
               os.path.join(temp_word_path, f'{group_idx+1:02d}页.pdf'))
        time.sleep(2.5)
    
    # Merge PDFs
    pdf_files = sorted([os.path.join(temp_word_path, f) for f in os.listdir(temp_word_path) if f.endswith('.pdf')])
    merger = PdfMerger()
    for pdf in pdf_files:
        merger.append(pdf)
    
    output_name = "03 0图关卡图操作卡片.pdf" if pt == 3 else f"03 {k[pt]}图操作卡片.pdf"
    merger.write(os.path.join(temp_pdf_path, output_name))
    merger.close()
    
    # Clean up
    shutil.rmtree(temp_word_path)
 
print('-----第二板块、动物任务卡和答案卡一套,只要JPG-------')
 
import random
from win32com.client import constants, gencache
from win32com.client import genpy
from win32com.client.gencache import EnsureDispatch
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH
import docxtpl
import pandas as pd
from docx2pdf import convert
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml
import copy
 

print('------3-1、生成指定数量的关卡(按最大空缺数限制)------')

n = hsall  # 宫格数(例如3)
g = n * n  # 总格子数(例如9)

# 根据宫格数确定最大空缺数
if n % 2 == 1:  # 奇数宫格
    max_empty = (g + 1) // 2  # 例如3宫格:(9+1)/2=5
else:  # 偶数宫格
    max_empty = g // 2  # 例如4宫格:16/2=8

# 只生成1到max_empty关(例如3宫格只生成5关)
a = []
for empty in range(1, max_empty + 1):  # 直接按空缺数生成
    # 计算对应的百分比(四舍五入)
    percentage = round(empty * 100 / g)
    print(f'{n}宫格,难度{percentage:03d},抽取{percentage:03d}%:实际有{empty:03d}空,已有图案{g-empty:03d}')
    a.append(f'{n}宫格,难度{percentage:03d},抽取{percentage:03d}%:实际有{empty:03d}空,已有图案{g-empty:03d}')

# 去重和排序(虽然现在应该已经是有序且不重复的)
b = []
for element in a:
    parts = element.split(":")
    info = parts[1]
    b.append(info)
b = list(set(b))
b.sort(reverse=False)

f = []
for d in range(len(b)):
    for c in a:
        if c[-15:] == b[d]:
            f.append(c)
            break

# 移除第一个(空0的无效项)如果有的话
if f and int(f[0][20:23]) == g:  # 检查是否全满(空0)
    f.pop(0)

print(f'实际生成关卡数:{len(f)}')

# 提取空缺数和已有图案数
empty_counts = []
filled_counts = []
for p in f:
    empty_counts.append(int(p[20:23]))
    filled_counts.append(int(p[12:15]))

print('空缺数序列:', empty_counts)
print('已有图案数:', filled_counts)


print('------2、制作宫格随机数字------')

def generate_non_adjacent_blanks(hs, num_blanks):
    """生成不连续的空格位置"""
    max_blanks = (hs*hs + 1)//2 if hs % 2 == 1 else (hs*hs)//2
    num_blanks = min(num_blanks, max_blanks)  # 确保不超过最大空格数
    
    positions = list(range(hs*hs))
    blanks = []
    
    # 尝试生成不连续的空格
    max_attempts = 1000
    attempts = 0
    
    while len(blanks) < num_blanks and attempts < max_attempts:
        temp_blanks = []
        remaining_positions = positions.copy()
        
        while len(temp_blanks) < num_blanks and remaining_positions:
            pos = random.choice(remaining_positions)
            row = pos // hs
            col = pos % hs
            
            # 检查是否与已有空格相邻
            valid = True
            for blank in temp_blanks:
                blank_row = blank // hs
                blank_col = blank % hs
                # 检查是否在同一行或同一列且相邻
                if (row == blank_row and abs(col - blank_col) == 1) or \
                   (col == blank_col and abs(row - blank_row) == 1):
                    valid = False
                    break
            
            if valid:
                temp_blanks.append(pos)
                # 移除相邻位置
                adjacent_positions = []
                if col > 0: adjacent_positions.append(pos-1)
                if col < hs-1: adjacent_positions.append(pos+1)
                if row > 0: adjacent_positions.append(pos-hs)
                if row < hs-1: adjacent_positions.append(pos+hs)
                
                for adj_pos in adjacent_positions:
                    if adj_pos in remaining_positions:
                        remaining_positions.remove(adj_pos)
            
            remaining_positions.remove(pos) if pos in remaining_positions else None
        
        if len(temp_blanks) == num_blanks:
            blanks = temp_blanks
            break
        
        attempts += 1
    
    # 如果无法生成不连续的空格,则返回随机空格
    if len(blanks) < num_blanks:
        blanks = random.sample(positions, num_blanks)
    
    return blanks

# 修改这里 - 使用empty_counts而不是g
for kk in range(len(empty_counts)):  # 遍历每个空缺数
    ll=['{}'.format(hs)]
    mm=['11']
    nn=['36']
    for r in range(len(ll)):
        if hs ==int(ll[r]):
            db=int(mm[r][0])        
            cb=int(mm[r][1])
            size=int(nn[r])
 
    imagePath=path+r'\\零时Word'
    os.makedirs(imagePath,exist_ok=True) 
    imagePatha=path+r'\06答案卡'
    imagePathq=path+r'\07任务卡'
    os.makedirs(imagePatha,exist_ok=True)
    os.makedirs(imagePathq,exist_ok=True)
 
    db_size = hs*db
    cb_size=  hs*cb
    print('{}宫格排列底{}侧{}共{}套,底边格子数{}'.format(hs,db,cb,db*cb,db_size))
    print('{}宫格排列底{}侧{}共{}套,侧边格子数{}'.format(hs,db,cb,db*cb,cb_size))
 
    bgszm=[]
    for a in range(0,cb_size,hs):
        for b in range(0,db_size,hs):
            bgszm.append('{}{}'.format('%02d'%a,'%02d'%b))
    print(bgszm)
 
    start_coordinates = [(int(s[0:2]), int(s[2:4])) for s in bgszm]
    cell_coordinates = []
 
    for start_coord in start_coordinates:
        i, j = start_coord
        subgrid_coordinates = []
        for x in range(hs):
            for y in range(hs):
                subgrid_coordinates.append((i + x, j + y))
        cell_coordinates.append(subgrid_coordinates)
 
    bg=[]
    for coordinates in cell_coordinates:
        for c in  coordinates:
            print(c)
            s = ''.join(str(num).zfill(2) for num in c)
            print(str(s))
            bg.append(s)
    print(bg)
 
    P=[] 
    for z in range(num):  
        P.clear()
        for j in range(db*cb):
            def generate_sudoku_board():
                board = [[0] * hs for _ in range(hs)]
 
                def filling_board(row, col):
                    if row == hs:
                        return True
                    
                    next_row = row if col < hs-1 else row + 1
                    next_col = (col + 1) % hs
 
                    import math
                    r = int(math.sqrt(hs))
                    print(r)
 
                    box_row = row // r
                    box_col = col // r
 
                    numbers = random.sample(range(1, hs+1), hs)
                    
                    for num in numbers:
                        if hs==4 or hs==9:
                            if num not in board[row] and all(board[i][col] != num for i in range(hs)) and all(num != board[i][j] for i in range(box_row*r, box_row*r+r) for j in range(box_col*r, box_col*r+r)):
                                board[row][col] = num
                                if filling_board(next_row, next_col):
                                    return True
                                board[row][col] = 0
                        else:
                            if num not in board[row] and all(board[i][col] != num for i in range(hs)) and all(num != board[i][j] for i in range(box_row, box_row) for j in range(box_col, box_col)):
                                board[row][col] = num
                                if filling_board(next_row, next_col):
                  

网站公告

今日签到

点亮在社区的每一天
去签到