飞道的博客

精心为学弟学妹整理了60个适合练手的C语言/C++项目,值得收藏!

324人阅读  评论(0)

前几天写这篇文章《精心为学弟学妹准备的C语言与C++学习路线、书籍、视频推荐和资料,值得收藏!》,阅读和收藏都挺多,也让我一周涨了3000多粉丝,在这里感谢大家关注支持我。

最近很多粉丝朋友私信问一些学习路线的问题以及一些学习资源,一个一个回复有点累,前几天我分享了这篇《精心为学弟学妹准备的刷题笔记与代码规范,看完距大厂又近了一步!值得收藏!》关于算法和代码规范的文章。也有不少小伙伴问看完书和视频后,可以做点啥,今天给大家分享60个c语言/c++的小项目源码(这里面一部分是c++的c),学习过程中,可以调试下。对编程能力提升很有帮助。

说明:虽然截图标题都是c语言,但是一部分是c++

私聊回复不过来,我把源码放到这里,大家需要的话自行下载60个项目源码大全,点击获取

例如:c语言做的播放器源码

代码:


  
  1. #include "stdafx.h"
  2. #include <windows.h>
  3. #include <windowsx.h>
  4. #include <stdlib.h>
  5. #include <time.h> //用到了time函数,所以要有这个头文件
  6. #include <commdlg.h>
  7. #include <mmsystem.h> // mciSengString函数调用需要先调用#include <mmsystem.h>
  8. #include <commctrl.h> // TBM_SETPOS头文件
  9. #include "resource.h"
  10. #include "MainDlg.h"
  11. #include <shellapi.h>//有关系统托盘的头文件
  12. #define WM_HIDE WM_USER+100
  13. //定制自己的消息ID。
  14. //为了防止用户定义的消息ID与系统的消息ID冲突
  15. //MS(Microsoft)定义了一个宏WM_USER,小于WM_USER的ID被系统使用,大于WM_USER的ID被用户使用。
  16. /* 欢迎关注公众号“c语言与cpp编程”,关注后回复“加群”进学习交流群,关注送海量资料 */
  17. #define ORDER 0 //顺序播放
  18. #define SINGLELOOP 1 //单曲循环
  19. #define LISTLOOP 2 //列表循环
  20. #define RANDOM 3 //随机播放
  21. void Main_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos); //声明滑块函数
  22. // 全局变量定义
  23. TCHAR szFileNamePath[ 256][MAX_PATH]; //歌曲的完全路径,二维数组 Path(路径)
  24. TCHAR szFileName[ 256][MAX_PATH]; // 歌曲名
  25. TCHAR shortName[ 256]; //歌曲的短路径名
  26. int num; //正在播放歌曲的序号
  27. int offset = 0; //打开歌曲时记录歌曲的编号,为了多次打开时编号能连续,所以设为全局变量
  28. int count = 0; //为列表中的歌曲添加序号
  29. int playStatus = 1; // 当前歌曲播放状态,1 表示正在播放状态,0 表示暂停状态
  30. int minite; // 曲目播放时间,分
  31. int second; // 曲目播放时间,秒
  32. long allLength; //这是什么?
  33. long curLength; // curLength = atoi(curTime); //这是但前时间的字符串转化为INT型
  34. TCHAR strTime[ 256] = ""; // 曲目播放当前时间
  35. TCHAR strTimeAll[ 256] = ""; // 曲目总时间
  36. TCHAR curTime[ 256] = ""; // 这是什么?
  37. int mode = ORDER; // 这是什么?
  38. int n; // 这是什么?
  39. // 函数原型
  40. void addFiles(HWND hwnd); // 添加歌曲
  41. void playMusic(HWND hwnd); // 播放歌曲
  42. void pauseMusic(HWND hwnd); // 暂停播放
  43. void stopPlay(HWND hwnd); // 停止播放当前正在播放的歌曲
  44. void playLast(HWND hwnd); // 播放上一曲
  45. void playNext(HWND hwnd); // 播放下一曲
  46. void autoNext(HWND hwnd); //自动播放下一曲
  47. void silence(HWND hwnd); // 静音
  48. void getAllTime(HWND hwnd); // 得到歌曲总时间
  49. void deleteAll(HWND hwnd); // 移除所有曲目
  50. void deleteSel(HWND hwnd); // 移除选中曲目
  51. void getSongMessage(HWND hwnd); // 获取曲目详细信息??
  52. ******* 此函数需要现在初始化对话框中定义TimerProc!!!如:SetTimer(hwnd, 1, 1000,TimerProc); ************* //
  53. VOID CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime) //IDC_EDITSYST编辑框中在显示系统时间
  54. {
  55. SYSTEMTIME stLocal; //系统当前时间
  56. TCHAR time[ 256]; //定义time数组来保存需要在IDC_EDITSYST编辑框中显示的内容
  57. GetLocalTime(&stLocal); //得到系统当前时间的指针
  58. wsprintf(time, "%d年%d月%d日 %d:%d:%d",stLocal.wYear,stLocal.wMonth,stLocal.wDay
  59. ,stLocal.wHour,stLocal.wMinute,stLocal.wSecond); //将“”中内容拷贝到time数组中
  60. SetDlgItemText(hwnd,IDC_EDITSYST,time); //将time数组内容打印到IDC_EDITSYST编辑框中
  61. }
  62. / 此函数需要现在初始化对话框中定义curTimePro!!!如:SetTimer(hwnd, 0, 1000, curTimePro); ///
  63. void CALLBACK curTimePro(HWND hwnd, UINT message, UINT iTemerID, DWORD dwTime)// 回调函数,读取当前播放时间,设置滑动条的当前值
  64. {
  65. TCHAR str[ 256];
  66. wsprintf(str, "status %s position", shortName);
  67. //int wsprintf(   LPTSTR lpOut, 输出缓冲区,最大为1024字节   LPCTSTR lpFmt, 格式字符串   ... 需输出的参数;)
  68. mciSendString(str, curTime, sizeof(curTime)/ sizeof(TCHAR), NULL); //mciSendString(“play ***”,"",0,NULL);
  69. curLength = atoi(curTime);
  70. minite = curLength / 60000; //定义时间中 “分”的由来
  71. second = (curLength / 1000) % 60; //定义时间中 “秒”的由来
  72. wsprintf(strTime, "%.2d:%.2d", minite, second); // 曲目播放当前时间 的确定
  73. SetDlgItemText(hwnd, IDC_EDITTIME, strTime); //将当前播放时间打印到IDC_EDITTIME中
  74. // 设置滑块的最大值,最小值以及当时位置
  75. HWND hwSlider = GetDlgItem(hwnd, IDC_SLIDER); //IDC_SLIDER的句柄定义为hwSlider
  76. SendMessage(hwSlider, TBM_SETRANGEMAX, (WPARAM)TRUE, allLength); //TBM_SETRANGEMAX:设置滑块逻辑位置的最大值,及是否重画
  77. SendMessage(hwSlider, TBM_SETRANGEMIN, (WPARAM)TRUE, 0); //TBM_SETRANGEMIN:设置滑块逻辑位置的最小值,及是否重画
  78. SendMessage(hwSlider, TBM_SETPOS, (WPARAM)TRUE, curLength); //TBM_SETPOS:设置滑块的逻辑位置,及是否重画
  79. TCHAR szCommand[MAX_PATH+ 10];
  80. TCHAR szReturn[MAX_PATH];
  81. ZeroMemory(szCommand, sizeof(szCommand)/ sizeof(TCHAR));
  82. //C语言中声明一个结构体变量之后,在使用这个变量之前要首先用memset来把各个位清零。使用C语言内置的函数memset来完成:
  83. //memset(&s1,sizeof(s1),0);
  84. //在这里我们使用ZeroMemory“函数”,ZeroMemory其实并不是函数,其实是memset的宏定义
  85. //ZeroMemory其实就是memset,纸老虎而已,不是一个全新的函数。
  86. wsprintf(szCommand, TEXT( "status %s mode"), shortName);
  87. mciSendString(szCommand, szReturn, sizeof(szReturn)/ sizeof(TCHAR), NULL);
  88. //***********************************下面的函数功能会和IDC_STOP点击函数冲突!!!***************************************//
  89. //strcmp速度快但是代码多;lstrcmp速度慢但精简,其实也就慢那么一丁丁丁丁点啦 推荐使用lstrcmp
  90. //lstrcmp字符串对比,本语句含义是:当szReturn==stopped时自动播放下一曲
  91. if ( 0 == lstrcmp(szReturn, TEXT( "stopped")))
  92. {
  93. autoNext(hwnd);
  94. }
  95. }
  96. / 此函数需要现在初始化对话框中定义TimerProc1!!!如:SetTimer(hwnd, 2, 1000,TimerProc1); ///
  97. VOID CALLBACK TimerProc1(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime) //IDC_EDITSYST编辑框中在显示系统时间
  98. {
  99. SYSTEMTIME stLocal; //系统当前时间
  100. GetLocalTime(&stLocal); //得到系统当前时间的指针
  101. TCHAR STR1[ 256],STR2[ 256];
  102. int hour,minute;
  103. GetDlgItemText(hwnd,IDC_EDIT1,STR1, sizeof(STR1));
  104. GetDlgItemText(hwnd,IDC_EDIT2,STR2, sizeof(STR2));
  105. hour = atoi(STR1);
  106. minute = atoi(STR2);
  107. if(hour == stLocal.wHour&&minute == stLocal.wMinute)
  108. {
  109. HWND hwList = GetDlgItem(hwnd,IDC_LIST1);
  110. TCHAR str1[ 256],str2[ 256];
  111. ListBox_GetText(hwList, 0,str1);
  112. wsprintf(str2, "play %s",str1);
  113. mciSendString(str2, "", 0, NULL);
  114. }
  115. }
  116. //*****************************************最下化到系统托盘问题*************************************************
  117. /* ypedef struct _NOTIFYICONDATAA {
  118. DWORD cbSize; //结构体的大小,以字节为单位。
  119. HWND hWnd; //窗口的句柄。标示的窗口用来接收与托盘图标相关的消息。
  120. UINT uID; //应用程序定义的任务栏图标的标识符。
  121. UINT uFlags; //此成员表明具体哪些其他成员为合法数据(即哪些成员起作用)。
  122. //此成员可以为以下值的组合:
  123. // NIF_ICON   hIcon成员起作用。  
  124. // NIF_MESSAGE  uCallbackMessage成员起作用。  
  125. // NIF_TIP    szTip成员起作用。  
  126. // NIF_STATE   dwState和dwStateMask成员起作用。
  127. // NIF_INFO    使用气球提示代替普通的工具提示框。szInfo, uTimeout, szInfoTitle和dwInfoFlags成员起作用。  
  128. // NIF_GUID    保留。
  129. UINT uCallbackMessage; //应用程序定义的消息标示。当托盘图标区域发生鼠标事件或者使用键盘选择或激活图标时,
  130. //系统将使用此标示向由hWnd成员标示的窗口发送消息。
  131. //消息响应函数的wParam参数标示了消息事件发生的任务栏图标,lParam参数根据事件的不同,
  132. //包含了鼠标或键盘的具体消息,例如当鼠标指针移过托盘图标时,lParam将为WM_MOUSEMOVE。
  133. HICON hIcon; //增加、修改或删除的图标的句柄。
  134. CHAR szTip[64]; //指向一个以\0结束的字符串的指针。字符串的内容为标准工具提示的信息。
  135. //包含最后的\0字符,szTip最多含有64个字符。
  136. } NOTIFYICONDATAA */
  137. //*****************首先了解上面的NOTIFYICONDATA结构体的成员*****************//
  138. void Minimized(HWND hwnd,int flag)
  139. {
  140. NOTIFYICONDATA nid;
  141. nid.cbSize = (DWORD) sizeof(NOTIFYICONDATA);
  142. nid.hWnd = hwnd;
  143. nid.uID = 1;
  144. nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
  145. nid.uCallbackMessage = WM_HIDE; //自定义消息
  146. HINSTANCE hin = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE); //获得程序句柄!!!
  147. nid.hIcon = LoadIcon(hin,MAKEINTRESOURCE( 1)); //增加一个MAKEINTRESOURCE(1)的图标句柄,MAKEINTRESOURCE(1)即:应用程序图标
  148. lstrcpy(nid.szTip,TEXT( "双击恢复窗口")); //最小化到托盘,鼠标移到托盘上面显示的信息提示条。
  149. switch(flag)
  150. {
  151. case 0:
  152. { //添加托盘图标,隐藏窗口
  153. Shell_NotifyIcon(NIM_ADD,&nid);
  154. //BOOL Shell_NotifyIcon( DWORD dwMessage,PNOTIFYICONDATA lpdata);
  155. //dwMessage为输入参数,传递发送的消息,表明要执行的操作。可选的值如下:
  156. //NIM_ADD 向托盘区域添加一个图标。
  157. //NIM_DELETE 删除托盘区域的一个图标。
  158. //NIM_MODIFY 修改托盘区域的一个图标。
  159. //NIM_SETFOCUS 设置焦点。比如当用户操作托盘图标弹出菜单,而有按下ESC键将菜单消除后,程序应该使用此消息来将焦点设置到托盘图标上。
  160. //lpdata 为输入参数,是指向NOTIFYICONDATA结构体的指针,结构体内容用来配合第一个参数wMessage进行图标操作。
  161. ShowWindow(hwnd,SW_HIDE); //隐藏窗口
  162. }
  163. break;
  164. case 1:
  165. { //删除托盘图标
  166. ShowWindow(hwnd,SW_SHOWNORMAL);
  167. Shell_NotifyIcon(NIM_DELETE,&nid);
  168. SetForegroundWindow(hwnd); //Foreground 前台
  169. //函数原型:BOOL SetForegroundWindow(HWND hWnd)
  170. //该函数将创建指定窗口的线程设置到前台,并且激活该窗口。
  171. //键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。
  172. }
  173. break;
  174. default:
  175. break;
  176. }
  177. }
  178. //***************************Main_Proc 对话框的消息处理函数****************************************************
  179. BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  180. {
  181. switch(uMsg)
  182. {
  183. //BEGIN MESSAGE CRACK
  184. HANDLE_MSG(hWnd,WM_HSCROLL, Main_OnHScroll); // Slider滑块消息
  185. HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); //初始化的消息
  186. HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); //发给控件们的消息
  187. HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose); //关闭对话框的消息
  188. //END MESSAGE CRACK
  189. case WM_HIDE: //#define WM_HIDE WM_USER+100
  190. {
  191. if(lParam==WM_LBUTTONDBLCLK) //表示左键双击事件
  192. {
  193. Minimized(hWnd, 1); //Minimized函数就需要这Main_Proc函数之前定义
  194. }
  195. else if(lParam==WM_RBUTTONDOWN) //表示右键单击事件
  196. {
  197. Minimized(hWnd, 1);
  198. }
  199. }
  200. break;
  201. case WM_SIZE:
  202. {
  203. if(SIZE_MINIMIZED==wParam) //点击最小化 到托盘
  204. {
  205. Minimized(hWnd, 0);
  206. }
  207. }
  208. }
  209. return FALSE;
  210. }
  211. //**********************************************************************************************************
  212. 对话框的初始化!!!! ///
  213. BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  214. {
  215. SetTimer(hwnd, 1, 1000,TimerProc); //SetTimer(HWND hWnd ,UINT nIDEvent,UINT uElapse,TIMERPROC lpTimerFunc)函数
  216. //HWND hWnd窗口句柄 ;
  217. //UINT nIDEvent 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
  218. //UINT uElapse时间间隔,单位为毫秒 ;
  219. //TIMERPROC lpTimerFunc 回调函数 。
  220. SetTimer(hwnd, 0, 1000, curTimePro);
  221. SetTimer(hwnd, 2, 1000,TimerProc1); //闹钟
  222. // 在SetTimer定义的回调函数定义必须在Main_OnInitDialog之前!!!!!!
  223. // 初始化时间,播放时间和曲目总时间都为零
  224. strcpy(strTime, "00:00");
  225. strcpy(strTimeAll, "00:00");
  226. SetDlgItemText(hwnd, IDC_EDITTIME, strTime);
  227. SetDlgItemText(hwnd, IDC_EDITTIMEALL, strTimeAll);
  228. // 初始化音量
  229. HWND hwSliderVolume = GetDlgItem(hwnd, IDC_SLIDERVOLUME);
  230. SendMessage(hwSliderVolume, TBM_SETRANGEMAX, (WPARAM)TRUE, 1000); // 音量最大为100
  231. SendMessage(hwSliderVolume, TBM_SETRANGEMIN, (WPARAM)TRUE, 0); // 最小值为0
  232. SendMessage(hwSliderVolume, TBM_SETPOS, (WPARAM)TRUE, 500); // 初始化为音量50
  233. //循环模式
  234. HWND hwCombo1 = GetDlgItem(hwnd, IDC_COMBO1);
  235. ComboBox_InsertString(hwCombo1, -1, TEXT( "顺序播放")); //index为-1时指:将顺序播放插入到列表末尾
  236. ComboBox_InsertString(hwCombo1, -1, TEXT( "单曲循环")); //index为-1时指:将单曲循环插入到列表末尾
  237. ComboBox_InsertString(hwCombo1, -1, TEXT( "列表循环")); //index为-1时指:将列表循环插入到列表末尾
  238. ComboBox_InsertString(hwCombo1, -1, TEXT( "随机播放")); //index为-1时指:将随机播放插入到列表末尾
  239. ComboBox_SetCurSel(hwCombo1, 0); //默认选择顺序播放模式
  240. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "Ready!......")); //初始化播放状态为READY
  241. return TRUE;
  242. }
  243. //******************************* Main_OnCommand 处理对话框控件消息的函数********************************//
  244. void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  245. {
  246. switch(id)
  247. {
  248. // 添加文件到列表
  249. case ID_MENUITEMADD:
  250. case IDC_ADD:
  251. {
  252. addFiles(hwnd);
  253. HWND hwList = GetDlgItem(hwnd, IDC_LIST);
  254. ListBox_SetCurSel(hwList, 0);
  255. }
  256. break;
  257. // 播放选中的歌曲
  258. case ID_MENUITEMPLAY:
  259. case IDC_PLAY:
  260. {
  261. playMusic(hwnd);
  262. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "playing!......."));
  263. }
  264. break;
  265. // 暂停选中的歌曲
  266. case ID_MENUITEMPAUSE:
  267. case IDC_PAUSE:
  268. {
  269. pauseMusic(hwnd);
  270. }
  271. break;
  272. // 停止正在播放的音乐
  273. case ID_MENUITEMSTOP:
  274. case IDC_STOP:
  275. {
  276. stopPlay(hwnd);
  277. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "stopping!........"));
  278. }
  279. break;
  280. //列表框IDC_LIST的信息处理
  281. case IDC_LIST:
  282. {
  283. switch(codeNotify)
  284. {
  285. // 播放双击选中的歌曲
  286. case LBN_DBLCLK: //双击选中项
  287. {
  288. playMusic(hwnd);
  289. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "playing!......."));
  290. }
  291. break;
  292. }
  293. }
  294. break;
  295. // 播放上一曲
  296. case ID_MENUITEMLAST:
  297. case IDC_LAST:
  298. {
  299. playLast(hwnd);
  300. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "playing!......."));
  301. }
  302. break;
  303. // 播放下一曲
  304. case ID_MENUITEMNEXT:
  305. case IDC_NEXT:
  306. {
  307. playNext(hwnd);
  308. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "playing!......."));
  309. }
  310. break;
  311. // 静音与恢复
  312. case IDC_CHECK:
  313. {
  314. silence(hwnd);
  315. }
  316. break;
  317. // 删除列表中所有曲目
  318. case ID_MENUITEMCLEAN:
  319. case IDC_DELETEALL:
  320. {
  321. deleteAll(hwnd);
  322. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "Ready!......"));
  323. }
  324. break;
  325. //删除列表中的单个曲目
  326. case ID_MENUITEMDEL:
  327. case IDC_DELETESEL:
  328. {
  329. deleteSel(hwnd);
  330. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "Ready!......"));
  331. }
  332. break;
  333. //显示器休眠
  334. case ID_MENUITEMSLEEP:
  335. case IDC_SLEEP:
  336. {
  337. SendMessage(hwnd,WM_SYSCOMMAND,SC_MONITORPOWER, 2);
  338. }
  339. break;
  340. //关于
  341. case ID_MENUITEMABOUT:
  342. {
  343. MessageBox(hwnd,TEXT( "大家一起学习探讨!QQ:983572133,加我时说明来自如鹏网!"),TEXT( "关于"),MB_OK);
  344. }
  345. break;
  346. //退出
  347. case ID_MENUITEMEXIT:
  348. {
  349. int i=MessageBox(hwnd,TEXT( "确认退出吗?"),TEXT( "询问"),MB_YESNO|MB_ICONQUESTION);
  350. if(i== 6)
  351. {
  352. Main_OnClose(hwnd);
  353. }
  354. }
  355. //添加闹钟
  356. case IDC_BUTTON1:
  357. {
  358. HWND hwList = GetDlgItem(hwnd, IDC_LIST1);
  359. TCHAR szFile[ 256*MAX_PATH] = "";
  360. TCHAR szPath[ 256] = "";
  361. OPENFILENAME ofn;
  362. ZeroMemory(&ofn, sizeof(ofn));
  363. ofn.lStructSize = sizeof(ofn);
  364. ofn.hwndOwner = hwnd;
  365. ofn.lpstrFilter = "音乐文件(mp3、wma、wav)\0*.wma;*.mp3;*.wav\0所有文件(*.*)\0*.*\0";
  366. ofn.lpstrCustomFilter = NULL;
  367. ofn.nFilterIndex = 1;
  368. ofn.lpstrFile = szFile;
  369. ofn.nMaxFile = sizeof(szFile) / sizeof(TCHAR);
  370. ofn.lpstrFile[ 0] = TEXT( '\0');
  371. ofn.lpstrTitle = TEXT( "添加闹铃");
  372. ofn.nMaxFileTitle = NULL;
  373. ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER ;
  374. ofn.lpstrDefExt = "*.mp3";
  375. if (GetOpenFileName(&ofn))
  376. {
  377. TCHAR getShort[MAX_PATH];
  378. GetShortPathName(szFile, getShort, sizeof(getShort));
  379. HWND hwList = GetDlgItem(hwnd, IDC_LIST1);
  380. ListBox_InsertString(hwList, 0 ,getShort);
  381. }
  382. }
  383. break;
  384. //关机
  385. case ID_MENUITEMOFF:
  386. case IDC_BUTTONOFF:
  387. {
  388. system( "shutdown -s -t 0");
  389. }
  390. break;
  391. //闹钟说明
  392. case ID_MENUITEMCLOCK:
  393. {
  394. MessageBox(hwnd,TEXT( "闹钟时间格式为 小时:分钟 "),TEXT( "闹钟说明"),MB_OK);
  395. }
  396. default:
  397. break;
  398. }
  399. }
  400. //******************************************各个函数的定义************************************************************//
  401. ************************************************************************************************************** //
  402. //******************************************* 添加歌曲 ************************************************//
  403. void addFiles(HWND hwnd)
  404. {
  405. HWND hwList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox句柄
  406. TCHAR szFile[ 256*MAX_PATH] = ""; // 文件的名字,*MaxPath能解决添加多文件时出现的问题
  407. TCHAR szPath[ 256] = ""; // 歌曲的路径
  408. TCHAR *p; // 指向歌曲的名字
  409. // int i; // 用于计数
  410. OPENFILENAME ofn;
  411. ZeroMemory(&ofn, sizeof(ofn)); // 清零(memset函数的宏定义)
  412. ofn.lStructSize = sizeof(ofn); // lStructSize指定这个结构的大小,以字节为单位。
  413. ofn.hwndOwner = hwnd; // 指向所有者对话框窗口的句柄。这个成员可以是任意有效窗口句柄,或如果对话框没有所有者它可以为NULL。
  414. ofn.lpstrFilter = "音乐文件(mp3、wma、wav)\0*.wma;*.mp3;*.wav\0所有文件(*.*)\0*.*\0";
  415. ofn.lpstrCustomFilter = NULL; //指向一个静态缓冲,它包含了一对以空字符结束的过滤器字符串,这个字符串是为了保留用户选择的过滤样式。
  416. //如果这个成员是NULL,对话框不能保留用户自定义过滤器样式。
  417. //如果这个成员不是NULL,nMaxCustFilter成员的值必须指定以TCHARs为单位的lpstrCustomFilter缓冲的大小。
  418. ofn.nFilterIndex = 1; // 指定在文件类型控件中当前选择的过滤器的索引。音乐文件(mp3、wma、wav) 从1开始!!
  419. ofn.lpstrFile = szFile; // lpstrFile指向包含初始化文件名编辑控件使用的文件名的缓冲。
  420. ofn.nMaxFile = sizeof(szFile) / sizeof(TCHAR); // 指定lpstrFile缓冲的大小,以TCHARs为单位。
  421. ofn.lpstrFile[ 0] = TEXT( '\0'); //不知道是什么?
  422. ofn.lpstrTitle = TEXT( "添加音乐"); // 指向接收选择的文件的文件名和扩展名的缓冲(不带路径信息)。这个成员可以是NULL。
  423. ofn.nMaxFileTitle = NULL; // 指定lpstrFileTitle缓冲的大小,以TCHARs为单位。
  424. ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_ALLOWMULTISELECT;
  425. //OFN_ALLOWMULTISELECT 指定文件名列表框允许多选
  426. //OFN_EXPLORER 指出任何打开或另存为对话框使用新的Explorer风格的用户化模块。
  427. //OFN_HIDEREADONLY 隐藏只读复选框。
  428. //OFN_FILEMUSTEXIST 指定用户仅可以在文件名登录字段中输入已存在的文件的名字。
  429. //OFN_PATHMUSTEXIST 指定用户仅能输入的路径和文件名。
  430. ofn.lpstrDefExt = "*.mp3";
  431. //指向包含默认扩展名的缓冲。如果用户忘记输入扩展名,GetOpenFileName和GetSaveFileName附加这个扩展名到文件名中。
  432. //这个字符串可以是任一长度,但但只有头三个字符被附加。字符串不应该包含一个句点(.)。
  433. //如果这个成员是NULL并且用户忘记了输入一个扩展名,那么将没有扩展名被附加。
  434. if (GetOpenFileName(&ofn)) //如果打开的文件是TRUE则有.....
  435. {
  436. int nLength = 0; // 文件路径的字符长度
  437. lstrcpyn(szPath, szFile, ofn.nFileOffset); // 把第一个文件名前的路径复制到szPath
  438. //lstrcpyn - 复制字符串, 同时指定要复制的长度
  439. //nFileOffset指第一个文件名前的路径
  440. //nFileOffset:
  441. //指定从路径开始到通过lpstrFile指定的文件名字符串基于0的偏移,以TCHARs为单位。
  442. //对于ANSI版本,是字节的个数;对于Unicode版本,是字符的个数。
  443. //例如,如果lpstrFile指向下列的字符串,“c:\dir1\dir2\file.ext”,这个成员包含指出“file.ext”字符串偏移的位置值13。
  444. szPath[ofn.nFileOffset] = '\0'; //(加上结束标记)取得文件路径
  445. nLength = lstrlen(szPath);
  446. //???????????????????????????????????????????不理解?????????????????????????????????????????????????????????//
  447. if (szPath[nLength -1] != '\\') // 如果选择了多个文件,必须加上'\\' //
  448. { //
  449. lstrcat(szPath, TEXT( "\\")); //
  450. } //
  451. //??????????????????????????????????????????????????????????????????????????????????????????????????????????//
  452. p = szFile + ofn.nFileOffset; //把指针移到第一个文件的文件名
  453. while (*p)
  454. {
  455. lstrcpy(szFileNamePath[offset], szPath); // 将路径复制给szFileNamePath[offset]
  456. lstrcat(szFileNamePath[offset], p); // 加上文件名
  457. SendMessage(hwList, LB_ADDSTRING, 0, (LPARAM)p); //向列表框添加文件名,(LPARAM)p即文件名指针
  458. lstrcat(szFileName[offset], p); //文件名复制给szfilename,用于显示显示正在播放的文件名
  459. //??????????????????????????????????????不理解??????????????????????????????????//
  460. p += lstrlen(p) + 1; //移至下一个文件 //
  461. //??????????????????????????????????????????????????????????????????????????????//
  462. offset++;
  463. }
  464. }
  465. }
  466. //******************************************* 播放歌曲 *******************************************//
  467. void playMusic(HWND hwnd)
  468. {
  469. stopPlay(hwnd); // 停止正在播放的歌曲
  470. TCHAR str1[ 256] = "";
  471. TCHAR str2[ 256] = "";
  472. HWND hwList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox句柄
  473. int index = ListBox_GetCurSel(hwList);
  474. ListBox_GetText(hwList, index, str1); // 得到歌曲名
  475. int count;
  476. for (count = 0; count < offset; count++)
  477. {
  478. if ( 0 == strcmp(str1, szFileName[count]))
  479. {
  480. GetShortPathName(szFileNamePath[count], shortName, sizeof(shortName)); // 获得短路径
  481. if ( 2 == mode)
  482. {
  483. wsprintf(str2, "play %s repeat", shortName);
  484. }
  485. else
  486. {
  487. wsprintf(str2, "play %s", shortName);
  488. }
  489. break;
  490. }
  491. }
  492. num = count;
  493. SetDlgItemText(hwnd, IDC_EDITMUSIC, szFileName[num]);
  494. mciSendString(str2, "", 0, NULL); // 播放选中歌曲
  495. getAllTime(hwnd);
  496. }
  497. //******************************************* 删除列表中全部项 *******************************************//
  498. void deleteAll(HWND hwnd)
  499. {
  500. stopPlay(hwnd);
  501. int i;
  502. HWND hwList = GetDlgItem(hwnd, IDC_LIST);
  503. int icount = ListBox_GetCount(hwList);
  504. for (i = icount - 1; i >= 0; i--)
  505. {
  506. ListBox_DeleteString(hwList, i);
  507. strcpy(szFileName[i], ""); //szFileName全局变量
  508. strcpy(szFileNamePath[i], ""); //szFileNamePath全局变量
  509. }
  510. offset = 0; //打开歌曲时记录歌曲的编号,为了多次打开时编号能连续,所以设为全局变量
  511. num = 0; //正在播放歌曲的序号
  512. }
  513. //******************************************* 移除选中的曲目 *******************************************//
  514. void deleteSel(HWND hwnd)
  515. {
  516. HWND hwList = GetDlgItem(hwnd, IDC_LIST);
  517. int selCount = ListBox_GetCurSel(hwList);
  518. if (selCount == num) // 如果删除的是当前正在播放的,停止播放音乐,选中下一首
  519. {
  520. stopPlay(hwnd);
  521. }
  522. int i;
  523. for (i = selCount; i < ListBox_GetCount(hwList) - 1; i++) // 将存放的路径信息依次前移
  524. {
  525. strcpy(szFileNamePath[i], szFileNamePath[i+ 1]);
  526. strcpy(szFileName[i], szFileName[i+ 1]);
  527. }
  528. strcpy(szFileName[i], ""); // 将原来最后的设为空
  529. strcpy(szFileNamePath[i], ""); // 将原来最后的设为空
  530. ListBox_DeleteString(hwList, selCount); // 从列表中删除选中项
  531. if(num == selCount) //正在播放的歌曲序号等于要删除的歌曲序号,选中列表中第一个歌曲
  532. {
  533. num= 0;
  534. }
  535. if (num > selCount) //正在播放的歌曲序号大于要删除的歌曲序号,依然选中列表中正在播放的歌曲
  536. {
  537. num--;
  538. }
  539. ListBox_SetCurSel(hwList, num); // 选中列表中正在播放的歌曲
  540. offset--;
  541. }
  542. //******************************************* 暂停播放 *******************************************//
  543. void pauseMusic(HWND hwnd)
  544. {
  545. TCHAR str1[ 256] = "";
  546. TCHAR str2[ 256] = "";
  547. HWND hwList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox句柄
  548. int index = ListBox_GetCurSel(hwList);
  549. ListBox_GetText(hwList, index, str1); // 得到歌曲名
  550. HWND hwButtonPause = GetDlgItem(hwnd, IDC_PAUSE); // 得到IDC_PAUSE按钮的句柄
  551. if( strcmp(str1, szFileName[num]) != 0) //选中的歌曲不是正在播放的歌曲就无法暂停
  552. {
  553. MessageBox(hwnd,TEXT( "无法暂停未播放的歌曲!"),TEXT( "错误"),MB_OK|MB_ICONERROR);
  554. }
  555. else
  556. {
  557. int count;
  558. for (count = 0; count < offset; count++)
  559. {
  560. if ( 0 == strcmp(str1, szFileName[count]))
  561. {
  562. GetShortPathName(szFileNamePath[count], shortName, sizeof(shortName)); // 获得短路径
  563. if ( 1 == playStatus) // 播放状态
  564. {
  565. SetWindowText(hwButtonPause, TEXT( "继续")); // 将按钮上的文字改为“继续”
  566. wsprintf(str2, "pause %s", shortName); // pause命令
  567. playStatus--;
  568. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "pausing!......."));
  569. }
  570. else
  571. {
  572. SetWindowText(hwButtonPause, TEXT( "暂停")); // 将按钮上的文字改为“暂停”
  573. wsprintf(str2, "resume %s", shortName); // resume命令
  574. playStatus++;
  575. SetDlgItemText(hwnd,IDC_STATUS,TEXT( "playing!......."));
  576. }
  577. }
  578. }
  579. }
  580. mciSendString(str2, "", 0, NULL); // 继续或是暂停播放歌曲
  581. }
  582. //******************************************* 自动转为下一曲 *******************************************//
  583. void autoNext(HWND hwnd)
  584. {
  585. srand(time( 0));
  586. mode = ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_COMBO1)); // 获取当前的播放模式
  587. stopPlay(hwnd);
  588. TCHAR str1[ 256] = "";
  589. TCHAR str2[ 256] = "";
  590. HWND hwList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox句柄
  591. int index = ListBox_GetCurSel(hwList); //得到现在正在播放的歌曲
  592. int all = ListBox_GetCount(hwList); // 列表中总项
  593. if ( 1 == mode)
  594. {
  595. ListBox_SetCurSel(hwList, index);
  596. }
  597. if ( 0 == mode || 2 == mode)
  598. {
  599. ListBox_GetText(hwList, (index+ 1)%all, str1); // 得到歌曲名
  600. ListBox_SetCurSel(hwList, (index+ 1)%all); //选中下一首歌曲
  601. if ( 0 == mode && all == index+ 1)
  602. {
  603. stopPlay(hwnd);
  604. }
  605. }
  606. if ( 3 == mode)
  607. {
  608. int iRand = rand()%all;
  609. ListBox_GetText(hwList, iRand, str1);
  610. ListBox_SetCurSel(hwList, iRand);
  611. }
  612. int count;
  613. for (count = 0; count < offset; count++)
  614. {
  615. if ( 0 == strcmp(str1, szFileName[count]))
  616. {
  617. GetShortPathName(szFileNamePath[count], shortName, sizeof(shortName)); // 获得短路径
  618. wsprintf(str2, "play %s", shortName);
  619. break;
  620. }
  621. }
  622. num = count;
  623. SetDlgItemText(hwnd, IDC_EDITMUSIC, szFileName[num]); // 如果在此处的话,什么都不显
  624. mciSendString(str2, "", 0, NULL); // 播放选中歌曲
  625. getAllTime(hwnd);
  626. }
  627. //******************************************* 播放上一曲 *******************************************//
  628. void playLast(HWND hwnd)
  629. {
  630. stopPlay(hwnd);
  631. TCHAR str1[ 256] = "";
  632. TCHAR str2[ 256] = "";
  633. HWND hwList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox句柄
  634. int index = ListBox_GetCurSel(hwList);
  635. int all = ListBox_GetCount(hwList); // 列表中总项
  636. if (index > 0)
  637. {
  638. ListBox_GetText(hwList, index -1, str1); // 得到歌曲名
  639. ListBox_SetCurSel(hwList, index -1);
  640. }
  641. else //当为第一首歌,即index==0时,跳到最后一首
  642. {
  643. ListBox_GetText(hwList, all -1, str1); // 得到歌曲名
  644. ListBox_SetCurSel(hwList, all -1);
  645. }
  646. int count;
  647. for (count = 0; count < offset; count++)
  648. {
  649. if ( 0 == strcmp(str1, szFileName[count]))
  650. {
  651. GetShortPathName(szFileNamePath[count], shortName, sizeof(shortName)); // 获得短路径
  652. wsprintf(str2, "play %s", shortName);
  653. break;
  654. }
  655. }
  656. num = count;
  657. SetDlgItemText(hwnd, IDC_EDITMUSIC, szFileName[num]); //在IDC_EDITMUSIC编辑框显示将要播放的歌曲文件名
  658. mciSendString(str2, "", 0, NULL); // 播放选中歌曲
  659. getAllTime(hwnd);
  660. }
  661. //******************************************* 播放下一曲 *******************************************//
  662. void playNext(HWND hwnd)
  663. {
  664. stopPlay(hwnd);
  665. TCHAR str1[ 256] = "";
  666. TCHAR str2[ 256] = "";
  667. HWND hwList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox句柄
  668. int index = ListBox_GetCurSel(hwList);
  669. int all = ListBox_GetCount(hwList); // 列表中总项
  670. ListBox_GetText(hwList, (index+ 1)%all, str1); // 得到歌曲名
  671. ListBox_SetCurSel(hwList, (index+ 1)%all);
  672. int count;
  673. for (count = 0; count < offset; count++)
  674. {
  675. if ( 0 == strcmp(str1, szFileName[count]))
  676. {
  677. GetShortPathName(szFileNamePath[count], shortName, sizeof(shortName)); // 获得短路径
  678. wsprintf(str2, "play %s", shortName);
  679. break;
  680. }
  681. }
  682. num = count;
  683. SetDlgItemText(hwnd, IDC_EDITMUSIC, szFileName[num]); // 在IDC_EDITMUSIC编辑框显示将要播放的歌曲文件名
  684. mciSendString(str2, "", 0, NULL); // 播放选中歌曲
  685. getAllTime(hwnd);
  686. }
  687. //****************************** 停止播放当前正在播放的歌曲 *****************************************//
  688. void stopPlay(HWND hwnd)
  689. {
  690. TCHAR str[ 256];
  691. GetShortPathName(szFileNamePath[num], shortName, sizeof(shortName));
  692. wsprintf(str, "close %s", shortName);
  693. mciSendString(str, "", 0, NULL);
  694. }
  695. //******************************************* 静音 *************************************************//
  696. void silence(HWND hwnd)
  697. {
  698. TCHAR str[ 256] = "";
  699. TCHAR szCommand[MAX_PATH + 10];
  700. HWND hwCheck = GetDlgItem(hwnd,IDC_CHECK); // 得到CheckBox的句柄
  701. HWND hwndList = GetDlgItem(hwnd, IDC_LIST); // 得到ListBox的句柄
  702. int index = ListBox_GetCurSel(hwndList);
  703. ListBox_GetText(hwndList, index, str); // 得到歌曲名
  704. int count;
  705. for (count = 0; count < offset; count++)
  706. {
  707. if ( 0 == strcmp(str, szFileName[count]))
  708. {
  709. GetShortPathName(szFileNamePath[count], shortName, sizeof(shortName)); // 获得短路径
  710. if(BST_CHECKED == Button_GetCheck(hwCheck)) // 如果被选中,则静音
  711. {
  712. wsprintf(szCommand, TEXT( "setaudio %s off"), shortName);
  713. }
  714. if (BST_UNCHECKED == Button_GetCheck(hwCheck)) // 未被选中,回复正常
  715. {
  716. wsprintf(szCommand, TEXT( "setaudio %s on"), shortName);
  717. }
  718. mciSendString(szCommand, NULL, 0, NULL);
  719. } // end if
  720. } // end for
  721. }
  722. //****************************************************** 获取曲目总长度 *******************************************//
  723. void getAllTime(HWND hwnd)
  724. {
  725. TCHAR sPosition[ 256];
  726. TCHAR str[ 256];
  727. wsprintf(str, "status %s length", shortName);
  728. mciSendString(str, sPosition, 255, 0);
  729. allLength = strtol(sPosition, NULL, 0);
  730. /*strtol是atoi的增强版,主要体现在这几方面:   
  731. 1.不仅可以识别十进制整数,还可以识别其它进制的整数,取决于base参数,
  732. 比如strtol("0XDEADbeE~~", NULL, 16)返回0xdeadbee的值,strtol("0777~~", NULL, 8)返回0777的值。   
  733. 2.endptr是一个传出参数,函数返回时指向后面未被识别的第一个字符。
  734. 例如char *pos; strtol("123abc", &pos, 10);,strtol返回123,pos指向字符串中的字母a。
  735. 如果字符串开头没有可识别的整数,例如char *pos; strtol("ABCabc", &pos, 10);,则strtol返回0,pos指向字符串开头,
  736. 可以据此判断这种出错的情况,而这是atoi处理不了的。 */
  737. minite = allLength / 60000;
  738. second = (allLength / 1000) % 60;
  739. wsprintf(strTimeAll, "%.2d:%.2d", minite, second);
  740. SetDlgItemText(hwnd, IDC_EDITTIMEALL, strTimeAll);
  741. }
  742. //******************************************** 获取歌曲的详细信息(未完成!!) ********************************//
  743. void getSongMessage(HWND hwnd)
  744. {
  745. struct tagID3V1
  746. {
  747. char Header[ 4]; // 标签头必须是“TAG”否则认为没有标签
  748. char Title[ 31]; // 标题
  749. char Artist[ 31]; // 作者
  750. char Album[ 31]; // 专辑
  751. char Comment[ 31]; // 备注
  752. }ID3V1;
  753. FILE *fp;
  754. fp = fopen(szFileNamePath[num], "r");
  755. fseek(fp, -128L,SEEK_END);
  756. fread(ID3V1.Header, 3, 1, fp);
  757. // 判断标签头有无“TAG”,没有则认为没有标签
  758. if ( 0 == memcmp(ID3V1.Header, "TAG", 3))
  759. {
  760. ID3V1.Header[ 3] = '\0';
  761. fread(ID3V1.Title, 30, 1, fp);
  762. ID3V1.Title[ 30]= '\0';
  763. fread(ID3V1.Artist, 30, 1, fp);
  764. ID3V1.Artist[ 30]= '\0';
  765. fread(ID3V1.Album, 30, 1, fp);
  766. ID3V1.Album[ 30]= '\0';
  767. fread(ID3V1.Comment, 30, 1, fp);
  768. ID3V1.Comment[ 30]= '\0';
  769. TCHAR str[ 256];
  770. wsprintf(str, "标题 %s\n\n作者 %s\n\n专辑 %s\n\n备注 %s", ID3V1.Title, ID3V1.Artist, ID3V1.Album, ID3V1.Comment);
  771. MessageBox(hwnd, str, TEXT( "曲目信息"), MB_OK);
  772. }
  773. else
  774. {
  775. MessageBox(hwnd, TEXT( "此歌曲里未包含ID3V1标签"), TEXT( "曲目信息"), MB_OK);
  776. }
  777. }
  778. //********************************** 滑块函数 控制声音和进度 *****************************************//
  779. void Main_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
  780. {
  781. switch(GetDlgCtrlID(hwndCtl)) //得到控件ID
  782. {
  783. //控制音量滑块
  784. case IDC_SLIDERVOLUME:
  785. {
  786. int voice = SendMessage(GetDlgItem(hwnd, IDC_SLIDERVOLUME), TBM_GETPOS, 0, 0); //得到当前滑块的音量值
  787. //TBM_GETPOS:返回当前滑块位置所代表的值(逻辑位置)
  788. TCHAR szVoice[ 256];
  789. wsprintf(szVoice, "setaudio %s volume to %d", shortName, voice); //将音量设置到滑块的值
  790. mciSendString(szVoice, (LPTSTR) NULL, 0, 0);
  791. }
  792. break;
  793. case IDC_SLIDER: //歌曲的进度条
  794. {
  795. if(SB_ENDSCROLL == code)
  796. {
  797. long lPosition = SendMessage(GetDlgItem(hwnd, IDC_SLIDER), TBM_GETPOS, 0, 0); //得到当前的进度值
  798. //itoa(lPosition, curTime, 10);
  799. TCHAR strPos[ 256];
  800. wsprintf(strPos, "play %s from %ld", shortName, lPosition);
  801. //???????????????????????????????????????????不理解????????????????????????????????????????????????????????//
  802. mciSendString(strPos, (LPTSTR) NULL, 0, 0); //
  803. mciSendString(strPos, (LPTSTR) NULL, 0, 0); // 为什么要用两个一样的我不明白 //
  804. //?????????????????????????????????????????????????????????????????????????????????????????????????????????//
  805. }
  806. }
  807. break;
  808. }
  809. }
  810. void Main_OnClose(HWND hwnd)
  811. {
  812. EndDialog(hwnd, 0);
  813. }

