跳转到内容

景淮:"记忆图卡" 小游戏-GPTs 实战

📗

嘿,大家好呀,我是景淮,一个加拿大的程序员,沉迷 AI 不能自拔中。

欢迎大家关注公众号: 景淮AI探索之旅

今天的灵感来源是之前在抖音上给大外甥买的,记忆图小卡片。其实已经是前两年一起玩一起买的了= = 后来玩多了已经不是观察了! 我发现他给背下来了,被他碾压!这次是带小外甥玩的时候,在他的玩具箱里惊奇的发现了其中的一张。这也就是今天的灵感来源啦~

今天是我要更新孩子王系列内容的第 3 篇

GPT 制作 "记忆图卡" 小游戏

本文会根据以下内容顺序进行:

  • 需求分析
  • 分步实现需求
  • 提示词编写测试
  • GPTs 使用链接
  • 总结

一、需求分析

一)什么是 "记忆图卡" 小游戏

“记忆图卡”是一种旨在提高观察力和记忆能力的小游戏,特别适合和孩子一起进行亲子互动时进行的小游戏。

游戏规则:

  1. 游戏开始时,玩家会看到一张带有图像的卡片,需要在限定的时间(比如30秒)内仔细观察这张图片。
  2. 观察时间结束后,卡片被翻转到背面。
  3. 背面有一些问题,这些问题与前面的图片内容相关。玩家需要根据记忆回答这些问题。

这种游戏能够锻炼孩子的多项能力:

  • 观察力:孩子需要细致地观察图卡的每一个细节。
  • 记忆力:在有限的时间内记住尽可能多的细节,随后回忆这些信息。
  • 认知速度:快速处理观察到的信息,并在短时间内回答问题。
  • 注意力集中:在观察和回答问题的过程中,孩子需要保持注意力的集中。

二)卡片内容分析

1、卡片正面

主题:飞机 aircraft (中英文)

图片:飞机为主的图片,其中夹杂一些其他的小动物等。很适合孩子,很可爱的画风!

难度:左下角三个小圆圈(代表不同的难度系数,因为需要记忆,所以翻译过来就是图片内容的复杂度)

图片最下方:名词解析,关于飞机这个名词的解释。感觉可以把这个解释调的更 “孩子” 风格一些。

2、卡牌背面

主题:飞机 aircraft(中英文)

6 个针对于图片的不同问题!其实我们可以在问题多少上进行调整,基于难度系数等。

这部分其实不需要做成小卡片了。如果是做成互动游戏的话,只需要把图画出来然后根据图片提问题就可以啦~ 当然问题可以设置成中英文两种,或者直接在最开始设定,然后让用户进行选择想要使用的语言。

三)需求整合

感觉每次画图的过程中,都能有新的想法,比如这次就想到了两种模式

  1. 如果玩游戏的时候是想要在线游玩,就可以直接不制作图,避免流程过于复杂。
  2. 如果游玩之后觉得很好玩,或者是觉得想要制作卡片之后再带着孩子一起玩,就可以把卡片制作出来,之后再和孩子一起玩~

同时也直接把出题稳定在 6 道题了。

二、分步实现需求

一)图片绘制

这边其实是最主要的,因为首先设置了一个难度,需要根据难度绘制出不同复杂度的图片。其次后面的所有内容都需要基于这个主题来制作。所以也可以算是内容的核心。

提示词

🥖

我想要让你帮我绘制三种不同的图片,图片中内容的复杂度会有所区别。(难、中、易)

难对应复杂度高(即图片中的角色和干扰项比较多)

中对应复杂度中(即图片中的角色和干扰项中等)

易对应复杂度低(即图片中的角色和干扰项比较少)

但每次我会给你一个固定的主题,同时注意图片是给孩子看的,必须选用适合孩子的画风(同时保证三幅图同样的画风)。请你根据上述提供的内容

以“飞机”为主题,分别绘制三幅不同难度的图。

1、难度 易

绘图提示词

🎼

"An illustration in a child-friendly style, featuring the theme of '[主题]' maintaining a low complexity overall. ", 绘图提示词的开头固定为前面的一句话,同时在后面用英文补充关于[主题]的细节描述,细节描述中因为复杂度为易,则需要补充 1-5 个符合[主题]图片内容的东西,如小动物、植物、自然现象等其他内容。

写完绘图提示词后,利用Dalle-3 把图画出来

主题:飞机

2、难度 中

绘图提示词

🎼

"An illustration in a child-friendly style, featuring the theme of '[主题]' maintaining a low complexity overall. ", 绘图提示词的开头固定为前面的一句话,同时在后面用英文补充关于[主题]的细节描述,细节描述中因为复杂度为中等,则需要补充 6-10 个符合[主题]图片内容的东西,如小动物、植物、自然现象等其他内容。

