三阶幻方是一种特殊的方阵,由3行3列的格子组成,其中每个格子都填有一个不同的整数,使得每行、每列和每条对角线上的三个数之和都相等。三阶幻方有8种不同的解法。
24点是一种纸牌游戏,使用一副扑克牌,去掉大小王后,将剩下的52张牌随机排列。游戏的目标是通过组合四张牌的数字和运算符,得到24这个结果。每张牌的面值可以是从1到10的任意整数,而运算符可以是加、减、乘、除。游戏中可以任意改变数字之间的顺序,但是每个数字只能使用一次。如果能找到一种运算方式,让四张牌的数字运算结果等于24,就算胜利。
为了便于学生练习三阶幻方和24点,利用Python编码自动生成练习卷。具体实现如下:
import numpy as np
from docx import Document
from docx.shared import Inches
import random
bHasAnswer = True
# 顺时针旋转90度的函数
def rotate_90_degrees(matrix):
return matrix.T[:, ::-1]
# 生成随机数并加到幻方上的函数
def add_random_numbers(magic_square):
random_number = random_number = np.random.randint(0, 80)
return magic_square + random_number
def generate_magic_square():
magic_square = np.zeros((3, 3), dtype=int) # 初始化一个3x3的零矩阵
magic_square[0, 1] = 1 # 从中间位置开始填充数字1
i, j = 0, 1 # 初始化位置为第一行第二列
for num in range(2, 10): # 从2开始填充到9
# 计算下一个位置
next_i = (i - 1) % 3
next_j = (j + 1) % 3
# 如果下一个位置已经被填充,则尝试另一个位置
if magic_square[next_i, next_j] != 0:
next_i = (i + 1) % 3
next_j = j
# 放置当前数字
magic_square[next_i, next_j] = num
# 更新当前位置
i, j = next_i, next_j
# 计算幻方的常数和
constant_sum = np.sum(magic_square[0]) # 任何一行、列或对角线的和都应该等于这个值
# 验证生成的幻方是否有效
assert np.all(np.sum(magic_square, axis=0) == constant_sum), "Rows do not sum to the constant."
assert np.all(np.sum(magic_square, axis=1) == constant_sum), "Columns do not sum to the constant."
assert np.sum(np.diag(magic_square)) == constant_sum, "Main diagonal does not sum to the constant."
assert np.sum(np.diag(np.fliplr(magic_square))) == constant_sum, "Antidiagonal does not sum to the constant."
randomCount = np.random.randint(0, 3)
for i in range(randomCount):
magic_square = rotate_90_degrees(magic_square)
# 加上随机数
random_magic_square = add_random_numbers(magic_square)
return random_magic_square
# 调用函数并打印生成的幻方
magic_square = generate_magic_square()
print(magic_square)
import random
def is_same_row(coords):
"""判断三个坐标是否在同一行"""
return all(coord[0] == coords[0][0] for coord in coords)
def is_same_col(coords):
"""判断三个坐标是否在同一列"""
return all(coord[1] == coords[0][1] for coord in coords)
def is_same_diagonal(coords):
"""判断三个坐标是否在同一斜线上"""
# 检查主对角线(从左上到右下)
if all(coord[0] - coord[1] == coords[0][0] - coords[0][1] for coord in coords):
return True
# 检查副对角线(从右上到左下)
if all(coord[0] + coord[1] == coords[0][0] + coords[0][1] for coord in coords):
return True
return False
def are_not_same_row_or_col(coords):
"""判断三个坐标是否非同行同列"""
return not (is_same_row(coords) or is_same_col(coords))
def is_in_special_relation(coords):
"""判断三个坐标是否满足同行、同列、同一斜线中的任一条件"""
return is_same_row(coords) or is_same_col(coords) or is_same_diagonal(coords)
# 定义一个函数来检查一个数是否是另一个数的对边数
def is_opposite_side(coord1, coord2):
x1, y1 = coord1
x2, y2 = coord2
return (x1, (y2 + 1) % 3) == coord2 or ((x1 + 1) % 3, y1) == coord2 or (x2, (y1 + 1) % 3) == coord1 or ((x2 + 1) % 3, y2) == coord1
# 随机选择三个坐标,避免两个都是对边坐标
def select_non_paired_coordinates():
# 获取幻方中的所有坐标
coordinates = [(i, j) for i in range(3) for j in range(3)]
# 随机选择一个顶点坐标
first_coord = random.choice(coordinates)
excluded_coords = []
excluded_coords.append(first_coord)
# 从剩下的坐标中随机选择第二个坐标
remaining_coords = [coord for coord in coordinates if coord not in excluded_coords]
second_coord = random.choice(remaining_coords)
excluded_coords.append(second_coord)
remaining_coords = [coord for coord in coordinates if coord not in excluded_coords and not is_in_special_relation([first_coord, second_coord, coord])]
third_coord = random.choice(remaining_coords)
return first_coord, second_coord, third_coord
# 生成题目和答案的函数
def generate_question_and_answer(magic_square):
# 题目表格
question_table = [
[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' ']
]
# 选择位置并打印结果
selected_pos = select_non_paired_coordinates()
print(selected_pos)
for i in range(3):
for j in range(3):
if (i, j) in selected_pos:
question_table[i][j] = magic_square[i][j].astype(str)
# 答案表格
answer_table = magic_square.astype(str).tolist()
# 将表格转换为文本
def table_to_text(table):
return '\n'.join(['\t'.join(row) for row in table])
question = f"\n{table_to_text(question_table)}"
answer = f"\n{table_to_text(answer_table)}"
return question_table, answer_table
# 尝试生成一个答案(这只是一个示例,可能不是有效的答案)
def generate_answer(numbers):
operations = ['+', '-', '*', '/']
for op1 in operations:
for op2 in operations:
for i in range(4):
for j in range(4):
if i != j:
try:
expr = f"({numbers[i]}{op1}{numbers[j]})"
if op1 == '/' and numbers[i] < numbers[j]:
continue
result1 = eval(expr)
for k in range(4):
if k not in (i, j):
for l in range(4):
if l not in (i, j, k):
expr2 = f"({result1}{op2}{numbers[k]})"
if op2 == '/' and numbers[i] < numbers[j]:
continue
result2 = eval(expr2)
if abs(eval(f"{result2}{op2}{numbers[l]}") - 24) < 0.0001:
return f"{numbers[i]}{op1}{numbers[j]}{op2}{numbers[k]}{op2}{numbers[l]} = 24"
except ZeroDivisionError:
continue
return ""
# 生成一个随机的24点题目
def generate_24_point_question():
numbers = [random.randint(1, 9) for _ in range(4)]
numbers.sort() # 对数字进行排序,使得题目更有序
answer = generate_answer(numbers)
while answer == "":
numbers = [random.randint(1, 9) for _ in range(4)]
numbers.sort() # 对数字进行排序,使得题目更有序
answer = generate_answer(numbers)
question = f"用{numbers[0]}、{numbers[1]}、{numbers[2]}、{numbers[3]}这四个数,通过加、减、乘、除(每个数只能用一次),使其结果等于24。请问如何计算?"
return question, answer
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import Cm
from docx.shared import Pt
from docx.enum.text import WD_BREAK
for index in range(20):
# 创建Word文档
doc = Document()
headingStr = '2024年XX小学数学能力比赛三阶幻方和24点练习' + str(index+1)
# 创建页眉
header = doc.sections[0].header
paragraph = header.paragraphs[0]
run = paragraph.add_run(headingStr)
run.font.size = Pt(8) # 设置字体大小
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置居中对齐
# 创建页脚
footer = doc.sections[0].footer
if not footer.paragraphs:
footer_paragraph = footer.add_paragraph()
else:
footer_paragraph = footer.paragraphs[0]
# 添加一些文本到页脚
footer_run = footer_paragraph.add_run(headingStr)
footer_run.font.size = Pt(8) # 设置字体大小
footer_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置居中对齐
# 添加标题
doc.add_heading(headingStr, 1)
doc.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
# 生成20题
doc.add_paragraph('一、请完成以下20题三阶幻方:')
answers = []
for id in range(20):
magic_square = generate_magic_square()
question, answer = generate_question_and_answer(magic_square)
answers.append(answer)
# 添加题目
doc.add_paragraph('幻方题'+str(id+1)+':')
table = doc.add_table(rows=3, cols=3, style='Table Grid')
# 填充表格
for i in range(3):
table.columns[i].width = Cm(1)
for j in range(3):
cell = table.cell(i, j)
cell.text = question[i][j] # 将整数转换为字符串并添加到单元格中
cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
# 添加分隔线
if ((id+1) % 8) == 0:
paragraph = doc.add_paragraph()
paragraph.add_run().add_break(WD_BREAK.PAGE)
doc.add_paragraph('二、请完成以下20题24点:')
answers24 = []
for id in range(20):
question,answer = generate_24_point_question()
answers24.append(answer)
doc.add_paragraph('24点题'+str(id+1)+':'+question+'\n')
if bHasAnswer:
paragraph = doc.add_paragraph()
paragraph.add_run().add_break(WD_BREAK.PAGE)
doc.add_heading('幻方和24点答案:', 1)
for id in range(20):
# 添加答案
doc.add_paragraph('幻方题'+str(id+1)+':')
table = doc.add_table(rows=3, cols=3, style='Table Grid')
answer = answers[id]
# 填充表格
for i in range(3):
table.columns[i].width = Cm(1)
for j in range(3):
cell = table.cell(i, j)
cell.text = answer[i][j] # 将整数转换为字符串并添加到单元格中
cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
# 添加分隔线
if ((id+1) % 8) == 0:
paragraph = doc.add_paragraph()
paragraph.add_run().add_break(WD_BREAK.PAGE)
doc.add_paragraph('\n-----------------------------------------------------------------------------------------------------------')
for id in range(10):
# 添加答案
doc.add_paragraph('24点题'+str(id*2+1)+':'+answers24[id*2] + '\t24点题'+str(id*2+2)+':'+answers24[id*2+1])
# 保存Word文档
doc.save('D://doclibs//'+headingStr+'.docx')