连连看


  
  1. #include <graphics.h>
  2. #include <conio.h>
  3. #include <time.h>
  4. #include <stdio.h>
  5. #include <windows.h>
  6. #pragma comment(lib,"winmm.lib")
  7. /* 欢迎关注公众号“c语言与cpp编程”,关注后回复“加群”进学习交流群,关注送海量资料 */
  8. //150 150 12 7 21 易
  9. //60 100 16 9 32 中
  10. //100 120 14 8 28 难
  11. #define leftedge 150 //游戏区距左边框距离
  12. #define topedge 150 //游戏区距上边框距离
  13. #define COL 12 //游戏区列数
  14. #define ROW 7 //游戏区行数
  15. #define GridNum 21 //游戏图片数目
  16. #define GridW 42 //游戏图片的长
  17. #define GridH 48 //游戏图片的宽
  18. #define N 555 //开屏大小(宽)
  19. #define M 785 //开屏大小(长)
  20. IMAGE image[GridNum + 1][ 2]; //图片库
  21. IMAGE image2; //填充图片
  22. int GridID[ROW + 2][COL + 2]; //游戏图纸
  23. MOUSEMSG mouse; //记录鼠标信息
  24. struct GridInfor //记入击中图片信息
  25. {
  26. int idx,idy; //图纸坐标
  27. int leftx,lefty; //屏幕坐标
  28. int GridID; //图片类型
  29. }pre,cur,dur;
  30. struct //记录连线点
  31. {
  32. int x;
  33. int y;
  34. }point[ 4];
  35. static int pn; //记录连线点个数
  36. void InitFace (); //初始化界面
  37. void Shuffle (); //随即打乱图片
  38. void ShowGrid (); //显示图片
  39. void RandGrid (); //绘制地图
  40. void Link (); //连接两图
  41. void Des_direct (); //直接相消
  42. void Des_one_corner(); //一折相消
  43. void Des_two_corner(); //两折相消
  44. void Load_picture (); //加载图片
  45. void Init_Grid (GridInfor& pre); //初始化格子信息
  46. void Leftbottondown (MOUSEMSG mouse); //实现鼠标左击效果
  47. void Draw_frame (int leftx,int lefty); //绘制边框
  48. void Mousemove (int leftx,int lefty); //实现鼠标移动效果
  49. bool Judg_val (int leftx,int lefty); //判断鼠标是否在游戏区
  50. void SeleReact (int leftx,int lefty); //显示选中效果
  51. void TranstoPhycoor (int* idx,int* idy); //图纸坐标转变为屏幕坐标
  52. void GridPhy_coor (int& leftx,int& lefty); //规范物理坐标
  53. void iPaint (long x1,long y1,long x2,long y2); //将直线销毁
  54. void DrawLine (int x1,int y1,int x2,int y2) ; //用直线连接两图
  55. bool DesGrid (GridInfor pre,GridInfor cur); //判断两者是否能相消
  56. bool Match_direct (POINT ppre,POINT pcur); //判断两者是否能够直接相消
  57. bool Match_one_corner (POINT ppre,POINT pcur); //判断两者是否能一折相消
  58. bool Match_two_corner (POINT ppre,POINT pcur); //判断两者是否能两折相消
  59. void ExchaVal (GridInfor& pre,GridInfor& cur); //交换图片信息
  60. bool Single_click_judge (int mousex,int mousey); //判断单击是否有效
  61. void RecordInfor (int leftx,int lefty,GridInfor &grid); //记录选中的信息
  62. void TranstoDracoor (int mousex,int mousey,int *idx,int *idy); //鼠标坐标转化为图纸坐标
  63. void Explot (POINT point,int *left,int *right,int *top,int *bottel); //探索point点附近的空位置
  64. void main()
  65. {
  66. initgraph(M,N);
  67. mciSendString( "play game_begin.mp3 repeat", NULL, 0, NULL);
  68. InitFace();
  69. while( 1)
  70. {
  71. mouse = GetMouseMsg();
  72. switch(mouse.uMsg)
  73. {
  74. case WM_MOUSEMOVE:
  75. Mousemove(mouse.x,mouse.y); break;
  76. case WM_LBUTTONDOWN:
  77. if(Single_click_judge(mouse.x,mouse.y))
  78. {
  79. Leftbottondown(mouse);
  80. } break;
  81. default: break;
  82. }
  83. }
  84. closegraph();
  85. }
  86. 生成操作 //
  87. void RandGrid() //产生图片的标记
  88. {
  89. for( int iCount = 0, x = 1; x <= ROW; ++x )
  90. {
  91. for( int y = 1; y <= COL; ++y )
  92. {
  93. GridID[x][y] = iCount++ % GridNum + 1;
  94. } } }
  95. void Shuffle( ) //打乱棋盘
  96. {
  97. int ix, iy, jx, jy, grid;
  98. for( int k = 0; k < 84; ++k )
  99. {
  100. ix = rand() % ROW + 1; // 产生 1 - COL 的随机数
  101. iy = rand() % COL + 1; // 产生 1 - ROW 的随机数
  102. jx = rand() % ROW + 1; // 产生 1 - COL 的随机数
  103. jy = rand() % COL + 1; // 产生 1 - ROW 的随机数
  104. if( GridID[ix][iy] != GridID[jx][jy] ) //如果不相等就交换数据
  105. {
  106. grid = GridID[ix][iy];
  107. GridID[ix][iy] = GridID[jx][jy];
  108. GridID[jx][jy] = grid;
  109. } } }
  110. 初始化界面 ///
  111. void InitFace()
  112. {
  113. srand(( unsigned)time( NULL));
  114. Load_picture();
  115. RandGrid();
  116. IMAGE image3;
  117. loadimage(&image3, "res\\bg.bmp");
  118. putimage( 0, 0,&image3);
  119. getimage(&image2, 3 * 42, 2 * 48, 42, 48);
  120. Shuffle();
  121. ShowGrid();
  122. }
  123. void Load_picture() //加载图片
  124. {
  125. IMAGE image1,background;
  126. loadimage(&image1, "IMAGE", "grids");
  127. SetWorkingImage(&image1);
  128. for( int i = 1 ;i < GridNum + 1 ;i ++)
  129. for( int j = 0;j < 2;j++)
  130. getimage(&image[i][j],j * 42,i * 48, 42, 48);
  131. loadimage(&background, "IMAGE", "bg");
  132. SetWorkingImage(&background);
  133. getimage(&image2, 3 * 42, 2 * 48, 42, 48);
  134. SetWorkingImage();
  135. putimage( 0, 0,&background);
  136. }
  137. void ShowGrid()
  138. {
  139. int idx,idy;
  140. for( int i = 0 ;i < ROW; i ++)
  141. for( int j = 0 ;j < COL ; j++)
  142. {
  143. idy = i * 48 + topedge ,idx = j * 42 + leftedge;
  144. putimage(idx,idy,&image[GridID[i + 1][j + 1]][ 0]);
  145. } }
  146. /鼠标操作
  147. void Mousemove (int leftx,int lefty) //鼠标移动时的变化
  148. {
  149. static int prex,prey,preidx,preidy, curidx,curidy;
  150. if(Judg_val(leftx,lefty))
  151. {
  152. TranstoDracoor(leftx,lefty,&curidx,&curidy); //转化为图纸坐标
  153. if(GridID[curidy][curidx] != 0)
  154. {
  155. GridPhy_coor(leftx,lefty);
  156. if(pre.idx == preidx && pre.idy == preidy)
  157. putimage(prex,prey,&image[GridID[preidy][preidx]][ 1]);
  158. else
  159. putimage(prex,prey,&image[GridID[preidy][preidx]][ 0]);
  160. prex = leftx, prey = lefty;
  161. preidx = curidx, preidy = curidy;
  162. Draw_frame(leftx,lefty); //绘制边框
  163. } } }
  164. void Leftbottondown (MOUSEMSG mouse) //左击时的变化
  165. {
  166. static int click = 0, idx,idy;
  167. click++;
  168. SeleReact (mouse.x,mouse.y); //显示选中效果
  169. if(click == 1) RecordInfor(mouse.x,mouse.y,pre);
  170. if(click == 2)
  171. {
  172. TranstoDracoor (mouse.x,mouse.y,&idx,&idy);
  173. if(idx != pre.idx || idy != pre.idy)
  174. {
  175. RecordInfor (mouse.x,mouse.y,cur);
  176. if(pre.GridID == cur.GridID && DesGrid(pre,cur))
  177. {
  178. GridID[pre.idy][pre.idx] = GridID[cur.idy][cur.idx] = 0;
  179. Link (); pn = 0;
  180. putimage(pre.leftx,pre.lefty,&image2);
  181. putimage(cur.leftx,cur.lefty,&image2);
  182. Init_Grid(pre); Init_Grid(cur); click = 0;
  183. }
  184. else
  185. {
  186. ExchaVal(dur,pre); ExchaVal(pre,cur);
  187. Init_Grid(cur); click = 1;
  188. putimage(dur.leftx,dur.lefty,&image[GridID[dur.idy][dur.idx]][ 0]);
  189. } }
  190. else click = 1;
  191. } }
  192. void SeleReact (int leftx,int lefty) //选中时效果
  193. {
  194. if(Judg_val(leftx,lefty))
  195. {
  196. int idx,idy;
  197. TranstoDracoor (leftx,lefty,&idx,&idy);
  198. GridPhy_coor (leftx,lefty);
  199. putimage(leftx,lefty,&image[GridID[idy][idx]][ 1]);
  200. } }
  201. bool Judg_val(int leftx,int lefty) //判断鼠标是否在游戏区
  202. {
  203. return leftx > leftedge && leftx < leftedge + GridW * COL &&
  204. lefty > topedge && lefty < topedge + GridH * ROW;
  205. }
  206. void TranstoDracoor (int mousex,int mousey ,int *idx,int *idy) //鼠标坐标转化为图纸坐标
  207. {
  208. if(Judg_val(mousex,mousey))
  209. {
  210. *idx = (mousex - leftedge) / 42 + 1;
  211. *idy = (mousey - topedge) / 48 + 1 ;
  212. } }
  213. void RecordInfor(int leftx,int lefty,GridInfor &grid) //记录选中的信息
  214. {
  215. TranstoDracoor(leftx,lefty,&grid.idx,&grid.idy);
  216. grid.leftx = (grid.idx - 1) * 42 + leftedge;
  217. grid.lefty = (grid.idy - 1) * 48 + topedge;
  218. grid.GridID = GridID[grid.idy][grid.idx];
  219. }
  220. bool Single_click_judge (int mousex,int mousey) //判断单击是否有效
  221. {
  222. int idx,idy;
  223. TranstoDracoor (mousex,mousey,&idx,&idy); //转化为图纸坐标
  224. if(Judg_val(mouse.x,mouse.y) && GridID[idy][idx] != 0)
  225. return true;
  226. return false;
  227. }
  228. void Draw_frame(int leftx,int lefty) //绘制方框
  229. {
  230. setcolor(RGB( 126, 91, 68));
  231. setlinestyle(PS_SOLID, NULL, 1);
  232. rectangle(leftx,lefty,leftx+ 41,lefty+ 47);
  233. rectangle(leftx + 2,lefty + 2,leftx+ 39,lefty+ 45);
  234. setcolor(RGB( 250, 230, 169));
  235. rectangle(leftx + 1,lefty + 1,leftx+ 40,lefty+ 46);
  236. }
  237. 判断消除操作/
  238. bool DesGrid (GridInfor pre,GridInfor cur) //判断两者是否能相消
  239. {
  240. bool match = false; POINT ppre,pcur;
  241. ppre.x = pre.idx; ppre.y = pre.idy;
  242. pcur.x = cur.idx; pcur.y = cur.idy;
  243. if(Match_direct(ppre,pcur)) match = true;
  244. else if(Match_one_corner(ppre,pcur)) match = true;
  245. else if(Match_two_corner(ppre,pcur)) match = true;
  246. return match;
  247. }
  248. bool Match_direct(POINT ppre,POINT pcur) //判断两者是否能够直接相消
  249. {
  250. int k,t;
  251. if(ppre.x == pcur.x)
  252. {
  253. k = ppre.y > pcur.y ? ppre.y : pcur.y;
  254. t = ppre.y < pcur.y ? ppre.y : pcur.y;
  255. if(t + 1 == k) goto FIND;
  256. for( int i = t + 1;i < k ;i++)
  257. if(GridID[i][ppre.x] != 0) return false;
  258. if(i == k) goto FIND;
  259. }
  260. else
  261. if(ppre.y == pcur.y)
  262. {
  263. k = ppre.x > pcur.x ? ppre.x : pcur.x;
  264. t = ppre.x < pcur.x ? ppre.x : pcur.x;
  265. if(t + 1 == k) goto FIND;
  266. for( int i = t + 1;i < k ;i++)
  267. if(GridID[ppre.y][i] != 0) return false;
  268. if(i == k) goto FIND;
  269. }
  270. return false;
  271. FIND: point[pn].x = pcur.x, point[pn].y = pcur.y; pn++;
  272. point[pn].x = ppre.x, point[pn].y = ppre.y; pn++;
  273. return true;
  274. }
  275. bool Match_one_corner(POINT ppre,POINT pcur) //判断两者是否能一折相消
  276. {
  277. int left,right,top,bottel,x = ppre.x,y = ppre.y;
  278. Explot(ppre,&left,&right,&top,&bottel);
  279. ppre.y = top - 1;
  280. RESEARCHX: if(ppre.y < bottel) ppre.y++;
  281. else goto BACK;
  282. if(Match_direct(ppre,pcur)) goto FIND;
  283. else goto RESEARCHX;
  284. BACK: ppre.y = y; ppre.x = left - 1;
  285. RESEARCHY: if(ppre.x < right) ppre.x++;
  286. else goto REBACK;
  287. if(Match_direct(ppre,pcur)) goto FIND;
  288. else goto RESEARCHY;
  289. REBACK: pn = 0; return false;
  290. FIND: point[pn].x = x,point[pn].y = y,pn++;
  291. return true;
  292. }
  293. bool Match_two_corner(POINT ppre,POINT pcur) //判断两者是否能两折相消
  294. {
  295. int left,right,top,bottel,x = ppre.x,y = ppre.y;
  296. Explot(ppre,&left,&right,&top,&bottel);
  297. ppre.y = top - 1;
  298. RESEARCHX: if(ppre.y < bottel) ppre.y++;
  299. else goto BACK;
  300. if(Match_one_corner(ppre,pcur)) goto FIND;
  301. else goto RESEARCHX;
  302. BACK: ppre.y = y; ppre.x = left - 1;
  303. RESEARCHY: if(ppre.x < right) ppre.x++;
  304. else goto REBACK;
  305. if(Match_one_corner(ppre,pcur)) goto FIND;
  306. else goto RESEARCHY;
  307. REBACK: pn = 0; return false;
  308. FIND: point[pn].x = x,point[pn].y = y,pn++;
  309. return true;
  310. }
  311. void Explot(POINT point,int *left,int *right,int *top,int *bottel)
  312. {
  313. int x = point.x,y = point.y; x++;
  314. while(x <= COL + 1 && GridID[y][x] == 0) x++; *right = x - 1; x = point.x; x--;
  315. while(x >= 0 && GridID[y][x] == 0) x--; *left = x + 1; x = point.x; y++;
  316. while(y <= ROW + 1 && GridID[y][x] == 0) y++; *bottel= y - 1; y = point.y; y--;
  317. while(y >= 0 && GridID[y][x] == 0) y--; *top = y + 1;
  318. }
  319. /消除操作
  320. void Link ()
  321. {
  322. switch(pn)
  323. {
  324. case 2:
  325. Des_direct(); break;
  326. case 3:
  327. Des_one_corner(); break;
  328. case 4:
  329. Des_two_corner(); break;
  330. default : break;
  331. } }
  332. void Des_direct ()
  333. {
  334. TranstoPhycoor(&point[ 0].x,&point[ 0].y);
  335. TranstoPhycoor(&point[ 1].x,&point[ 1].y);
  336. DrawLine(point[ 0].x,point[ 0].y,point[ 1].x,point[ 1].y);
  337. Sleep( 250);
  338. iPaint(point[ 0].x,point[ 0].y,point[ 1].x,point[ 1].y);
  339. }
  340. void Des_one_corner()
  341. {
  342. TranstoPhycoor(&point[ 0].x,&point[ 0].y);
  343. TranstoPhycoor(&point[ 1].x,&point[ 1].y);
  344. TranstoPhycoor(&point[ 2].x,&point[ 2].y);
  345. DrawLine(point[ 0].x,point[ 0].y,point[ 1].x,point[ 1].y);
  346. DrawLine(point[ 1].x,point[ 1].y,point[ 2].x,point[ 2].y);
  347. Sleep( 250);
  348. iPaint(point[ 0].x,point[ 0].y,point[ 1].x,point[ 1].y);
  349. iPaint(point[ 1].x,point[ 1].y,point[ 2].x,point[ 2].y);
  350. }
  351. void Des_two_corner()
  352. {
  353. TranstoPhycoor(&point[ 0].x,&point[ 0].y);
  354. TranstoPhycoor(&point[ 1].x,&point[ 1].y);
  355. TranstoPhycoor(&point[ 2].x,&point[ 2].y);
  356. TranstoPhycoor(&point[ 3].x,&point[ 3].y);
  357. DrawLine(point[ 0].x,point[ 0].y,point[ 1].x,point[ 1].y);
  358. DrawLine(point[ 1].x,point[ 1].y,point[ 2].x,point[ 2].y);
  359. DrawLine(point[ 2].x,point[ 2].y,point[ 3].x,point[ 3].y);
  360. Sleep( 250);
  361. iPaint(point[ 0].x,point[ 0].y,point[ 1].x,point[ 1].y);
  362. iPaint(point[ 1].x,point[ 1].y,point[ 2].x,point[ 2].y);
  363. iPaint(point[ 2].x,point[ 2].y,point[ 3].x,point[ 3].y);
  364. }
  365. void DrawLine (int x1,int y1,int x2,int y2)
  366. {
  367. setlinestyle(PS_SOLID, NULL, 3);
  368. setcolor(RGB( 90, 43, 9));
  369. line(x1 + 21,y1 + 24,x2 + 21,y2 + 24);
  370. }
  371. void iPaint (long x1,long y1,long x2,long y2)
  372. {
  373. int minx,miny,maxx,maxy;
  374. if(x1 == x2)
  375. {
  376. maxy = y1 > y2? y1:y2;
  377. miny = y1 < y2? y1:y2;
  378. for( int i = miny; i <= maxy;i += 48)
  379. putimage(x1,i,&image2);
  380. }
  381. else if(y1 == y2)
  382. {
  383. maxx = x1 > x2? x1:x2;
  384. minx = x1 < x2? x1:x2;
  385. for( int j = minx; j <= maxx;j += 42 )
  386. putimage(j,y1,&image2);
  387. } }
  388. /
  389. void GridPhy_coor(int& leftx,int& lefty) //转化为标准物理坐标
  390. {
  391. leftx = ((leftx - leftedge) / 42) * 42 + leftedge;
  392. lefty = ((lefty - topedge) / 48) * 48 + topedge;
  393. }
  394. void ExchaVal(GridInfor& pre,GridInfor& cur) //交换格子信息
  395. {
  396. pre.GridID = cur.GridID;
  397. pre.idx = cur.idx;pre.idy = cur.idy;
  398. pre.leftx = cur.leftx;pre.lefty = cur.lefty;
  399. }
  400. void Init_Grid(GridInfor& grid) //初始化格子
  401. {
  402. grid.GridID = 0;
  403. grid.idx = 0; grid.idy = 0;
  404. grid.leftx = 0; grid.lefty = 0;
  405. }
  406. void TranstoPhycoor (int* idx,int* idy) //图纸坐标转变为屏幕坐标
  407. {
  408. int x ,y;x =*idx,y = *idy;
  409. *idy = (y - 1) * 48 + leftedge;
  410. *idx = (x - 1) * 42 + topedge;
  411. }
  412. ///end//

其他的就不放了,有需要源码的自取

60个项目源码大全,点击获取

最后,有什么其他问题可以私聊我,欢迎大家一键三连,点赞+收藏+评论转发。


转载:https://blog.csdn.net/weixin_41055260/article/details/116865434
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场