VS2013写智能电子钢琴

本文介绍了一个基于VS2013的智能电子钢琴程序设计,该程序通过C/C++实现自动播放示例音乐,并允许用户通过键盘输入演奏不同的音符。程序还包括了图形界面,能够显示钢琴键状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

软件:VS2013-->win32应用程序

语言: C/C++

程序功能:   运行程序后自动播放一段示例音乐,开始自由演奏(用户再按下1~7数字键发出对应音符)

下载地址:https://download.youkuaiyun.com/download/cai_niaocainiao/10618216

规划,流程:(音乐文件和图片文件放在智能电子钢琴文件夹里)
    1.播放音乐                //音乐格式为mp3
        1.1 音乐文件
        1.2 打开音乐文件
        1.3 播放音乐文件
        1.4 关闭音乐文件
    2.按键控制音乐播放
        2.1 getch获取按键
        2.2 switch调用不同函数播不同音乐文件
    3.加上界面                 //图片格式为.bmp
        3.1 一开始做好界面
            贴图三部曲:定义变量 加载图片 贴图
        3.2 按下对应的按键就用灰色把对应的钢琴键覆盖
        3.3 等待一段时间后还原
    4.智能自动播放示例音乐
        4.1 程序模拟按键
            按键消息
            SendMessage

  5.播放完示例音乐,后出现一张start图片停留2000ms后恢复钢琴界面

步骤:

1.创建win32应用程序(Visual c++ -->win32应用程序)

注:去掉安全开发生命周期(SDL)检查,否则一些功能将用不了


2.项目属性-->配置属性-->常规-->字符集-->使用多字节字符集

3.代码:

// 智能电子钢琴.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"
#include "Mmsystem.h"
#include "conio.h"  //getch的头文件
#include <graphics.h> // 图形库的头文件,需要先安装好easyx


//图片宽
#define WIDTH 100
//图片高
#define HEIGH 400
//定时器间隔时间
#define SPACE 50

//贴图,定义变量
IMAGE bmp[7];
IMAGE down;
IMAGE start;
HWND G_hWnd;

#pragma comment(lib,"Winmm.lib")

void playMusic(char *m)       //m为传进来的音乐名
{
	int m_in;
	char buff[256] = { 0 };  //初始化为空
	sprintf(buff, "open sounds\\%s alias m", m);  //alias m别名,将m写入字符串里
	//对应位置贴灰色图片
	m_in = m[0] - '0'; //转换成Int型
	printf("n:%d\n", m_in);
	putimage((m_in - 1)*WIDTH, 0, &down);
	//1 播放音乐
	mciSendString(buff, NULL, NULL, NULL);//设置字节符为多字节字符集,解决不匹配问题。
	mciSendString("play m", NULL, NULL, NULL);
	Sleep(50); //延迟50ms
	//贴回对应图片
	putimage((m_in - 1)*WIDTH, 0, &bmp[m_in-1]);
	Sleep(200);
	mciSendString("close m", NULL, NULL, NULL);

}

//贴图的准备工作
void initDraw()
{
	char buff[256];
	//1制作窗口
	G_hWnd=initgraph(7 * WIDTH, HEIGH,SHOWCONSOLE);
	//加载图片
	loadimage(&down, "images\\down.bmp");
	loadimage(&start, "images\\start.bmp");
	for (int i = 0; i < 7; i++)
	{
		memset(buff, 0, 256);//清空数组
		sprintf(buff, "images\\%d.bmp", i + 1);
		loadimage(&bmp[i], buff);
	}
}


void drawbeginWindow()             //画开始界面
{
	for (int i = 0; i < 7; i++)
	{
		putimage(i*WIDTH, 0, &bmp[i]);
	}
}

int array[] = { 6, 0, 6, 0, 3, 0, 6, 0, 0, 0, 6, 0, 6, 0,
5, 0, 6, 0, 7, 0, 5, 0, 3, 0, 4, 0, 4, 0, 4, 0, 5, 0, 4, 0, 4, 0, 4, 0, 3, 0, 2, 0, 3, 0, 3, 0 };

int len = sizeof(array) / sizeof(array[0]);//获取数组元素个数
int index = 0;


//每隔固定时间做的事情
VOID timeProc(HWND G_hWnd, UINT uInt, UINT_PTR ptr,DWORD dWord)
{
	//防止数组越界
	if (index >= len)
	{
		KillTimer(G_hWnd, 10086);  //结束自动播放
		putimage(0, 0, &start);       //贴start图片
		Sleep(2000);
		//贴回对应图片
		drawbeginWindow();

	}

	switch (array[index]){
	case 1:
		SendMessage(G_hWnd, WM_KEYDOWN, 49, NULL);
		break;
	case 2:
		SendMessage(G_hWnd, WM_KEYDOWN, 50, NULL);
		break;
	case 3:
		SendMessage(G_hWnd, WM_KEYDOWN, 51, NULL);
		break;
	case 4:
		SendMessage(G_hWnd, WM_KEYDOWN, 52, NULL);
		break;
	case 5:
		SendMessage(G_hWnd, WM_KEYDOWN, 53, NULL);
		break;
	case 6:
		SendMessage(G_hWnd, WM_KEYDOWN, 54, NULL);
		break;
	case 7:
		SendMessage(G_hWnd, WM_KEYDOWN, 55, NULL);
		break;
	}
	index++;

}