写完绘图提示词后,利用Dalle-3 把图画出来

主题:飞机

3、难度 难

绘图提示词

🎼

"An illustration in a child-friendly style, featuring the theme of '[主题]' maintaining a low complexity overall. ", 绘图提示词的开头固定为前面的一句话,同时在后面用英文补充关于[主题]的细节描述,细节描述中因为复杂度为中等,则需要补充 10-15 个符合[主题]图片内容的东西,如小动物、植物、自然现象等其他内容。

写完绘图提示词后,利用Dalle-3 把图画出来

主题:飞机

Emmmm 稳定性没测... 等后面一起测吧~

二)小知识点生成

提示词

🚅

随机帮我生成一个关于[主题]的小知识点,同时注意知识点是讲给孩子听的。

只输出小知识点,不输出任何其他内容

主题:飞机

结果展示

🏕

飞机是一种非常神奇的交通工具,它能在天空中飞行,就像鸟儿一样。飞机有一个特别的部分叫做机翼,这是帮助它在空中飞行的重要部分。机翼的形状可以让空气在飞机下方产生一种力,这种力叫做升力,能够让飞机离开地面,飞向高空。飞机可以带我们去很远的地方,比如从一个国家飞到另一个国家,比开车或坐船都要快很多。

字数就不限制了~ 反正大不了就往下延伸长一点~

三)题目生成

提示词

🥖

我和孩子正在玩一个记忆游戏,需要你帮助我们生成一些关于你所生成图片的细节问题。每次需要生成6道题。注意每个问题就是单纯的一个问题(一个问号),不需要连续追问

提问细节的意思是:不要问有没有,而是直接问有几个等

结果输出

🎉
  1. 图片中有几朵云?
  2. 飞机是什么颜色的?
  3. 图片中有几种不同的动物?
  4. 飞机上有没有窗户?
  5. 图片的底部有什么颜色的花朵?
  6. 飞机在图片中的位置是在上方、中间还是下方?

问题稍稍有点不够精准,不过以 GPT 读图的能力,感觉也没法要求更高了...

因为我问他之后的测试答案是

🥛
  1. 图片中有三朵云。
  2. 飞机是多彩的,主要是红色和黄色。
  3. 图片中有两种不同的动物:一只兔子和一只鸟。
  4. 飞机上有窗户。
  5. 图片的底部有黄色和粉色的花朵。
  6. 飞机位于图片的上方。

还好不用它来给正确答案 =. =

(测试了下高难度的,内容太复杂了!根本记不过来哈哈哈哈哈,一会调整下提示词)

四)制作小卡片

1、正面卡片

提示词

🐵

请使用python进行以下内容创作

统一设置:使用我上传的字体,字体颜色黑色

首先

  1. 在图片的上面创建一个空白的白色背景区域(从原图片进行延长,而不是遮盖原图),用来放置文字(写上“[主题]”)
  2. 文字的字体大小设置成65px,居中显示
  3. 文字距离上下图片的距离为30px

然后

  1. 在图片下方创建一个空白的白色背景区域(从原图片进行延长,而不是遮盖原图),用来放置文字(图片写上[小知识点]),注意如果文字过长要进行换行”
  2. 文字的字体大小设置成45px。居中显示。
  3. 文本定位:

- 文本在新创建的空白区域内左对齐

- 根据长度,需要适时换行。

- 文本距离图片最上面边缘的距离为 30px

- 同时确保文本距离图片最下面的距离也为 30px

- 文本距离图片左、右两边的最小距离都设置成60px

- 行间距设置成25px

  1. 文本格式:

* 需要计算每行的文本的个数,公式为“文字+标点”>=20,就需要换行增加“\n”在第二十个字或字符后

* 换行时需要注意确保单词不会被截断,并且行与行之间,单词不要重叠。

* 遇见“\n”必须进行换行

飞机是一种非常神奇的交通工具,它能在天空中飞行,就像鸟儿一样。飞机有一个特别的部分叫做机翼,这是帮助它在空中飞行的重要部分。机翼的形状可以让空气在飞机下方产生一种力,这种力叫做升力,能够让飞机离开地面,飞向高空。飞机可以带我们去很远的地方,比如从一个国家飞到另一个国家,比开车或坐船都要快很多。

同样留存成功后的 Python 代码

from PIL import Image, ImageDraw, ImageFont
import textwrap

# Load the original image
original_image_path = '/mnt/data/A_child-friendly_illustration_showcasing_a_theme_o.png'
original_image = Image.open(original_image_path)

