前言
使用C语言绘制一个完整的元素周期表是一个既复杂又细致的任务,因为需要精确地处理大量的元素数据及其多样化的属性。为了提升编码效率和准确性,一个高效的方法是先在Excel等电子表格软件中整理这些元素及其属性,然后利用Excel的批量处理能力来生成C语言代码中所需的数据结构或初始化代码片段。
将一些比较有规律的代码整理到Excel中,然后连接起来。这里为了避免英文引号不能够使用到字符串中,我先使用@符号代替,然后复制到VS中再整体替换为英文引号。
在元素周期表中有一些汉字很生僻,没有找到对应的汉字,所以用两个字来组,看起来有些别扭。
想法
在绘制元素周期表的基础上,我进一步设想将其打造为一个互动式的学习工具,而不仅仅是一个静态的展示。这个设想的核心在于实现元素周期表的联动功能,让用户能够通过鼠标点击任何一个元素,不仅能看到该元素的详细信息(包括名称、符号、原子序数、原子量等),还能听到该元素的发音,从而帮助学生更加直观地记忆和理解。
为了实现这一功能,我计划整合之前提到的C语言语音包调用技术,使得每个元素都能对应一个语音文件或调用语音合成API来生成发音。这样,当用户在图形界面上点击某个元素时,程序就能自动播放该元素的发音,增强了学习的趣味性和效果。
此外,我还考虑将每个元素的化学性质、用途、常见化合物及其化学方程式等详细信息也录入到系统中。当用户点击某个元素后,程序可以展示一个扩展的界面或弹出窗口,专门用于学习该元素的相关知识。这样的设计不仅丰富了元素周期表的内容,还使其成为一个全面的学习资源库。
总的来说,我的目标是将这个元素周期表项目从一个静态的展示转变为一个动态的、互动式的学习器,通过技术手段提升用户的学习体验和效率。这个想法虽然具有挑战性,但也有着广阔的应用前景和教育价值。
源码
///////////////////////////////////////////////////
// 程序名称:绘制元素周期表
// 编译环境:Mictosoft Visual Studio 2022, EasyX_20200315(beta)
// 作 者:luoyh <2864292458@qq.com>
// 最后修改:2024-9-10
// 公 众 号:C语言研究
//
// 计算一下一个格子的大小60个像素
int GZ = 60;
struct PT
{
int X;
int Y;
bool IS_show; // 是否显示
};
typedef struct
{
int atomicNumber; // 原子序数
char symbol[4]; // 元素符号,假设不超过3个字符
char name[50]; // 元素名称
COLORREF color; // 填充颜色
} Element;
Element elements[] =
{
{1,"H","氢",RGB(48,158,253)},
{2,"He","氦",RGB(110,87,9)},
{3,"Li","锂",RGB(111,17,113)},
{4,"Be","铍",RGB(111,17,113)},
{5,"B","硼",RGB(138,42,4)},
{6,"C","碳",RGB(48,158,253)},
{7,"N","氮",RGB(48,158,253)},
{8,"O","氧",RGB(48,158,253)},
{9,"F","氟",RGB(110,87,9)},
{10,"Ne","氖",RGB(110,87,9)},
{11,"Na","钠",RGB(111,17,113)},
{12,"Mg","镁",RGB(111,17,113)},
{13,"Al","铝",RGB(59,0,116)},
{14,"Si","硅",RGB(138,42,4)},
{15,"P","磷",RGB(48,158,253)},
{16,"S","硫",RGB(48,158,253)},
{17,"Cl","氯",RGB(110,87,9)},
{18,"Ar","氩",RGB(110,87,9)},
{19,"K","钾",RGB(111,17,113)},
{20,"Ca","钙",RGB(111,17,113)},
{21,"Sc","钪",RGB(5,46,78)},
{22,"Ti","钛",RGB(5,46,78)},
{23,"V","钒",RGB(5,46,78)},
{24,"Cr","铬",RGB(5,46,78)},
{25,"Mn","锰",RGB(5,46,78)},
{26,"Fe","铁",RGB(5,46,78)},
{27,"Co","钴",RGB(5,46,78)},
{28,"Ni","镍",RGB(5,46,78)},
{29,"Cu","铜",RGB(5,46,78)},
{30,"Zn","锌",RGB(5,46,78)},
{31,"Ga","镓",RGB(59,0,116)},
{32,"Ge","锗",RGB(138,42,4)},
{33,"As","砷",RGB(138,42,4)},
{34,"Se","硒",RGB(48,158,253)},
{35,"Br","溴",RGB(110,87,9)},
{36,"Kr","氪",RGB(110,87,9)},
{37,"Rb","铷",RGB(111,17,113)},
{38,"Sr","锶",RGB(111,17,113)},
{39,"Y","钇",RGB(5,46,78)},
{40,"Zr","锆",RGB(5,46,78)},
{41,"Nb","铌",RGB(5,46,78)},
{42,"Mo","钼",RGB(5,46,78)},
{43,"Tc","锝",RGB(5,46,78)},
{44,"Ru","钌",RGB(5,46,78)},
{45,"Rh","铑",RGB(5,46,78)},
{46,"Pd","钯",RGB(5,46,78)},
{47,"Ag","银",RGB(5,46,78)},
{48,"Cd","镉",RGB(5,46,78)},
{49,"In","铟",RGB(59,0,116)},
{50,"Sn","锡",RGB(59,0,116)},
{51,"Sb","锑",RGB(138,42,4)},
{52,"Te","碲",RGB(138,42,4)},
{53,"I","碘",RGB(110,87,9)},
{54,"Xe","氙",RGB(110,87,9)},
{55,"Cs","铯",RGB(111,17,113)},
{56,"Ba","钡",RGB(111,17,113)},
{57,"La","镧",RGB(120,0,1)},
{58,"Ce","铈",RGB(120,0,1)},
{59,"Pr","镨",RGB(120,0,1)},
{60,"Nd","钕",RGB(120,0,1)},
{61,"Pm","钷",RGB(120,0,1)},
{62,"Sm","钐",RGB(120,0,1)},
{63,"Eu","铕",RGB(120,0,1)},
{64,"Gd","钆",RGB(120,0,1)},
{65,"Tb","铽",RGB(120,0,1)},
{66,"Dy","镝",RGB(120,0,1)},
{67,"Ho","钬",RGB(120,0,1)},
{68,"Er","铒",RGB(120,0,1)},
{69,"Tm","铥",RGB(120,0,1)},
{70,"Yb","镱",RGB(120,0,1)},
{71,"Lu","镥",RGB(120,0,1)},
{72,"Hf","铪",RGB(5,46,78)},
{73,"Ta","钽",RGB(5,46,78)},
{74,"W","钨",RGB(5,46,78)},
{75,"Re","铼",RGB(5,46,78)},
{76,"Os","锇",RGB(5,46,78)},
{77,"Ir","铱",RGB(5,46,78)},
{78,"Pt","铂",RGB(5,46,78)},
{79,"Au","金",RGB(5,46,78)},
{80,"Hg","汞",RGB(5,46,78)},
{81,"Tl","铊",RGB(59,0,116)},
{82,"Pb","铅",RGB(59,0,116)},
{83,"Bi","铋",RGB(59,0,116)},
{84,"Po","钋",RGB(138,42,4)},
{85,"At","砹",RGB(110,87,9)},
{86,"Rn","氡",RGB(110,87,9)},
{87,"Fr","钫",RGB(111,17,113)},
{88,"Ra","镭",RGB(111,17,113)},
{89,"Ac","锕",RGB(0,82,8)},
{90,"Th","钍",RGB(0,82,8)},
{91,"Pa","镤",RGB(0,82,8)},
{92,"U","铀",RGB(0,82,8)},
{93,"Np","镎",RGB(0,82,8)},
{94,"Pu","钚",RGB(0,82,8)},
{95,"Am","镅",RGB(0,82,8)},
{96,"Cm","锔",RGB(0,82,8)},
{97,"Bk","锫",RGB(0,82,8)},
{98,"Cf","锎",RGB(0,82,8)},
{99,"Es","锿",RGB(0,82,8)},
{100,"Fm","镄",RGB(0,82,8)},
{101,"Md","钔",RGB(0,82,8)},
{102,"No","锘",RGB(0,82,8)},
{103,"Lr","铹",RGB(0,82,8)},
{104,"Rf","钅卢",RGB(5,46,78)},
{105,"Db","钅杜",RGB(5,46,78)},
{106,"Sg","钅喜",RGB(5,46,78)},
{107,"Bh","钅波",RGB(5,46,78)},
{108,"Hs","钅黑",RGB(5,46,78)},
{109,"Mt","钅麦",RGB(5,46,78)},
{110,"Ds","钅达",RGB(5,46,78)},
{111,"Rg","钅仑",RGB(5,46,78)},
{112,"Cn","钅哥",RGB(5,46,78)},
{113,"Nh","钅尔",RGB(59,0,116)},
{114,"Fl","钅夫",RGB(59,0,116)},
{115,"Mc","镆",RGB(59,0,116)},
{116,"Lv","钅立",RGB(59,0,116)},
{117,"Ts","石田",RGB(110,87,9)},
{118,"Og","奥气",RGB(110,87,9)},
};
PT pt[126]; // 上部分
PT pt_d[30]; // 下部分
void initPT(); // 初始化元素周期表
void DrawPT(); // 绘制元素周期表
void DrawOther(); // 绘制其他
void DrawNum(LPCSTR str, LPCSTR strnum, int h, int L);
int main()
{
initgraph(1200, 750);
initPT();
DrawPT();
DrawOther();
_getch();
return 0;
}
void initPT()
{
int X = 60;
int Y = 50;
for (int i = 0; i < 126; i++)
{
if (i % 18 == 0)
{
X = 60;
Y += GZ;
}
pt[i].X = X;
pt[i].Y = Y;
X += GZ;
if ((i > 0 && i < 17) || (i > 19 && i < 30) || (i > 37 && i < 48))
{
pt[i].IS_show = false;
}
else
{
pt[i].IS_show = true;
}
}
int X_d = 180;
int Y_d = 520;
for (int i = 0; i < 30; i++)
{
if (i % 15 == 0)
{
X_d = 180;
Y_d += GZ;
}
pt_d[i].X = X_d;
pt_d[i].Y = Y_d;
X_d += GZ;
}
}
void DrawPT()
{
setlinecolor(WHITE);
settextcolor(WHITE);
setbkmode(TRANSPARENT);
settextstyle(20, 0, _T("宋体"));
int NUM = 0;
for (int i = 0; i < 126; i++)
{
if (pt[i].IS_show)
{
setfillcolor(elements[NUM].color);
fillrectangle(pt[i].X, pt[i].Y, pt[i].X + GZ, pt[i].Y + GZ);
settextstyle(20, 0, _T("宋体"));
RECT r = { pt[i].X, pt[i].Y, pt[i].X + GZ, pt[i].Y + GZ };
drawtext(elements[NUM].name, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
settextstyle(15, 0, _T("黑体"));
TCHAR str[25];
_stprintf_s(str, _T("%d"), elements[NUM].atomicNumber);
outtextxy(pt[i].X + 3, pt[i].Y + 1, str);
outtextxy(pt[i].X + 40, pt[i].Y + 45, elements[NUM].symbol);
if (NUM == 56)
{
setfillcolor(elements[NUM].color);
fillrectangle(pt[i].X, pt[i].Y, pt[i].X + GZ, pt[i].Y + GZ);
settextstyle(20, 0, _T("宋体"));
drawtext("镧系", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
settextstyle(15, 0, _T("黑体"));
_stprintf_s(str, _T("%d-%d"), elements[NUM].atomicNumber, elements[70].atomicNumber);
outtextxy(pt[i].X + 3, pt[i].Y + 1, str);
outtextxy(pt[i].X + 18, pt[i].Y + 45, "La-Lu");
NUM = 70;
}
if (NUM == 88)
{
setfillcolor(elements[NUM].color);
fillrectangle(pt[i].X, pt[i].Y, pt[i].X + GZ, pt[i].Y + GZ);
settextstyle(20, 0, _T("宋体"));
drawtext("锕系", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
settextstyle(15, 0, _T("黑体"));
_stprintf_s(str, _T("%d-%d"), elements[NUM].atomicNumber, elements[102].atomicNumber);
outtextxy(pt[i].X + 3, pt[i].Y + 1, str);
outtextxy(pt[i].X + 18, pt[i].Y + 45, "Ac-Lr");
NUM = 102;
}
NUM++;
}
}
int NUM_d = 56;
for (int i = 0; i < 30; i++)
{
setfillcolor(elements[NUM_d].color);
fillrectangle(pt_d[i].X, pt_d[i].Y, pt_d[i].X + GZ, pt_d[i].Y + GZ);
settextstyle(20, 0, _T("宋体"));
RECT r = { pt_d[i].X, pt_d[i].Y, pt_d[i].X + GZ, pt_d[i].Y + GZ };
drawtext(elements[NUM_d].name, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
settextstyle(15, 0, _T("黑体"));
TCHAR str[25];
_stprintf_s(str, _T("%d"), elements[NUM_d].atomicNumber);
outtextxy(pt_d[i].X + 3, pt_d[i].Y + 1, str);
outtextxy(pt_d[i].X + 40, pt_d[i].Y + 45, elements[NUM_d].symbol);
NUM_d++;
if (i == 14)
{
NUM_d = 88;
}
}
}
void DrawOther() // 绘制其他
{
for (int i = 0; i < 7; i++)
{
settextcolor(WHITE);
settextstyle(15, 0, "宋体");
TCHAR str[25];
_stprintf_s(str, _T("%d"), i + 1);
RECT r = { 20,110 + i * GZ, 60, 110 + (i + 1) * GZ };
drawtext(str, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
DrawNum("IA", "1", 0, 0);
DrawNum("VIIIA", "18", 0, 17);
DrawNum("IIA", "2", 1, 1);
DrawNum("IIIB", "3", 3, 2);
DrawNum("IVB", "4", 3, 3);
DrawNum("VB", "5", 3, 4);
DrawNum("VIB", "6", 3, 5);
DrawNum("VIIB", "7", 3, 6);
DrawNum("VIII", "8", 3, 7);
DrawNum("VIII", "9", 3, 8);
DrawNum("VIII", "10", 3, 9);
DrawNum("IB", "11", 3, 10);
DrawNum("IIB", "12", 3, 11);
DrawNum("IIIA", "13", 1, 12);
DrawNum("IVA", "14", 1, 13);
DrawNum("VA", "15", 1, 14);
DrawNum("VIA", "16", 1, 15);
DrawNum("VIIA", "17", 1, 16);
settextcolor(WHITE);
settextstyle(50, 0, "楷体");
RECT r = { 0,0,1200,120 };
drawtext("元素周期表", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
void DrawNum(LPCTSTR str, LPCTSTR strnum, int h, int L)
{
RECT r = { 60 + GZ * L,50 + GZ * h, 120 + GZ * L, 50 + GZ + GZ * h };
drawtext(strnum, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
RECT r1 = { 60 + GZ * L,85 + GZ * h, 120 + GZ * L, 50 + GZ + GZ * h };
drawtext(str, &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
效果图