int _tmain(int argc, _TCHAR* argv[])
{
	initDraw();
	// 2 按键控制
	int ch;  //用来保存按键虚拟键值
	DWORD id;  //线程的身份证号
	//定时器 每隔固定时间就响一下
	SetTimer(G_hWnd, 10086, SPACE, (TIMERPROC)timeProc);       //10086是定时器的id
	
	while (1)
	{
		drawbeginWindow();
		ch = getch();
		printf("%d\n", ch);
		switch (ch)
		{
		case 49:   //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "1.mp3", NULL, &id);
			break;
		case 50:  //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "2.mp3", NULL, &id);
			break;
		case 51:   //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "3.mp3", NULL, &id); 
			break;
		case 52:   //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "4.mp3", NULL, &id);
			break;
		case 53:   //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "5.mp3", NULL, &id);
			break;
		case 54:  //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "6.mp3", NULL, &id);
			break;
		case 55:  //创建线程
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)playMusic, "7.mp3", NULL, &id);
			break;
		}
	}
	while (1);
	return 0;
}

结果部分截图:

程序运行后:

播放完示例音乐,出现图片:

start图片停留2000ms后,即可自由演奏

### PPODPOGRPO 算法的区别与联系 #### Proximal Policy Optimization (PPO) Proximal Policy Optimization 是一种强化学习方法,旨在通过引入信任区域来稳定策略更新过程。该算法利用剪切函数限制新旧策略之间的差异,从而防止参数更新过大导致性能下降。PPO 结合了 TRPO 的稳定性以及简单易实现的特点,在实践中表现出良好的收敛速度和鲁棒性[^1]。 ```python def ppo_update(policy_net, old_policy_net, optimizer, states, actions, rewards): advantages = compute_advantages(states, rewards) for _ in range(update_epochs): new_log_probs = policy_net.log_prob(actions) old_log_probs = old_policy_net.log_prob(actions).detach() ratio = torch.exp(new_log_probs - old_log_probs) surr1 = ratio * advantages surr2 = torch.clamp(ratio, 1.0 - clip_param, 1.0 + clip_param) * advantages loss = -torch.min(surr1, surr2).mean() optimizer.zero_grad() loss.backward() optimizer.step() ``` #### Direct Preference Optimization (DPO) Direct Preference Optimization 则是从人类反馈中直接优化模型的行为分布,而不需要显式的奖励信号。这种方法能够更高效地利用少量高质量的人类评价数据,并且可以避免传统基于奖励塑造的方法所带来的偏差问题。DPO 使用对比损失函数训练模型以最大化所选行为序列相对于未选行为的概率比值。 ```python def dpo_loss(selected_seq_logits, unselected_seq_logits): logits_diff = selected_seq_logits - unselected_seq_logits losses = F.softplus(-logits_diff) return losses.mean() for epoch in range(num_epochs): for batch in data_loader: selected_seq_logits, unselected_seq_logits = model(batch) loss = dpo_loss(selected_seq_logits, unselected_seq_logits) optimizer.zero_grad() loss.backward() optimizer.step() ``` #### Gradient Ratio Policy Optimization (GRPO) Gradient Ratio Policy Optimization 提出了调整正负梯度系数的概念,实验结果显示这能显著提升在线环境下的表现。特别是当采用细粒度步长感知型梯度比率时(即 GRPO+PS),其效果要好于仅考虑整体比例的情况(如 GRPO+OS)。这种机制允许更加灵活地控制不同阶段的学习速率变化趋势,有助于提高最终决策质量[^2]。 ```python class GRPOTrainer: def __init__(self, ...): self.positive_coefficient = ... self.negative_coefficient = ... def update(self, positive_gradients, negative_gradients): adjusted_positive_grads = positive_gradients * self.positive_coefficient adjusted_negative_grads = negative_gradients * self.negative_coefficient final_gradients = adjusted_positive_grads - adjusted_negative_grads apply_gradients(final_gradients) ``` 综上所述,虽然三种算法都属于强化学习领域内的改进方案,但各自侧重点有所不同:PPO 关注如何平稳有效地完成单次迭代;DPO 注重从有限数量的偏好样本里提取有用信息来进行指导;GRPO 则探索了动态调节梯度权重对于加速收敛的作用。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cai_niaocainiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值