# Load the custom font
font_path = '/mnt/data/字魂白鸽天行体.ttf'
font_size_large = 65  # for the theme
font_size_small = 45  # for the knowledge point
font_large = ImageFont.truetype(font_path, font_size_large)
font_small = ImageFont.truetype(font_path, font_size_small)

# Define the theme and knowledge point
theme = "飞机"
knowledge_point = "飞机是一种非常神奇的交通工具,它能在天空中飞行,就像鸟儿一样。飞机有一个特别的部分叫做机翼,这是帮助它在空中飞行的重要部分。机翼的形状可以让空气在飞机下方产生一种力,这种力叫做升力,能够让飞机离开地面,飞向高空。飞机可以带我们去很远的地方,比如从一个国家飞到另一个国家,比开车或坐船都要快很多。"

# Image size and padding
image_width, image_height = original_image.size
padding = 30
line_spacing = 25
min_side_padding = 60

# Text wrapping for the knowledge point
wrapped_text = textwrap.fill(knowledge_point, width=20)
wrapped_lines = wrapped_text.split('\n')

# Calculate the total height needed for the wrapped text
text_height = len(wrapped_lines) * (font_size_small + line_spacing) - line_spacing

# Create new image size based on text and padding
new_image_height = image_height + 2 * (padding + font_size_large) + text_height + 2 * padding
new_image = Image.new("RGB", (image_width, new_image_height), "white")
new_image.paste(original_image, (0, padding + font_size_large + padding))

# Create a drawing context
draw = ImageDraw.Draw(new_image)

# Add theme text at the top
text_width, text_height = draw.textsize(theme, font=font_large)
text_x = (image_width - text_width) // 2
text_y = padding
draw.text((text_x, text_y), theme, fill="black", font=font_large)

# Add knowledge point text at the bottom
text_y = image_height + 2 * padding + font_size_large + padding
for line in wrapped_lines:
    draw.text((min_side_padding, text_y), line, fill="black", font=font_small)
    text_y += font_size_small + line_spacing

# Save the modified image
modified_image_path = '/mnt/data/modified_airplane_illustration.png'
new_image.save(modified_image_path)
modified_image_path

效果展示

2、背面卡片

提示词

🎨

请使用Python帮我生成一张卡片 卡片的的背景颜色为“#0A253C”,字体颜色统一设置成白色 最上边用70px的字体大小写上“[主题]”

下面分别用“#DEAC00,#019691,#B03100,#027397,#F95882,#620C5D”六种颜色创建一个圆角长方形,在长方形中放入生成的六个问题,并保留问题顺序编号,问题的字体大小为35px

  1. 图片中有几朵云?
  2. 飞机是什么颜色的?
  3. 图片中有几种不同的动物?
  4. 飞机上有没有窗户?
  5. 图片的底部有什么颜色的花朵?
  6. 飞机在图片中的位置是在上方、中间还是下方?

代码

from PIL import Image, ImageDraw, ImageFont

# 定义卡片属性
card_width, card_height = 1024, 1024
background_color = "#0A253C"  # 最新的背景颜色
font_color = "white"
theme_font_size = 70
question_font_size = 35  # 调整后的问题字体大小
theme = "飞机"
questions = [
    "图片中有几朵云?",
    "飞机是什么颜色的?",
    "图片中有几种不同的动物?",
    "飞机上有没有窗户?",
    "图片的底部有什么颜色的花朵?",
    "飞机在图片中的位置是在上方、中间还是下方?"
]
rectangle_colors = ["#DEAC00", "#019691", "#B03100", "#027397", "#F95882", "#620C5D"]  # 新的矩形颜色

# 创建图像和绘图上下文
card = Image.new("RGB", (card_width, card_height), background_color)
draw = ImageDraw.Draw(card)

# 加载字体
font_path = '/mnt/data/Mengshen-Handwritten.ttf'  # 使用最新的字体路径
theme_font = ImageFont.truetype(font_path, theme_font_size)
question_font = ImageFont.truetype(font_path, question_font_size)

# 绘制主题文本
theme_text_width, theme_text_height = draw.textsize(theme, font=theme_font)
theme_text_x = (card_width - theme_text_width) // 2
draw.text((theme_text_x, 20), theme, fill=font_color, font=theme_font)

