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

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

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

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

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

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

然后写了写…

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
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):
[Easyx\C++]一个简单的QQ聊天机器人的实现_第1张图片
目前缺陷:
1.只能回答单个关键词的单个回答,暂时不能在同一个关键词的情况下,实现回答随机,或根据关键词出现次数出现特定回答的能力
2.在没有找到关键词的情况只会复读。
3.当对方发出的是语音消息是,会无法处理或错误处理。

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

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

你可能感兴趣的:(c++)