c++ 贪吃蛇实现 新手 各种杂七杂八的问题聚集地

煜_ 2017-05-30 10:44:22
问题1://播放背景BGM,Debug下运行没有声音,直接运行exe能听到声音
void PlayBgm()
{
TCHAR szBuffer[256] = {0};
TCHAR Buffer[256] = {0};
WCHAR VolumCmd[256];
WCHAR volume[256];
//先关闭failure.mp3
wsprintf(szBuffer,L"failure.mp3");
wsprintf(Buffer,L"close \"%s\"",szBuffer);
mciSendString(Buffer,0,0,0);

//再载入bgm
wsprintf(szBuffer,L"The Dawn.mp3");
wsprintf(Buffer,L"open \"%s\"",szBuffer);
mciSendString(Buffer,NULL,0,NULL); //打开设备
wsprintf(Buffer,L"play \"%s\" repeat",szBuffer);
mciSendString(Buffer,NULL,0,NULL); //播放

wsprintf(VolumCmd,L"status \"%s\" volume",szBuffer);
mciSendString(VolumCmd,volume, sizeof(volume), 0 );
int v0 = _wtoi(volume);
wsprintf(VolumCmd,L"setaudio \"%s\" volume to %i",szBuffer,500);//修改音量
mciSendString(VolumCmd,0,0,0);
}

从网上下载的vs可运行的贪吃蛇代码,想试着修改BGM,但是修改红色部分的歌曲名之后,运行exe文件就没有声音了,修改回去,又会有声音,想要修改的mp3文件已放入debug中。求大神帮忙看看是怎么回事。
问题二:试着新建了一个控制台应用程序,但是把代码粘过去之后(把相应的图标文件,位图文件,mp3文件也都拷进了对应文件),运行一直出错:

错误 2 error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用 F:\ruanjian2\vs2013\files\lianxi\lianxi\MSVCRTD.lib(crtexe.obj) lianxi

上网查之后,加了个void main(){}
然后就只出现黑框(正真的控制台了吧)
求大佬能指点一下

代码放上来就超字数了,怎么办啊QAQ


...全文
2821 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-03-20
  • 打赏
  • 举报
回复
《Visual C++ 游戏开发经典案例详解》
一条晚起的虫 2018-03-20
  • 打赏
  • 举报
回复
// 你可以在debug时输出 GetCurrentDirectory(),就可以看到会调用哪个目录下的文件了。
一条晚起的虫 2018-03-20
  • 打赏
  • 举报
回复
// mp3,在debug下无声,直接运行有声,显然你的mp3路径错了 // 默认,debug时,你没有指明路径的话,会调用源代码同一目录的文件,而不是debug输出目录的文件。
  • 打赏
  • 举报
回复
这里说的格式不是指mp3格式,是你播放程序对mp3有没有什么t特别 要求。如果对mp3格式熟悉,可以另找个普通mp3文件来剖析比较下。
schlafenhamster 2017-06-15
  • 打赏
  • 举报
回复
想要修改的mp3文件已放入debug中 要放入 Release 中
  • 打赏
  • 举报
回复
1.猜测可能你的mp3格式与原来不匹配
2.是vs窗口程序与控制台程序的编译冲突
VS2005中的设置

1.菜单中选择Project->Properties, 弹出Property Pages窗口

2.在左边栏中依次选择:ConfigurationProperties->C/C++->Preprocessor,然后在右边栏的PreprocessorDefinitions对应的项中删除_WINDOWS,添加_CONSOLE

3.在左边栏中依次选择:ConfigurationProperties->Linker->System,然后在右边栏的SubSystem对应的项改为console(/SUBSYSTEM:CONSOLE)
煜_ 2017-05-30
  • 打赏
  • 举报
回复
第二个问题已解决,求大佬帮忙看看第一个问题,如何修改bgm
煜_ 2017-05-30
  • 打赏
  • 举报
