花费三天时间写了一个扫雷游戏大家指导指导
目前实现了有初中高级,有红旗问号标志,但是没有时间显示,因为时间函数还没写好图片是偷懒了盗用别人写的代码里的图片
这里是源代码和图片文件
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 编辑 ]





表示不会用~~~

