[Easyx\C++]一个简单的QQ聊天机器人的实现

最近看到个很智能的聊天机器人,于是我也想着自己是不是也可以做一个

于是经过一番查询,我发现方法有很多(识图,买机器人服务之类的),比较麻烦。

然后这时候我蹦出了一个清奇的想法…

我可不可以直接右键聊天内容,复制到剪贴板,然后再对内容进行操作之后塞入剪贴板,再给贴回去从而达到目的呢?

经过一番操作后,发现可以!(我知道这个方法很取巧,是我太菜了23333)

然后写了写…

代码如下:

#include <Windows.h>
#include <iostream>
#include <thread>
#include <string>
#include <graphics.h>
#include <fstream>
using namespace std;
bool live = true;
bool getn = false;
wifstream fp;//文件引导
void run() {
	GetAsyncKeyState(VK_UP);
	GetAsyncKeyState(VK_DOWN);
	while (live) {
		if (GetAsyncKeyState(VK_UP) & 1) {
			getn = !getn;
			wcout << (getn ?TEXT("开启\n") :TEXT("关闭\n"));
		}
		else if (GetAsyncKeyState(VK_DOWN) & 1)
			live = false;
		Sleep(30);
	}
}
void gress() {
	wstring str;
	TCHAR str_get[600]{ 0 };
	OpenClipboard(NULL);//打开剪贴板,成功了返回true
	if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
		str.insert(0, (TCHAR*)GetClipboardData(CF_UNICODETEXT));
		wcout <<TEXT("发现句子:") << str << endl;
		wcout <<TEXT("正在比对字符串...") << endl;
		fp.seekg(0, ios::beg);//移到开头
		fp.clear();
		while (fp.good()) {
			fp.getline(str_get, 600, TEXT('\n'));
			if ((-1 != str.find(str_get)) && (lstrlen(str_get) > 0)) {//如果有
				wcout <<TEXT("抓取的关键词是:") << str_get << endl;
				fp.getline(str_get, 600, '\n');
				wcout <<TEXT("反馈句子是:") << str_get << endl;
				EmptyClipboard();//清空剪贴板
				HGLOBAL h = GlobalAlloc(GMEM_DDESHARE, (lstrlen(str_get) + 1)*sizeof(TCHAR));//分配内存
				if (!h) {//如果获取内存失败
					CloseClipboard();//关闭剪贴板
					return;
				}
				memcpy(GlobalLock(h), str_get, (lstrlen(str_get) + 1) * sizeof(TCHAR));
				GlobalUnlock(h);
				SetClipboardData(CF_UNICODETEXT, h);
				break;
			}
			else {//如果没有
				fp.getline(str_get, 600, TEXT('\n'));
				fp.getline(str_get, 600, TEXT('\n'));
			}
		}
		wcout <<TEXT("比对完成!") << endl;
	}
	CloseClipboard();//关闭剪贴板,成功了返回非0,否则返回0
}
int main() {
	wcout.imbue(locale("chs"));
	wcin.imbue(locale("chs"));
	fp.imbue(locale("zh_CN.UTF-8"));
	wcout << TEXT("使用提示:启动程序后请不要移动指定的QQ窗口\n方向键up启动/暂停,方向键down关闭程序\n");
	wstring str;
	COLORREF begin[2000], end[2000];
	const int WX = 100;
	const int WY = 100;
	const int line = 543;
	const int we = 74;
	IMAGE img{ 100,20 };
	int i, j;
	HWND hwnd;
	fp.open(TEXT("data.data"), ios::in);
	if (!fp.is_open()) {
		MessageBox(NULL,TEXT("必需文件不存在!"),TEXT("tip"), 0);
		return 0;
	}
	do {
		wcout <<TEXT("请输入已经打开了的QQ窗口的标题名:");
		wcin >> str;
		hwnd = FindWindow(NULL, str.c_str());//warma沃玛粉丝流浪窝
		if (hwnd == NULL)
			wcout <<endl<<TEXT("没找到!") << endl;
	} while (hwnd == NULL);
	wcout << TEXT("准备完毕!\n");
	HDC srcDC = GetDC(NULL);	// 获取桌面 DC
	HDC dstDC = GetImageHDC(&img);	// 获取 IMAGE 对象的 DC
	BitBlt(dstDC, 0, 0, 100, 20, srcDC, WX + we, WY + line, SRCCOPY);
	DWORD *p = GetImageBuffer(&img);
	SetWindowPos(hwnd, NULL, WX, WY, 888, 758, SWP_NOSIZE);
	for (i = 0; i < 20; ++i) {
		for (j = 0; j < 100; ++j)
			begin[i + j * 20] = end[i + j * 20] = p[i + j * 20];
	}
	thread var(run);
	while (live)
	{
		if (getn) {
			BitBlt(dstDC, 0, 0, 100, 20, srcDC, WX + we, WY + line, SRCCOPY);
			for (i = 0; i < 20; ++i) {
				for (j = 0; j < 100; ++j)
					end[i + j * 20] = p[i + j * 20];
			}
			for (i = 0; i < 1000; ++i) {
				if (begin[i] != end[i]) {
					SetCursorPos(WX + we, WY + line); Sleep(2);
					mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0); Sleep(2);
					mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0); Sleep(300);
					keybd_event('C', 0, 0, 0); Sleep(3);
					keybd_event('C', 0, KEYEVENTF_KEYUP, 0); Sleep(300);
					gress();
					SetCursorPos(WX + we, WY + line + 120); Sleep(2);
					mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); Sleep(2);
					mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); Sleep(2);
					PostMessage(hwnd, WM_PASTE, 0, 0); Sleep(200);
					SendMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0); Sleep(300);
					BitBlt(dstDC, 0, 0, 100, 20, srcDC, WX + we, WY + line, SRCCOPY);
					for (i = 0; i < 20; ++i) {
						for (j = 0; j < 100; ++j)
							begin[i + j * 20] = end[i + j * 20] = p[i + j * 20];
					}
					break;
				}
			}
		}
		else {
			BitBlt(dstDC, 0, 0, 100, 20, srcDC, WX + we, WY + line, SRCCOPY);
			for (i = 0; i < 20; ++i) {
				for (j = 0; j < 100; ++j)
					begin[i + j * 20] = p[i + j * 20];
			}
		}
		Sleep(30);
	}
	fp.close();
	var.join();
	return 0;
}