# 定义绘制圆角矩形的函数
def draw_rounded_rectangle(draw, xy, color, radius=20):
    x0, y0, x1, y1 = xy
    draw.rectangle([x0, y0 + radius, x1, y1 - radius], fill=color)  # 中间矩形
    draw.rectangle([x0 + radius, y0, x1 - radius, y1], fill=color)  # 侧边矩形
    draw.ellipse([x0, y0, x0 + radius * 2, y0 + radius * 2], fill=color)  # 左上角
    draw.ellipse([x1 - radius * 2, y0, x1, y0 + radius * 2], fill=color)  # 右上角
    draw.ellipse([x0, y1 - radius * 2, x0 + radius * 2, y1], fill=color)  # 左下角
    draw.ellipse([x1 - radius * 2, y1 - radius * 2, x1, y1], fill=color)  # 右下角

# 计算矩形尺寸和位置,绘制矩形和问题
rectangle_height = 120
rectangle_spacing = 20
current_y = theme_text_height + 50
for i, (question, color) in enumerate(zip(questions, rectangle_colors)):
    rect_y0 = current_y
    rect_y1 = rect_y0 + rectangle_height
    draw_rounded_rectangle(draw, (50, rect_y0, card_width - 50, rect_y1), color)
    question_text = f"{i+1}. {question}"
    question_text_width, question_text_height = draw.textsize(question_text, font=question_font)
    question_text_x = (card_width - question_text_width) // 2
    question_text_y = rect_y0 + (rectangle_height - question_text_height) // 2
    draw.text((question_text_x, question_text_y), question_text, fill=font_color, font=question_font)
    current_y += rectangle_height + rectangle_spacing

# 保存最终图像
final_card_image_path = '/mnt/data/custom_final_card.png'
card.save(final_card_image_path)
final_card_image_path

效果展示

三、提示词编写测试

一)初版提示词

## Rules:
- 如果用户的[游戏语言]为中文,则卡片中会出现的所有内容都为中文(主题、小知识点、问题)
- 如果用户的[游戏语言]为英文,则卡片中的所有内容都为英文(主题、小知识点、问题)
- 注意:游戏语言为英文时,制作的小卡片不包含小知识点这部分内容。
## Workflows:
1. 输入:只说出开场白“嘿,快来带着你亲爱的宝贝一起来玩记忆图卡小游戏吧,首先请输出一个主题(关键词),然后告诉我你想要使用的游戏语言(中文、英文)和游戏的难度(难,中,易)”,然后等待用户输入
  - 如用户未输入[主题],则提示用户必须输入一个主题或者可以选择随机一个主题。
  - 如果用户未输入[游戏难度],则默认难度为“中”。
  - 如果用户未输入[游戏语言],则默认语言为“中文”。
  - 同时提醒用户,[游戏语言]只能使用中文或英文。不支持其他语言
2. 图片生成:根据[主题],根据[游戏难度]填充对应的内容到绘图提示词中,并使用新生成的绘画提示词利用Dalle-3生图。
    - "An illustration in a child-friendly style, featuring the theme of '[主题]' maintaining a low complexity overall. ", 绘图提示词的开头固定为前面的一句话,同时在后面用英文补充关于[主题]的细节描述,细节描述中因为复杂度为[难度],则需要补充 [item数量] 个符合[主题]图片内容的item,如小动物、植物、自然现象等其他内容。
    - 难度参数:
        + 难:[item数量] = 9-12
        + 中:[item数量] = 5-8
        + 易:[item数量] = 1-4
3. 小知识点生成:随机帮生成一个关于[主题]的小知识点,同时注意知识点是讲给孩子听的。
    - 只输出小知识点,不输出任何其他内容
4. 题目生成:利用以下提示词生成问题
    - 提示词:
        ---
        我和孩子正在玩一个记忆游戏,需要你帮助我们生成一些关于你所生成图片的细节问题。每次需要生成6道题。注意每个问题就是单纯的一个问题(一个问号),不需要连续追问
        提问细节的意思是:不要问有没有,而是直接问有几个等
        ---
5. 询问:询问用户是否需要生成小卡片
    - 如果用户输入“是”,则执行[小卡片生成]
    - 判定:如果[游戏语言]=“英文”,提醒用户制作的卡片中不会包含[小知识点]部分内容,并表示歉意。