回复
#include <windows.h> #include <tchar.h>//使用swprintf_s函数所需的头文件 #include "Snake.h" #include "time.h" #include "mmsystem.h" #include "iostream" using namespace std; //-----------------------------------【库文件包含部分】--------------------------------------- #pragma comment (lib,"User32.lib") #pragma comment (lib,"Gdi32.lib") #pragma comment(lib,"winmm.lib") //调用PlaySound函数所需库文件 #pragma comment(lib,"Msimg32.lib") //添加使用TransparentBlt函数所需的库文件 //-----------------------------------【宏定义部分】-------------------------------------------- #define WINDOW_WIDTH 815 //为窗口宽度定义的宏,以方便在此处修改窗口宽度 #define WINDOW_HEIGHT 640 //为窗口高度定义的宏,以方便在此处修改窗口高度 #define WINDOW_TITLE L"贪吃蛇" //为窗口标题定义的宏 CSnake snake; HDC g_hdc = NULL, g_mdc = NULL, g_bufdc = NULL; //全局设备环境句柄与两个全局内存DC句柄 HBITMAP g_hHead = NULL, g_hBody = NULL, g_hCandy = NULL, g_hFailure = NULL; HBITMAP g_hBackGround = NULL; //定义位图句柄数组用于存储四张方向图,以及定义存储背景图的句柄 DWORD g_tPre = 0, g_tNow = 0; //声明l两个函数来记录时间,g_tPre记录上一次绘图的时间,g_tNow记录此次准备绘图的时间 int candy_x, candy_y; int g_iDirection = 0;//g_iDirection为蛇移动方向,这里我们中以0,1,2,3代表上,下,左,右方向上的移动 int g_iIntervalTime = 200; bool g_bChangeDirection = 0; bool g_bExistCandy = 0; bool g_bKeyDown = 0;//判断当前是否两个方向键一起按下,这样可以防止蛇斜方向运动 bool g_bFailure = 0; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);//窗口过程函数 BOOL Game_Init(HWND hwnd); //在此函数中进行资源的初始化 VOID Game_Paint(HWND hwnd); //在此函数中进行绘图代码的书写 BOOL Game_CleanUp(HWND hwnd); //在此函数中进行资源的清理 void SetCandy(); //将新的candy放置在蛇未占据的地方 void ReplayGame(); //重新开始游戏 //-----------------------------------【WinMain( )函数】-------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //【1】开始设计一个完整的窗口类 WNDCLASSEX wndClass = { 0 }; //用WINDCLASSEX定义了一个窗口类 wndClass.cbSize = sizeof(WNDCLASSEX); //设置结构体的字节数大小 wndClass.style = CS_HREDRAW | CS_VREDRAW; //设置窗口的样式 wndClass.lpfnWndProc = WndProc; //设置指向窗口过程函数的指针 wndClass.cbClsExtra = 0; //窗口类的附加内存,取0就可以了 wndClass.cbWndExtra = 0; //窗口的附加内存,依然取0就行了 wndClass.hInstance = hInstance; //指定包含窗口过程的程序的实例句柄。 wndClass.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); //本地加载自定义ico图标 wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); //指定窗口类的光标句柄。 wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //为hbrBackground成员指定一个白色画刷句柄 wndClass.lpszMenuName = NULL; //用一个以空终止的字符串,指定菜单资源的名字。 wndClass.lpszClassName = L"tanchishe"; //用一个以空终止的字符串,指定窗口类的名字。 //【2】注册窗口类 if (!RegisterClassEx(&wndClass)) //设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口 return -1; //【3】正式创建窗口 HWND hwnd = CreateWindow(L"tanchishe", WINDOW_TITLE, //喜闻乐见的创建窗口函数CreateWindow WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); //【4】窗口的移动、显示与更新 MoveWindow(hwnd, 20, 20, WINDOW_WIDTH, WINDOW_HEIGHT, true); //调整窗口显示时的位置,使窗口左上角位于(250,80)处 ShowWindow(hwnd, nShowCmd); //调用ShowWindow函数来显示窗口 UpdateWindow(hwnd); //对窗口进行更新,就像我们买了新房子要装修一样 //游戏资源的初始化,若初始化失败,弹出一个消息框,并返回FALSE if (!Game_Init(hwnd)) { MessageBox(hwnd, L"资源初始化失败", L"消息窗口", 0); //使用MessageBox函数,创建一个消息窗口 return FALSE; } //【5】消息循环过程 MSG msg = { 0 }; //定义并初始化msg while (msg.message != WM_QUIT) //使用while循环,如果消息不是WM_QUIT消息,就继续循环 { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) //查看应用程序消息队列,有消息时将队列中的消息派发出去。 { TranslateMessage(&msg); //将虚拟键消息转换为字符消息 DispatchMessage(&msg); //分发一个消息给窗口程序。 } else { g_tNow = GetTickCount(); //获取当前系统时间 if (g_tNow - g_tPre >= g_iIntervalTime) //当此次循环运行与上次绘图时间相差0.4秒时再进行重绘操作 if (!g_bFailure) Game_Paint(hwnd); } } //【6】窗口类的注销 UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance); //程序准备结束,注销窗口类 return 0; } //-----------------------------------【WndProc( )函数】-------------------------------------- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) //switch语句开始 { case WM_KEYDOWN: //按下键盘消息 //判断按键的虚拟键码 if (g_bKeyDown) break; switch (wParam) { case VK_ESCAPE: //按下【Esc】键 DestroyWindow(hwnd); // 销毁窗口, 并发送一条WM_DESTROY消息 PostQuitMessage(0); //结束程序 break; case VK_UP: //按下【↑】键 snake.MoveBody(0); g_bKeyDown = 1; break; case VK_DOWN: //按下【↓】键 snake.MoveBody(1); g_bKeyDown = 1; break; case VK_LEFT: //按下【←】键 snake.MoveBody(2); g_bKeyDown = 1; break; case VK_RIGHT: //按下【→】键 snake.MoveBody(3); g_bKeyDown = 1; break; case VK_SPACE: //按下【空格】键 if (g_bFailure) ReplayGame(); //重新开始游戏 break; } g_bChangeDirection = 1;//已改变方向 //g_bKeyDown = 1; break; //跳出该switch语句 case WM_DESTROY: //若是窗口销毁消息 Game_CleanUp(hwnd); //调用自定义的资源清理函数Game_CleanUp()进行退出前的资源清理 PostQuitMessage(0); //向系统表明有个线程有终止请求。用来响应WM_DESTROY消息 break; //跳出该switch语句 default: //若上述case条件都不符合,则执行该default语句 return DefWindowProc(hwnd, message, wParam, lParam); //调用缺省的窗口过程 } return 0; //正常退出 } //-----------------------------------【Game_Init( )函数】-------------------------------------- // 描述:初始化函数,进行一些简单的初始化 //------------------------------------------------------------------------------------------------ BOOL Game_Init(HWND hwnd) { srand((unsigned)time(NULL)); HBITMAP bmp; g_hdc = GetDC(hwnd); g_mdc = CreateCompatibleDC(g_hdc); //创建一个和hdc兼容的内存DC g_bufdc = CreateCompatibleDC(g_hdc);//再创建一个和hdc兼容的缓冲DC bmp = CreateCompatibleBitmap(g_hdc, WINDOW_WIDTH, WINDOW_HEIGHT); SelectObject(g_mdc, bmp); //加载各张跑动图及背景图,这里以0,1,2,3来代表人物的上,下,左,右移动 g_hHead = (HBITMAP)LoadImage(NULL, L"head.bmp", IMAGE_BITMAP, 40, 80, LR_LOADFROMFILE); g_hBody = (HBITMAP)LoadImage(NULL, L"body.bmp", IMAGE_BITMAP, 40, 80, LR_LOADFROMFILE); g_hCandy = (HBITMAP)LoadImage(NULL, L"candy.bmp", IMAGE_BITMAP, 40, 80, LR_LOADFROMFILE); g_hFailure = (HBITMAP)LoadImage(NULL, L"failure.bmp", IMAGE_BITMAP, 1086, 396, LR_LOADFROMFILE); g_hBackGround = (HBITMAP)LoadImage(NULL, L"bk.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE); //设置字体 HFONT hFont; hFont = CreateFont(25, 0, 0, 0, 700, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("钟齐段宁行书")); SelectObject(g_mdc, hFont); SetBkMode(g_mdc, TRANSPARENT); Game_Paint(hwnd); return TRUE; } //-----------------------------------【Game_Paint( )函数】-------------------------------------- // 描述:绘制函数,在此函数中进行绘制操作 //-------------------------------------------------------------------------------------------------- VOID Game_Paint(HWND hwnd) { //先在mdc中贴上背景图 SelectObject(g_bufdc, g_hBackGround); BitBlt(g_mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY); //若最近没有按下方向键的话,将自动运动 if (!g_bChangeDirection) { switch (snake.head.iDirection) { case 0: snake.MoveBody(0); break; case 1: snake.MoveBody(1); break; case 2: snake.MoveBody(2); break; case 3: snake.MoveBody(3); break; default: break; } } g_bChangeDirection = 0; //这里首先判断蛇头有没有碰到其他物体 if (snake.head.x<-20 || snake.head.x>780 || snake.head.y<-20 || snake.head.y>580)//撞墙 g_bFailure = 1; else { for (int i = 0; i<snake.iSumPanel; i++) { if (snake.head.x == snake.body[i].x&&snake.head.y == snake.body[i].y)//撞自己 g_bFailure = 1; } } if (g_bFailure) { //绘制失败文字 SelectObject(g_bufdc, g_hFailure); BitBlt(g_mdc, 130, 200, 543, 396, g_bufdc, 543, 0, SRCAND); BitBlt(g_mdc, 130, 200, 543, 396, g_bufdc, 0, 0, SRCPAINT); WCHAR str[100]; swprintf_s(str, L"您的分数为:%d", snake.iSumPanel - 1); SetTextColor(g_mdc, RGB(0, 0, 255)); TextOut(g_mdc, 0, 0, str, wcslen(str)); swprintf_s(str, L"请按空格键继续"); SetTextColor(g_mdc, RGB(0, 0, 255)); TextOut(g_mdc, 325, 630, str, wcslen(str)); BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY); return; } //绘制糖果 if (!g_bExistCandy) SetCandy(); SelectObject(g_bufdc, g_hCandy); BitBlt(g_mdc, candy_x, candy_y, 40, 40, g_bufdc, 0, 40, SRCAND); BitBlt(g_mdc, candy_x, candy_y, 40, 40, g_bufdc, 0, 0, SRCPAINT); //当蛇头遇到糖果时 if (snake.head.x == candy_x&&snake.head.y == candy_y) { snake.EatCandy(); g_bExistCandy = 0; } //绘制蛇头 SelectObject(g_bufdc, g_hHead); BitBlt(g_mdc, snake.head.x, snake.head.y, 40, 40, g_bufdc, 0, 40, SRCAND); BitBlt(g_mdc, snake.head.x, snake.head.y, 40, 40, g_bufdc, 0, 0, SRCPAINT); //绘制蛇身 if (snake.iSumPanel>0) { SelectObject(g_bufdc, g_hBody); for (int i = 0; i<snake.iSumPanel; i++) { BitBlt(g_mdc, snake.body[i].x, snake.body[i].y, 40, 40, g_bufdc, 0, 40, SRCAND); BitBlt(g_mdc, snake.body[i].x, snake.body[i].y, 40, 40, g_bufdc, 0, 0, SRCPAINT); } } //将最后的画面显示在窗口中 BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY); g_bKeyDown = 0; g_tPre = GetTickCount(); //记录此次绘图时间 } //-----------------------------------【Game_CleanUp( )函数】-------------------------------- // 描述:资源清理函数,在此函数中进行程序退出前资源的清理工作 //--------------------------------------------------------------------------------------------------- BOOL Game_CleanUp(HWND hwnd) { //释放资源对象 DeleteObject(g_hBackGround); DeleteObject(g_hHead); DeleteObject(g_hBody); DeleteObject(g_hCandy); DeleteDC(g_bufdc); DeleteDC(g_mdc); ReleaseDC(hwnd, g_hdc); return TRUE; } //-----------------------------------【其他函数】-------------------------------- void SetCandy() { //随机放置糖果的位置 a: candy_x = 40 * (rand() % 20); candy_y = 40 * (rand() % 15); if (candy_x == snake.head.x&&candy_y == snake.head.y)//若新糖果与蛇头重合 goto a; for (int i = 0; i<snake.iSumPanel; i++) if (candy_x == snake.body[i].x&&candy_y == snake.body[i].y)//若新糖果与蛇身重合 goto a; g_bExistCandy = 1; return; } //重新开始游戏 void ReplayGame() { g_bFailure = 0; snake.iSumPanel = 1; snake.head.x = 360; snake.head.y = 360; }
煜_ 2017-05-30
  • 打赏
  • 举报