之后只需要在程序旁边建立一个名为data.data的文件,并在里面按照如下格式写预设的对答就好了:

关键词1
关键词1的回复
空行
关键词2
关键词2的回复
空行
关键词3
关键词3的回复
空行
...

以下给出一个文档例子:

唱歌
我会唱好多歌?想听吗?

算了
那该怎么办?

有啊
真的有吗?

什么
不知道

猫
说喵星人干什么?

布吉岛
神马岛?

笨蛋
我是很笨哦,聪明的话就不跟你聊天了.

就是
我也说不清楚啊!

我的
没关系~我有着宽广的胸怀.

方式
什么方式?你喜欢什么方式

实际使用效果图(用的不是上面那个例子的data.data):
在这里插入图片描述
目前缺陷:
1.只能回答单个关键词的单个回答,暂时不能在同一个关键词的情况下,实现回答随机,或根据关键词出现次数出现特定回答的能力
2.在没有找到关键词的情况只会复读。
3.当对方发出的是语音消息是,会无法处理或错误处理。

其中,第一跟第二点都是通过更新代码实现相应逻辑来解决,第三点的话目前我还没想到什么法子解决_(:з」∠)_

注意事项:
只能获取独立出去了的QQ窗口的句柄,当QQ窗口时多窗口合并的时候,会无法获取窗口句柄
最后:
本文就介绍到这里了,原创的想法,原创的代码逻辑,供各位参考,也希望大佬多多包涵。

  • 13
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,下面是一个简单的示例代码,你可以根据自己的需求进行修改和完善: ```cpp #include <graphics.h> #include <conio.h> int main() { initgraph(640, 480); // 初始化图形窗口 // 绘制机器人的身体、头部、手臂和腿 setfillcolor(RGB(255, 255, 255)); // 填充颜色为白色 fillrectangle(200, 200, 400, 400); // 身体 fillellipse(300, 150, 100, 100); // 头部 fillrectangle(150, 220, 200, 280); // 左手臂 fillrectangle(400, 220, 450, 280); // 右手臂 fillrectangle(250, 400, 300, 450); // 左腿 fillrectangle(350, 400, 400, 450); // 右腿 // 绘制机器人的眼睛和嘴巴 setfillcolor(RGB(0, 0, 0)); // 填充颜色为黑色 fillcircle(270, 130, 10); // 左眼 fillcircle(330, 130, 10); // 右眼 setfillcolor(RGB(255, 0, 0)); // 填充颜色为红色 fillpie(270, 160, 60, 120, 30, 150); // 嘴巴 // 循环监听键盘输入,按下相应键时移动机器人的手臂和腿 while (true) { if (_kbhit()) // 判断是否有键盘输入 { int key = _getch(); // 获取键盘输入的字符码 if (key == 'a') // 按下 'a' 键,向左移动左手臂和右腿 { setfillcolor(RGB(255, 255, 255)); // 填充颜色为白色 fillrectangle(150, 220, 200, 280); // 左手臂 fillrectangle(400, 220, 450, 280); // 右手臂 fillrectangle(250, 400, 300, 450); // 左腿 setfillcolor(RGB(0, 0, 0)); // 填充颜色为黑色 fillrectangle(350, 400, 400, 450); // 右腿 } else if (key == 'd') // 按下 'd' 键,向右移动右手臂和左腿 { setfillcolor(RGB(255, 255, 255)); // 填充颜色为白色 fillrectangle(150, 220, 200, 280); // 左手臂 fillrectangle(400, 220, 450, 280); // 右手臂 fillrectangle(350, 400, 400, 450); // 右腿 setfillcolor(RGB(0, 0, 0)); // 填充颜色为黑色 fillrectangle(250, 400, 300, 450); // 左腿 } } } closegraph(); // 关闭图形窗口 return 0; } ``` 这里我们使用了 easyx 图形库来绘制机器人和监听键盘输入,通过判断键盘输入的字符码来移动机器人的手臂和腿。你可以根据自己的需求来修改和完善代码。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值