花费三天时间写了一个扫雷游戏大家指导指导
目前实现了有初中高级,有红旗问号标志,但是没有时间显示,因为时间函数还没写好图片是偷懒了盗用别人写的代码里的图片
这里是源代码和图片文件
http://pan.baidu.com/share/link?shareid=3987660787&uk=2988506976
程序代码:
/**************************** ** 程序名称:扫雷游戏 * ** 完成时间:3013/07/16 * ** 编程人员: * ****************************/ #include<graphics.h> #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<time.h> #include<string.h> /**********宏定义区域 ******************/ #define BOMB 9 #define FLAG_OPEN -1 /***********数据类型定义区域 ************/ typedef struct map { int x; // 横坐标 int y; // 纵坐标 int count; // 方格内的数字 int flag; // 当前状态(初始,翻开,红旗,问号) }Map; struct size { int Length; int Width; int row; int col; int Lnum; }Wnd_size; /***********变量定义区域 ***************/ static const int side = 40; IMAGE img_flag[4]; // 存储状态标志图 IMAGE img_Bomb[10]; // 雷相关资源 static int *save_bomb; // 10个雷横纵20个坐标 static int *cnt; // 通关要翻的格数 static int g_time = 0; /********** 函数声明区域 ***************/ void initData(Map **LandMap); void initWindow(Map **LandMap); void initGame(Map **LandMap); void GetLandmine(Map **LandMap); void setNum(int x,int y,Map **LandMap); void putNum(int x,int y,Map **LandMap); void putImg(IMAGE img,int x,int y); void dealMouseMsg(Map **LandMap); void RMsg(int x,int y,Map **LandMap); void LMsg(int x,int y,Map **LandMap); void Bomb(int x,int y,Map **LandMap); void dealEmpty(int x, int y,Map **LandMap); void setFlag(int x,int y,Map **LandMap); void game_lose(); void game_win(); void cout_time(); void setSize(int row,int col,int n); void select_deg(int *m_size); void set_bombtime(int *b_time); /********* 函数定义区域 ****************/ void set_bombtime(int *b_time) { /* 设置雷爆炸的速度 */ switch(Wnd_size.Lnum) { case 10: *b_time = 30;break; case 40: *b_time = 20;break; case 99: *b_time = 10;break; } } void select_deg(int *m_size) { /* 初始化一个窗口让用户选择游戏等级 */ IMAGE img; MOUSEMSG msg; IMAGE img_deg[3]; int len = 300,width = 400; int len_img = 90; initgraph(len,width); setbkcolor(BLUE); cleardevice(); loadimage(&img,_T("./res/num.bmp"),len,width,false); putImg(img,0,0); loadimage(&img_deg[0],_T("./res/easy.bmp"),len_img,50,false); loadimage(&img_deg[1],_T("./res/middle.bmp"),len_img,50,false); loadimage(&img_deg[2],_T("./res/hard.bmp"),len_img,50,false); putImg(img_deg[0],(len - len_img)/2,width/5); putImg(img_deg[1],(len - len_img)/2,(width/5) * 2); putImg(img_deg[2],(len - len_img)/2,(width/5) * 3); while (1) { FlushMouseMsgBuffer(); msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN && msg.x >= ((len - len_img)/2) && msg.x <= ((len - len_img)/2) + len_img) if (msg.y >= (width/5) && msg.y <= (width/5) + 50) { *m_size = 0; break; } else if (msg.y >= (width/5)*2 && msg.y <= (width/5)*2 + 50) { *m_size = 1; break; } else if (msg.y >= (width/5)*3 && msg.y <= (width/5)*3 + 50) { *m_size = 2; break; } } Sleep(300); closegraph(); } void setSize(int row,int col,int n) { /* 设置游戏难度相关数据 */ Wnd_size.row = row; Wnd_size.col = col; Wnd_size.Length = col * side + 10; Wnd_size.Width = row * side + 10; switch (n) { case 0: Wnd_size.Lnum = 10; break; case 1: Wnd_size.Lnum = 40; break; case 2: Wnd_size.Lnum = 99; break; } cnt = (int *)malloc(sizeof(int)); *cnt = (Wnd_size.row - 1) * Wnd_size.col - Wnd_size.Lnum; save_bomb = (int *)malloc(sizeof(int)*2*Wnd_size.Lnum); } void cout_time() { /* 计时函数 */ char cout_c[4]; setbkmode(TRANSPARENT); // 设置文字背景透明 setcolor(RED); settextstyle(side / 2, 0, _T("宋体")); while(1) { Sleep(1000); // Sleep()函数是以毫秒计算,所以为了计时是一秒选用1000 g_time++; // cout计时变量 _itoa(g_time,cout_c,10); if (g_time < 10) outtextxy(Wnd_size.Length-side/2-3,side/4,cout_c[0]); else if (g_time < 100) { outtextxy(Wnd_size.Length-side/2-3,side/4,cout_c[1]); outtextxy(Wnd_size.Length-side,side/4,cout_c[0]); }else { outtextxy(Wnd_size.Length-side/2-3,side/4,cout_c[2]); outtextxy(Wnd_size.Length-side,side/4,cout_c[1]); outtextxy(Wnd_size.Length-3*side/2-3,side/4,cout_c[0]); } if (*cnt == 0) // 游戏通关或者失败都要停止 break; } } void game_win() { /* 处理游戏通关事件*/ if (*cnt == 0) { setbkmode(TRANSPARENT); // 设置文字背景透明 setcolor(RGB(237,24,35)); settextstyle(50, 0, _T("宋体")); outtextxy(Wnd_size.Length / 5,Wnd_size.Width / 4,_T("YOU ARE WIN!!")); while (1) { ; /************************************************** ** 处理后续事件,比如选择关卡,显示游戏主菜单等等 */ } } } void game_lose() { /* 处理游戏失败事件*/ setbkmode(TRANSPARENT); // 设置文字背景透明 setcolor(RGB(237,24,35)); settextstyle(side, 0, _T("宋体")); outtextxy(Wnd_size.Length / 7,Wnd_size.Width / 4,_T("YOU ARE LOSE!!")); // 输出数字 while (1) { ; /************************************************** ** 处理后续事件,比如选择关卡,显示游戏主菜单等等 */ } } void setFlag(int x,int y,Map **LandMap) { LandMap[x][y].flag = FLAG_OPEN; } void dealEmpty(int x,int y,Map **LandMap) { /* 处理点到空白方格的事件 */ int dir[8][2] = { {-1,-1},{ -1,0},{ -1,1},{0, 1},{1, 1},{1,0},{1,-1},{0,-1} }; int k = 0; putImg(img_flag[3],LandMap[x][y].x,LandMap[x][y].y); // 翻开这张牌 并设置状态为翻开 setFlag(x,y,LandMap); (*cnt)--; // 未翻开的格数减1 game_win(); for (k =0; k <8; k++) if (x+dir[k][0] >= 0 && x+dir[k][0] < Wnd_size.row - 1 && // 判断横坐标处于有效区域 y+dir[k][1] >= 0 && y+dir[k][1] < Wnd_size.col && // 判断纵坐标处于有效区域 LandMap[x+dir[k][0]][y+dir[k][1]].flag != FLAG_OPEN) // 判断此方格是否翻开 { if (LandMap[x+dir[k][0]][y+dir[k][1]].count > 0) // 数字 { putImg(img_flag[3],LandMap[x+dir[k][0]][y+dir[k][1]].x, LandMap[x+dir[k][0]][y+dir[k][1]].y); putNum(x+dir[k][0],y+dir[k][1],LandMap); // 数字的话输出数字并设置状态为 翻开 setFlag(x+dir[k][0],y+dir[k][1],LandMap); (*cnt)--; // 未翻开的格数减1 game_win(); } else if (LandMap[x+dir[k][0]][y+dir[k][1]].count == 0) // 空格 { /* putImg(img_flag[3],LandMap[x+dir[k][0]][y+dir[k][1]].x, LandMap[x+dir[k][0]][y+dir[k][1]].y); // 翻开这张牌 并设置状态为翻开 setFlag(x+dir[k][0],y+dir[k][1],LandMap); (*cnt)--; // 未翻开的格数减1 */ dealEmpty(x+dir[k][0],y+dir[k][1],LandMap); } } } void Bomb(int x,int y,Map **LandMap) { /* 输出爆炸效果 */ int j = 0; int b_time = 0; set_bombtime(&b_time); for (j = 0; j < 8; j++) { putImg(img_Bomb[j],LandMap[x][y].x,LandMap[x][y].y); Sleep(b_time); } } void LMsg(int x,int y,Map **LandMap) { /* 处理左键消息 */ if (LandMap[x][y].count == BOMB) { // 踩到雷,游戏结束 int i = 0,j = 0; int x1 = 0,y1 = 0; outtextxy(LandMap[x][y].x,LandMap[x][y].y,'L'); Bomb(x,y,LandMap); // 先输出当前的 putImg(img_Bomb[6],LandMap[x][y].x,LandMap[x][y].y); for(i = 0; i < Wnd_size.Lnum*2; i += 2) { x1 = save_bomb[i]; y1 = save_bomb[i+1]; if (x1 == x && y1 == y) continue; Bomb(x1,y1,LandMap); if (LandMap[x1][y1].flag % 3 == 1) // 红旗 putImg(img_Bomb[8],LandMap[x1][y1].x,LandMap[x1][y1].y); if (LandMap[x][y].flag % 3 == 2) // 问号 putImg(img_Bomb[9],LandMap[x1][y1].x,LandMap[x1][y1].y); } // 程序终止在操作不起作用,锁定界面,处理游戏结束事件 game_lose(); } else if (LandMap[x][y].count > 0) { // 点到数字翻开,并设置标志为翻开状态-1,通关所需的格数减 1 putImg(img_flag[3],LandMap[x][y].x,LandMap[x][y].y); putNum(x,y,LandMap); setFlag(x,y,LandMap); (*cnt)--; game_win(); // 处理通关事件 } else if (LandMap[x][y].count == 0) dealEmpty(x,y,LandMap); // 点到空白,向四周扩展 } void RMsg(int x,int y,Map **LandMap) { /* 处理右键消息 */ LandMap[x][y].flag++; // 标志加1 putImg(img_flag[LandMap[x][y].flag % 3],LandMap[x][y].x,LandMap[x][y].y); } void dealMouseMsg(Map **LandMap) { /* 处理鼠标消息:左键;右键 */ MOUSEMSG msg; int x = 0,y = 0; while (1) { msg = GetMouseMsg(); if (msg.y >= side) { x = msg.y / side - 1; // 得到实际坐标对应的数组下标 y = msg.x / side; if (LandMap[x][y].flag != FLAG_OPEN) // 所点区域处于没有翻开状态 { if (msg.uMsg == WM_LBUTTONDOWN && LandMap[x][y].flag % 3 == 0) // 鼠标左键按下 必须为初始状态才可以响应,其他状态都不响应 LMsg(x,y,LandMap); else if (msg.uMsg == WM_RBUTTONDOWN) // 鼠标右键按下 RMsg(x,y,LandMap); // cout_time(); } } } } void putImg(IMAGE img,int x,int y) { /* 在特定坐标输出一个方格的图片 */ putimage(x,y,&img); } void initGame(Map **LandMap) { /* 总的初始化函数 */ initgraph(Wnd_size.Length,Wnd_size.Width); initData(LandMap); initWindow(LandMap); GetLandmine(LandMap); } void initWindow(Map **LandMap) { /* 初始化游戏开始界面 */ int i = 0,j = 0; char num[3]; // 转换雷数为字符,储存位置 setbkcolor(RGB(12,112,213)); // 设置屏幕背景色 cleardevice(); for (i = 0; i < Wnd_size.row - 1; i ++) for ( j = 0; j < Wnd_size.col; j++) putImg(img_flag[0],LandMap[i][j].x,LandMap[i][j].y); setbkmode(TRANSPARENT); // 设置文字背景透明 setcolor(RED); settextstyle(side / 2, 0, _T("宋体")); _itoa(Wnd_size.Lnum,num,10); outtextxy(0,side/4,num[0]); outtextxy(side/2,side/4,num[1]); } void initData(Map **LandMap) { /* 初始化地图坐标,所有状态标志, */ int i = 0,j = 0; for (i = 0; i < Wnd_size.row - 1; i ++) // 初始化坐标和标志 上面预留一行 for ( j = 0; j < Wnd_size.col; j++) { LandMap[i][j].x = j*side; // 初始化横坐标 LandMap[i][j].y = (i+1)*side; // 初始化纵坐标 LandMap[i][j].count = 0; // 初始化数字为0 LandMap[i][j].flag = 0; // 初始化标志(0:初始 1:红旗 2:问号 -1:翻开) } loadimage(&img_flag[0],_T("./res/block.bmp"),side,side,false); // 初始 loadimage(&img_flag[1],_T("./res/flag.bmp"),side,side,false); // 红旗 loadimage(&img_flag[2],_T("./res/quote.bmp"),side,side,false); // 问号 loadimage(&img_flag[3],_T("./res/space.bmp"),side,side,false); // 翻开 loadimage(&img_Bomb[0],_T("./res/mine.bmp"),side,side,false); // 雷爆 loadimage(&img_Bomb[1],_T("./res/mine1.bmp"),side,side,false); loadimage(&img_Bomb[2],_T("./res/mine2.bmp"),side,side,false); loadimage(&img_Bomb[3],_T("./res/mine3.bmp"),side,side,false); loadimage(&img_Bomb[4],_T("./res/mine4.bmp"),side,side,false); loadimage(&img_Bomb[5],_T("./res/mine5.bmp"),side,side,false); loadimage(&img_Bomb[6],_T("./res/mine6.bmp"),side,side,false); loadimage(&img_Bomb[7],_T("./res/mine7.bmp"),side,side,false); loadimage(&img_Bomb[8],_T("./res/mine8.bmp"),side,side,false); loadimage(&img_Bomb[9],_T("./res/mine9.bmp"),side,side,false); } void GetLandmine(Map **LandMap) { int i = 0,j = 0; int x = 0,y = 0; srand((unsigned)time(NULL)); for (i = 0; i < Wnd_size.Lnum; i++) { x = rand() % (Wnd_size.row-1); y = rand() % Wnd_size.col; if (LandMap[x][y].count != BOMB) // 防止重复 { save_bomb[j++] = x; // 储存雷的位置 save_bomb[j++] = y; LandMap[x][y].count = BOMB; // 填雷 /**************************************** * 根据雷的位置填写周边数字,可以省去 * 记录雷位置的开销或者遍历地图的开销, * 记得判断周围方格是否为雷 ****************************************/ setNum(x,y,LandMap); } else i--; // 增加一次机会 } } void putNum(int i,int j,Map **LandMap) { /* 显示一个方格的数字 */ char count[2] = "0"; setbkmode(TRANSPARENT); // 设置文字背景透明 _itoa(LandMap[i][j].count,count,10); // 把数字转换成字符 setcolor(BLACK); outtextxy(LandMap[i][j].x+side/4,LandMap[i][j].y+side/4,count[0]); // 输出数字 } void setNum(int x,int y,Map **LandMap) { /* 设置每个雷周围的数字 */ int dir[8][2] = { {-1,-1},{ -1,0},{ -1,1},{0, 1},{1, 1},{1,0},{1,-1},{0,-1} }; int k = 0; for (k =0; k <8; k++) if (x+dir[k][0] >= 0 && x+dir[k][0] < Wnd_size.row-1 && // 判断横坐标处于有效区域 y+dir[k][1] >= 0 && y+dir[k][1] < Wnd_size.col && // 判断纵坐标处于有效区域 LandMap[x+dir[k][0]][y+dir[k][1]].count != BOMB) // 判断此方格没有雷 LandMap[x+dir[k][0]][y+dir[k][1]].count++; } void main(void) { static const int row[3] = {10,17,17}; static const int col[3] = {9,16,30}; int m_size = -1; int i = 0; Map **LandMap = NULL; select_deg(&m_size); setSize(row[m_size],col[m_size],m_size); LandMap = (Map**)malloc(sizeof(Map*)*(Wnd_size.row-1)); for (i = 0; i < Wnd_size.row - 1; i++) LandMap[i] = (Map*)malloc(sizeof(Map)*Wnd_size.col); initGame(LandMap); dealMouseMsg(LandMap); _getch(); closegraph(); free(*LandMap); free(&LandMap); }
[ 本帖最后由 Fisher~ 于 2013-7-16 14:51 编辑 ]