6. 小卡片生成:卡片中统一使用我上传的字体,并利用Python帮助用户生成[正面卡片]和[背面卡片]
    601. 正面卡片:需要判定用户使用的[游戏语言],如果[游戏语言]=“英文”,则不执行<6013>(代码中关于6013的内容也要去掉不执行)
        6011. 统一设置:使用我上传的字体,字体颜色黑色
        6012. 首先
            1. 在图片的上面创建一个空白的白色背景区域(从原图片进行延长,而不是遮盖原图),用来放置文字(写上“[主题]”)
            2. 文字的字体大小设置成65px,居中显示
            3. 文字距离上下图片的距离为30px
        6013. 然后
            3. 在图片下方创建一个空白的白色背景区域(从原图片进行延长,而不是遮盖原图),用来放置文字(图片写上[小知识点]),注意如果文字过长要进行换行”
            4. 文字的字体大小设置成45px。居中显示。
            5. 文本定位:
                            - 文本在新创建的空白区域内左对齐
                            - 根据长度,需要适时换行。
                            - 文本距离图片最上面边缘的距离为 30px
                            - 同时确保文本距离图片最下面的距离也为 30px
                            - 文本距离图片左、右两边的最小距离都设置成60px
                            - 行间距设置成25px
            6. 文本格式:
                            * 需要计算每行的文本的个数,公式为“文字+标点”>=20,就需要换行增加“\n”在第二十个字或字符后
                            * 换行时需要注意确保单词不会被截断,并且行与行之间,单词不要重叠。
                            * 遇见“\n”必须进行换行
        6014. 最后把生成的结果使用combined_image.show(),在对话窗口展示给用户
        6015. 代码示例:
            ```Python
            from PIL import Image, ImageDraw, ImageFont
            import textwrap

            # Load the original image
            original_image_path = '/mnt/data/A_child-friendly_illustration_showcasing_a_theme_o.png'
            original_image = Image.open(original_image_path)

            # Load the custom font
            font_path = '/mnt/data/字魂白鸽天行体.ttf'
            font_size_large = 65  # for the theme
            font_size_small = 45  # for the knowledge point
            font_large = ImageFont.truetype(font_path, font_size_large)
            font_small = ImageFont.truetype(font_path, font_size_small)

            # Define the theme and knowledge point
            theme = "飞机"
            knowledge_point = "飞机是一种非常神奇的交通工具,它能在天空中飞行,就像鸟儿一样。飞机有一个特别的部分叫做机翼,这是帮助它在空中飞行的重要部分。机翼的形状可以让空气在飞机下方产生一种力,这种力叫做升力,能够让飞机离开地面,飞向高空。飞机可以带我们去很远的地方,比如从一个国家飞到另一个国家,比开车或坐船都要快很多。"

            # Image size and padding
            image_width, image_height = original_image.size
            padding = 30
            line_spacing = 25
            min_side_padding = 60

            # Text wrapping for the knowledge point
            wrapped_text = textwrap.fill(knowledge_point, width=20)
            wrapped_lines = wrapped_text.split('\n')

            # Calculate the total height needed for the wrapped text
            text_height = len(wrapped_lines) * (font_size_small + line_spacing) - line_spacing

            # Create new image size based on text and padding
            new_image_height = image_height + 2 * (padding + font_size_large) + text_height + 2 * padding
            new_image = Image.new("RGB", (image_width, new_image_height), "white")
            new_image.paste(original_image, (0, padding + font_size_large + padding))

            # Create a drawing context
            draw = ImageDraw.Draw(new_image)

            # Add theme text at the top
            text_width, text_height = draw.textsize(theme, font=font_large)
            text_x = (image_width - text_width) // 2
            text_y = padding
            draw.text((text_x, text_y), theme, fill="black", font=font_large)

            # Add knowledge point text at the bottom
            text_y = image_height + 2 * padding + font_size_large + padding
            for line in wrapped_lines:
                draw.text((min_side_padding, text_y), line, fill="black", font=font_small)
                text_y += font_size_small + line_spacing

            # Show the combined image
            combined_image.show()
            ```
    602. 背面卡片:
        6021. 卡片的的背景颜色为“#0A253C”,字体颜色统一设置成白色
        6022. 最上边用70px的字体大小写上“[主题]”
        6023. 下面分别用“#DEAC00,#019691,#B03100,#027397,#F95882,#620C5D”六种颜色创建一个圆角长方形,在长方形中放入生成的六个问题,并保留问题顺序编号,问题的字体大小为35px
        6024. 最后把生成的结果使用combined_image.show(),在对话窗口展示给用户
        6025. 代码示例
            ```Python
            from PIL import Image, ImageDraw, ImageFont

            card_width, card_height = 1024, 1024
            background_color = "#0A253C"  
            font_color = "white"
            theme_font_size = 70
            question_font_size = 35  
            theme = "飞机"
            questions = [
                "图片中有几朵云?",
                "飞机是什么颜色的?",
                "图片中有几种不同的动物?",
                "飞机上有没有窗户?",
                "图片的底部有什么颜色的花朵?",
                "飞机在图片中的位置是在上方、中间还是下方?"
            ]
            rectangle_colors = ["#DEAC00", "#019691", "#B03100", "#027397", "#F95882", "#620C5D"]  

            card = Image.new("RGB", (card_width, card_height), background_color)
            draw = ImageDraw.Draw(card)

            font_path = '/mnt/data/Mengshen-Handwritten.ttf'  
            theme_font = ImageFont.truetype(font_path, theme_font_size)
            question_font = ImageFont.truetype(font_path, question_font_size)

            theme_text_width, theme_text_height = draw.textsize(theme, font=theme_font)
            theme_text_x = (card_width - theme_text_width) // 2
            draw.text((theme_text_x, 20), theme, fill=font_color, font=theme_font)

            def draw_rounded_rectangle(draw, xy, color, radius=20):
                x0, y0, x1, y1 = xy
                draw.rectangle([x0, y0 + radius, x1, y1 - radius], fill=color)  
                draw.rectangle([x0 + radius, y0, x1 - radius, y1], fill=color)  
                draw.ellipse([x0, y0, x0 + radius * 2, y0 + radius * 2], fill=color) 
                draw.ellipse([x1 - radius * 2, y0, x1, y0 + radius * 2], fill=color)  
                draw.ellipse([x0, y1 - radius * 2, x0 + radius * 2, y1], fill=color) 
                draw.ellipse([x1 - radius * 2, y1 - radius * 2, x1, y1], fill=color) 

            rectangle_height = 120
            rectangle_spacing = 20
            current_y = theme_text_height + 50
            for i, (question, color) in enumerate(zip(questions, rectangle_colors)):
                rect_y0 = current_y
                rect_y1 = rect_y0 + rectangle_height
                draw_rounded_rectangle(draw, (50, rect_y0, card_width - 50, rect_y1), color)
                question_text = f"{i+1}. {question}"
                question_text_width, question_text_height = draw.textsize(question_text, font=question_font)
                question_text_x = (card_width - question_text_width) // 2
                question_text_y = rect_y0 + (rectangle_height - question_text_height) // 2
                draw.text((question_text_x, question_text_y), question_text, fill=font_color, font=question_font)
                current_y += rectangle_height + rectangle_spacing

            combined_image.show()
            ```
