新手练箫 每个音对应的指法还不熟 又觉得一个一个看指法表太麻烦。于是自己搓了一个练习洞箫的软件,方便在看乐谱的同时,下方直接能显示对应指法。(G调洞箫 指法作5)
如下图所示
2024.2.5 完成初版
开发使用的是上古时代的dev.c 也暂时没有用界面库做 还是有很多瑕疵;
整体实现:
需要在代码中手敲进乐谱和对应汉字 分别放到两个数组里 一个乐符对应一个汉字 乐符没有对应汉字的在汉字数组中用0表示;乐符数组中, 5 6 7表示是低音的sol la xi 13=6+7 是中音的la
1.程序运行时,检测用户输入 如果输入的是1 输出女儿情洞箫乐谱
2.将输入的乐谱和汉字数组转换到定义的结构体中 neq_stru
3.根据转换后的结构体打印乐谱
整体功能比较简陋 之后会根据情况修改更新
工程链接 包括代码cpp 与可执行文件exe
链接:https://pan.baidu.com/s/1FWM6W0Rj7NlfF5PQVNF7Nw?pwd=wcjj
提取码:wcjj
工程代码(好像并没有用到string.h来着)
#include <stdio.h>
#include <string.h>
//G调魈 指法作五
#define NUMPERLINE 15 //每行显示的乐符个数
#define XIAO1 "●\t" //表示该箫孔按下
#define XIAO0 "○\t" //表示该箫孔松开
#define NEQLINE 3 //女儿情行数
typedef struct{
int num; //音阶
char word[2];//汉字 空汉字用两个零字节表示
}music_note;
//女儿情
char finger_table[16][8]={{1,1,1,1,1,1,1,1},//5. sol
{1,1,1,1,1,1,1,0}, //6. la
{1,1,1,1,1,0,1,0}, //7. si
{1,1,1,1,0,0,1,0}, //1 do
{1,1,1,0,0,0,1,0}, //2 re
{1,0,1,0,0,0,1,0}, //3 mi
{0,1,1,1,0,0,1,0}, //4 fa
{0,1,1,1,1,1,1,1}, //5 sol
{1,1,1,1,1,1,1,0}, //6 la
{1,1,1,1,1,0,1,0}, //7 xi
{1,1,1,1,0,0,1,0}, //.1 do
{1,1,1,0,0,0,1,0}, //.2 re
{1,0,1,0,0,0,1,0}, //.3 mi
{0,1,1,1,1,1,1,0}, //.4 fa
{0,1,1,1,1,1,1,1}, //.5 sol
{1,1,1,0,1,1,1,0}, //.6 la
};
//之后要先计算出共有多少音符 方便计算出要分配的结构体大小
char nverqingyin[NEQLINE][30] = {{5,6,8,9,10,7,13,7,5,6},
{6,8,9,10,12,13,8,9,10,11,10},
{10,10,12,13,12,13,6,10,9,8,9,10,5,6,7,10,6,6,8,8}};
char nverqingzi[NEQLINE][50] = {{"鸳鸯双栖蝶0双00飞"},
{"0满园春色惹0人00醉"},
{"0悄悄问圣僧女儿美不美女儿0美0不美00"}};
music_note neq_stru[100];//女儿情数据结构体
void Nverqing(void);
int shownote(music_note * music_stru, int size);
int main(void)
{
int num;
while(1){
scanf("%d",&num);
for(int i = 0;i < 3;i++)
{
for(int j = 0; j<50;j+=2)
{
if(nverqingzi[i][j] == '\0')break;
else if(nverqingzi[i][j] == '0'){
j--;
continue;
}
printf("%c%c ",nverqingzi[i][j],nverqingzi[i][j+1]);
}
printf("\r\n");
}
if(num == 1)Nverqing();
}
return 0;
}
//将全局变量音符和汉字整理为结构体
//模仿乐谱 顺序排列
void Nverqing(void)
{
int pos_in_stru = 0;
int pos_in_lineyin; //当前位于音符数组的第几个字节
int pos_in_linezi; //当前位于歌词数组的第几个字节
//遍历每行
for(int line = 0;line < NEQLINE;line++) {
pos_in_lineyin = 0;
pos_in_linezi = 0;
while(nverqingyin[line][pos_in_lineyin] != 0)
{
neq_stru[pos_in_stru].num = nverqingyin[line][pos_in_lineyin];//乐符赋值 //汉字赋值
if(nverqingzi[line][pos_in_linezi] == '0')
{
neq_stru[pos_in_stru].word[0] = 0;//两个字节都赋值为0表示该音符处无歌词
neq_stru[pos_in_stru].word[1] = 0;
pos_in_linezi++;//加一个字节
}
else
{
neq_stru[pos_in_stru].word[0] = nverqingzi[line][pos_in_linezi];
neq_stru[pos_in_stru].word[1] = nverqingzi[line][pos_in_linezi+1];
pos_in_linezi += 2;//加两个字节
}
pos_in_stru++;
pos_in_lineyin++;
}
}
//test
/*
for(int i = 0; i < 100;i++)
printf("%d %c%c\r\n",neq_stru[i].num,neq_stru[i].word[0],neq_stru[i].word[1]);
*/
shownote(neq_stru,100);
}
int shownote(music_note * music_stru, int size)
{
int pos = 0;
//每行输出NUMPERLINE个音符
for(int i = 0; i < size; i += NUMPERLINE - 1)
{
if(music_stru[i].num < 5 || music_stru[i].num > 20)return 0;
for(int j = 0;j < NUMPERLINE - 1;j++)
{
if(music_stru[i+j].num >= 15)
printf(".\t");
else printf("\t");
}
printf("\r\n");
for(int j = 0;j < NUMPERLINE - 1;j++)
{
if(music_stru[i+j].num > 7 && music_stru[i+j].num <= 14)
printf("%d\t",music_stru[i+j].num-7);
else if(music_stru[i+j].num > 14 && music_stru[i+j].num <= 21)
printf("%d\t",music_stru[i+j].num-14);
else printf("%d\t",music_stru[i+j].num);
}
printf("\r\n");
for(int j = 0;j <= NUMPERLINE - 1;j++)
{
if(music_stru[i+j].num <= 7 && music_stru[i+j].num > 0)
printf(".\t");
else printf("\t");
}
printf("\r\n\r\n");
for(int j = 0;j < NUMPERLINE - 1;j++)
{
if(music_stru[i+j].word[0] == 0 && music_stru[i+j].word[1] == 0)printf("\t");
else printf("%c%c\t",music_stru[i+j].word[0],music_stru[i+j].word[1]);
}
printf("\r\n");
//打印箫孔
for(int line = 0; line < 8; line++)
{
for(int j = 0;j < NUMPERLINE - 1;j++)
{
if(finger_table[music_stru[i+j].num - 5][line] == 0)printf(XIAO0);
else if(finger_table[music_stru[i+j].num - 5][line] == 1)printf(XIAO1);
}
printf("\r\n");
}
}
return 0;
}