回复
#pragma once struct Occupy { int x; int y; int iDirection;//方向,0为上,1为下,2为左,3为右 }; class CSnake { public: CSnake(void); ~CSnake(void); public: //处理下一次移动后的各个节点的位置 void MoveBody(int dir); //处理吃到糖果后的变化,实际上不太需要这个函数,这里为了直观,保留之 void EatCandy(); //一般成员变量定为私有,这里为了方便,设置为public public: //头的位置 Occupy head; //身体的位置,默认最多300个,不够再改 Occupy body[300]; //身体的总节数 int iSumPanel; }; CSnake::CSnake(void)//构造函数 { //初始化 head.x = 360; head.y = 360; head.iDirection = 3; iSumPanel = 1; } CSnake::~CSnake(void) { } void CSnake::MoveBody(int dir) { //这里额外记录一个节点,用于吃到candy时的备用 if (iSumPanel == 0) body[0] = head; //若存在身体 else { //身体长度大于0的话,禁止直接反向运动 if (head.iDirection == 0 && dir == 1) return; if (head.iDirection == 1 && dir == 0) return; if (head.iDirection == 2 && dir == 3) return; if (head.iDirection == 3 && dir == 2) return; //这里额外记录一个节点,吃到candy时可直接使用该节点 for (int i = iSumPanel; i>0; i--) { body[i] = body[i - 1]; } body[0].iDirection = head.iDirection; body[0].x = head.x; body[0].y = head.y; } switch (dir) { case 0: head.y -= 40; head.iDirection = 0; break; case 1: head.y += 40; head.iDirection = 1; break; case 2: head.x -= 40; head.iDirection = 2; break; case 3: head.x += 40; head.iDirection = 3; break; default: break; } return; } void CSnake::EatCandy() { iSumPanel++; } //Snake.h头文件
煜_ 2017-05-30
  • 打赏
  • 举报
回复
引用 4 楼 js_gary 的回复:
1.猜测可能你的mp3格式与原来不匹配 2.是vs窗口程序与控制台程序的编译冲突 VS2005中的设置 1.菜单中选择Project->Properties, 弹出Property Pages窗口 2.在左边栏中依次选择:ConfigurationProperties->C/C++->Preprocessor,然后在右边栏的PreprocessorDefinitions对应的项中删除_WINDOWS,添加_CONSOLE 3.在左边栏中依次选择:ConfigurationProperties->Linker->System,然后在右边栏的SubSystem对应的项改为console(/SUBSYSTEM:CONSOLE)
mp3文件应该不分类吧

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