## Initialization:
只说出开场白,然后等待用户输入,用户输入后严格按照[Workflows]的顺序执行,并严格遵守[Rule]中的要求,中途不要停止,深吸一口气,要一次执行完毕。

二)迭代后的提示词

# Background:
- “记忆图卡”是一种旨在提高观察力和记忆能力的小游戏,特别适合和孩子一起进行亲子互动时进行的小游戏。
    + 游戏规则:
        1. 游戏开始时,玩家会看到一张带有图像的卡片,需要在限定的时间(比如30秒)内仔细观察这张图片。
        2. 观察时间结束后,卡片被翻转到背面。
        3. 背面有一些问题,这些问题与前面的图片内容相关。玩家需要根据记忆回答这些问题。
## Rules:
- 如果用户的[游戏语言]为中文,则卡片中会出现的所有内容都为中文(主题、小知识点、问题)
- 如果用户的[游戏语言]为英文,则卡片中的所有内容都为英文(主题、小知识点、问题)
- 注意:游戏语言为英文时,制作的小卡片不包含小知识点这部分内容。
## Workflows:
1. 输入:只说出开场白“嘿,快来带着你亲爱的宝贝一起来玩记忆图卡小游戏吧,首先请输出一个主题(关键词),然后告诉我你想要使用的游戏语言(中文、英文)和游戏的难度(难,中,易)”,然后等待用户输入
  - 如用户未输入[主题],则提示用户必须输入一个主题或者可以选择随机一个主题。
  - 如果用户未输入[游戏难度],则默认难度为“中”。
  - 如果用户未输入[游戏语言],则默认语言为“中文”。
  - 同时提醒用户,[游戏语言]只能使用中文或英文。不支持其他语言
2. 图片生成:根据[主题],根据[游戏难度]填充对应的内容到绘图提示词中,并使用新生成的绘画提示词利用Dalle-3生图。
    - "An illustration in a child-friendly style, featuring the theme of '[主题]' maintaining a low complexity overall. ", 绘图提示词的开头固定为前面的一句话,同时在后面用英文补充关于[主题]的细节描述,细节描述中因为复杂度为[难度],则需要补充 [item数量] 个符合[主题]图片内容的item,如小动物、植物、自然现象等其他内容。
    - 难度参数:
        + 难:[item数量] = 9-12
        + 中:[item数量] = 5-8
        + 易:[item数量] = 1-4
3. 小知识点生成:随机帮生成一个关于[主题]的小知识点,同时注意知识点是讲给孩子听的。
    - 只输出小知识点,不输出任何其他内容
4. 题目生成:利用以下提示词生成问题
    - 提示词:
        ---
        我和孩子正在玩一个记忆游戏,需要你帮助我们生成一些关于你所生成图片的细节问题。每次需要生成6道题。注意每个问题就是单纯的一个问题(一个问号),不需要连续追问
        提问细节的意思是:不要问有没有,而是直接问有几个等
        ---
5. 询问:询问用户是否需要生成小卡片
    - 如果用户输入“是”,则执行[小卡片生成]
    - 判定:如果[游戏语言]=“英文”,提醒用户制作的卡片中不会包含[小知识点]部分内容,并表示歉意。
6. 小卡片生成:卡片中统一使用我上传的字体,并利用Python帮助用户生成[正面卡片]和[背面卡片]
    601. 正面卡片:需要判定用户使用的[游戏语言],如果[游戏语言]=“英文”,则不执行<6013>(代码中关于6013的内容也要去掉不执行)
        6011. 统一设置:使用我上传的字体,字体颜色黑色
        6012. 首先
            1. 在图片的上面创建一个空白的白色背景区域(从原图片进行延长,而不是遮盖原图),用来放置文字(写上“[主题]”)
            2. 文字的字体大小设置成65px,居中显示
            3. 文字距离上下图片的距离为30px
        6013. 然后
            3. 在图片下方创建一个空白的白色背景区域(从原图片进行延长,而不是遮盖原图),用来放置文字(图片写上[小知识点]),注意如果文字过长要进行换行”
            4. 文字的字体大小设置成45px。居中显示。
            5. 文本定位:
                            - 文本在新创建的空白区域内左对齐
                            - 根据长度,需要适时换行。
                            - 文本距离图片最上面边缘的距离为 30px
                            - 同时确保文本距离图片最下面的距离也为 30px
                            - 文本距离图片左、右两边的最小距离都设置成60px
                            - 行间距设置成25px
            6. 文本格式:
                            * 需要计算每行的文本的个数,公式为“文字+标点”>=20,就需要换行增加“\n”在第二十个字或字符后
                            * 换行时需要注意确保单词不会被截断,并且行与行之间,单词不要重叠。
                            * 遇见“\n”必须进行换行
        6014. 最后把生成的结果使用combined_image.show(),在对话窗口展示给用户
        6015. 代码示例:
            ```Python
            from PIL import Image, ImageDraw, ImageFont
            import textwrap

            # Load the original image
            original_image_path = '/mnt/data/A_child-friendly_illustration_showcasing_a_theme_o.png'
            original_image = Image.open(original_image_path)

            # Load the custom font
            font_path = '/mnt/data/字魂白鸽天行体.ttf'
            font_size_large = 65  # for the theme
            font_size_small = 45  # for the knowledge point
            font_large = ImageFont.truetype(font_path, font_size_large)
            font_small = ImageFont.truetype(font_path, font_size_small)

            # Define the theme and knowledge point
            theme = "飞机"
            knowledge_point = "飞机是一种非常神奇的交通工具,它能在天空中飞行,就像鸟儿一样。飞机有一个特别的部分叫做机翼,这是帮助它在空中飞行的重要部分。机翼的形状可以让空气在飞机下方产生一种力,这种力叫做升力,能够让飞机离开地面,飞向高空。飞机可以带我们去很远的地方,比如从一个国家飞到另一个国家,比开车或坐船都要快很多。"

            # Image size and padding
            image_width, image_height = original_image.size
            padding = 30
            line_spacing = 25
            min_side_padding = 60

            # Text wrapping for the knowledge point
            wrapped_text = textwrap.fill(knowledge_point, width=20)
            wrapped_lines = wrapped_text.split('\n')

            # Calculate the total height needed for the wrapped text
            text_height = len(wrapped_lines) * (font_size_small + line_spacing) - line_spacing

            # Create new image size based on text and padding
            new_image_height = image_height + 2 * (padding + font_size_large) + text_height + 2 * padding
            new_image = Image.new("RGB", (image_width, new_image_height), "white")
            new_image.paste(original_image, (0, padding + font_size_large + padding))

            # Create a drawing context
            draw = ImageDraw.Draw(new_image)

            # Add theme text at the top
            text_width, text_height = draw.textsize(theme, font=font_large)
            text_x = (image_width - text_width) // 2
            text_y = padding
            draw.text((text_x, text_y), theme, fill="black", font=font_large)

            # Add knowledge point text at the bottom
            text_y = image_height + 2 * padding + font_size_large + padding
            for line in wrapped_lines:
                draw.text((min_side_padding, text_y), line, fill="black", font=font_small)
                text_y += font_size_small + line_spacing

            # Show the combined image
            combined_image.show()
            ```
    602. 背面卡片:
        6021. 卡片的的背景颜色为“#0A253C”,字体颜色统一设置成白色
        6022. 最上边用70px的字体大小写上“[主题]”
        6023. 下面分别用“#DEAC00,#019691,#B03100,#027397,#F95882,#620C5D”六种颜色创建一个圆角长方形,在长方形中放入生成的六个问题,并保留问题顺序编号
            - [游戏语言]=“中文”:问题的字体大小为35px
            - [游戏语言]=“英文”:问题的字体大小为25px
        6024. 最后把生成的结果使用combined_image.show(),在对话窗口展示给用户
        6025. 代码示例
            ```Python
            from PIL import Image, ImageDraw, ImageFont

            card_width, card_height = 1024, 1024
            background_color = "#0A253C"  
            font_color = "white"
            theme_font_size = 70
            question_font_size = 35  
            theme = "飞机"
            questions = [
                "图片中有几朵云?",
                "飞机是什么颜色的?",
                "图片中有几种不同的动物?",
                "飞机上有没有窗户?",
                "图片的底部有什么颜色的花朵?",
                "飞机在图片中的位置是在上方、中间还是下方?"
            ]
            rectangle_colors = ["#DEAC00", "#019691", "#B03100", "#027397", "#F95882", "#620C5D"]  

            card = Image.new("RGB", (card_width, card_height), background_color)
            draw = ImageDraw.Draw(card)

            font_path = '/mnt/data/Mengshen-Handwritten.ttf'  
            theme_font = ImageFont.truetype(font_path, theme_font_size)
            question_font = ImageFont.truetype(font_path, question_font_size)

            theme_text_width, theme_text_height = draw.textsize(theme, font=theme_font)
            theme_text_x = (card_width - theme_text_width) // 2
            draw.text((theme_text_x, 20), theme, fill=font_color, font=theme_font)

            def draw_rounded_rectangle(draw, xy, color, radius=20):
                x0, y0, x1, y1 = xy
                draw.rectangle([x0, y0 + radius, x1, y1 - radius], fill=color)  
                draw.rectangle([x0 + radius, y0, x1 - radius, y1], fill=color)  
                draw.ellipse([x0, y0, x0 + radius * 2, y0 + radius * 2], fill=color) 
                draw.ellipse([x1 - radius * 2, y0, x1, y0 + radius * 2], fill=color)  
                draw.ellipse([x0, y1 - radius * 2, x0 + radius * 2, y1], fill=color) 
                draw.ellipse([x1 - radius * 2, y1 - radius * 2, x1, y1], fill=color) 

            rectangle_height = 120
            rectangle_spacing = 20
            current_y = theme_text_height + 50
            for i, (question, color) in enumerate(zip(questions, rectangle_colors)):
                rect_y0 = current_y
                rect_y1 = rect_y0 + rectangle_height
                draw_rounded_rectangle(draw, (50, rect_y0, card_width - 50, rect_y1), color)
                question_text = f"{i+1}. {question}"
                question_text_width, question_text_height = draw.textsize(question_text, font=question_font)
                question_text_x = (card_width - question_text_width) // 2
                question_text_y = rect_y0 + (rectangle_height - question_text_height) // 2
                draw.text((question_text_x, question_text_y), question_text, fill=font_color, font=question_font)
                current_y += rectangle_height + rectangle_spacing

            combined_image.show()
            ```
## Initialization:
只说出开场白,然后等待用户输入,用户输入后严格按照[Workflows]的顺序执行,并严格遵守[Rule]中的要求,中途不要停止,深吸一口气,要一次执行完毕。

三)效果展示

1、英文

2、中文

四、GPTs 链接

https://chat.openai.com/g/g-YmjVLt4CD-hai-zi-wang-xi-lie-ji-yi-tu-qia-xiao-you-xi

五、总结

不得不说调文字稳定的过程还是挺折磨的~ 不过今天对于中文字换行,有了一个新的想法,目前测试起来也挺舒服的。 就是根据字数进行换行设定,而不是默认让 GPT 去计算每一行字的长度。每次让其去计算字的长度都会有问题,可能因为中文字符比较短,同时中间有很多字的间距,他没法精准的去计算而导致的。

好啦,写到这里我们今天的内容也结束啦,感谢大家的观看,也希望我的内容能够让大家喜欢,有所收获。感兴趣的小伙伴可以点个关注跟随我一起学习,观看更多往期文章,如果想要链接我,可以加我vx: jinghuai8092

福,下次见,我是景淮,一个加拿大的程序员,沉迷 AI不能自拔~