c语言小游戏--扫雷

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: c语言小游戏--扫雷

 (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)

今天我们来尝试用easyx图形库实现c语言的扫雷小游戏,相关图片我已经在文中给出

首先就是引用相关头文件

#include<stdio.h>
#include<graphics.h>//图形库文件,便于生成新的窗口
#include<stdlib.h>
#include<time.h>//用于生成随机函数

接着绘制地图,我们定义的扫雷为十行十列, 规定-1为雷,0表示为空白,1,2,3就是对应的数字

#define row 10//行
#define col 10//列
int map[row][col] = { 0 };//定义地图
void drawmap()//绘制地图
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            printf(" %2d ", map[i][j]); //2d表示每个字符占两位,使-1与0等齐
        }
        printf("\n");
    }
}

然后就是埋雷的,因为是随机埋雷,所以需要用到随机函数rand();因此我们先在主函数中创建一个随机函数种子

srand((unsigned int)time(0));//生成随机数种子

然后就是用rand随机生成雷(-1),而且还要防止雷在同一个地方重复出现

//给数组随机埋雷,雷用-1表示,只要10个雷
    for (int i = 0; i < 10;)
    {
        //雷的行列
        int a = rand()%row;
        int b = rand()%col;
        if (map[a][b] == 0)//防止重复
        {
            map[a][b] = -1;
            i++;//只有当-1赋值成功以后,才去遍历下一个雷
        }
    }

有了雷以后,就要对雷周围的数据进行修改,每个雷周围的九宫格都要在0的基础上加一 ,越界问题是扫雷的一个细节,要确保数据在界面以内

//雷周围的九宫格数字都加1,(雷自己除外)
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (map[i][j] == -1)
            {
                for (int a = i - 1; a <= i + 1; a++)
                {
                    for (int b = j - 1; b <= j + 1; b++)
                    {
                        if ((a>=0&&a<row&&b>=0&&b<col)&&map[a][b] != -1)//防止越界且不能为雷
                        {
                            map[a][b]++;
                        }
                    }
                }
            }
        }
    }

基本数据已经搭建好了,接下来就是图形的绘制,我们可以在主函数上面先定义一个图形库窗口,且定义每一个图片大小为40

#define imagesize 40//定义图片大小
initgraph(row * imagesize, col * imagesize); //创建窗口

绘制图片分为三步:图片变量定义--图片加载--图片输出(图片如何输出问题在我之前的博客中有提及http://t.csdn.cn/PcJiP

首先定义图片

IMAGE img[12];//定义图形

 

接着就是加载图片,这里为了方便,我运用了sprintf

void load()//加载图片
{
    for (int i = 0; i < 12; i++)
    {
        //字符串格式化
        char imagename[50];
        sprintf(imagename, "./图片库/%d.jpg", i);
        loadimage(img + i,imagename, imagesize, imagesize);
    }
}

如果大家不了解sprintf,就可以使用常规方法,将图片逐一加载出来

void load()
{
    loadimage(img + 0, "./图片库/0.jpg", imagesize, imagesize);
    loadimage(img + 1, "./图片库/1.jpg", imagesize, imagesize);
    loadimage(img + 2, "./图片库/2.jpg", imagesize, imagesize);
    loadimage(img + 3, "./图片库/3.jpg", imagesize, imagesize);
    loadimage(img + 4, "./图片库/4.jpg", imagesize, imagesize);
    loadimage(img + 5, "./图片库/5.jpg", imagesize, imagesize);
    loadimage(img + 6, "./图片库/6.jpg", imagesize, imagesize);
    loadimage(img + 7, "./图片库/7.jpg", imagesize, imagesize);
    loadimage(img + 8, "./图片库/8.jpg", imagesize, imagesize);
    loadimage(img + 9, "./图片库/9.jpg", imagesize, imagesize);
    loadimage(img + 10, "./图片库/10.jpg", imagesize, imagesize);
    loadimage(img + 11, "./图片库/11.jpg", imagesize, imagesize);
}

接下来就是输出图片

for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (map[i][j] >= 0 && map[i][j] <= 8)
            {
                putimage(j * imagesize, i * imagesize, img + map[i][j]);
            }
            else if(map[i][j]==-1)//贴雷
            {
                putimage(j * imagesize, i * imagesize, img + 9);
            }
        }
    }

这样我们的数据原型就做好了,接下来就是对其进行加密,也就是将雷和数字遮起来,我们这里的思路就是将每一个数字的结果加上date,然后使加上date后的数字对应改为第10号图形

#define date 20//定义date的值
//加密数据
    for (int m = 0; m < row; m++)
    {
        for (int n = 0; n < col; n++)
        {
            map[m][n] += date;
        }
    }

然后就是对新的数字定义图形

//加密
if (map[i][j] >= -1 + date && map[i][j] <= 8 + date)
{
putimage(j * imagesize, i * imagesize, img + 10);
}

然后我们就需要通过鼠标点击对数据进行修改,我们定义鼠标每次点击后原数据减去date (对于鼠标如何操作,在我之前的博客中有提及http://t.csdn.cn/B7pwW

if (MouseHit())//判断是否有鼠标操作
    {
        MOUSEMSG msg = GetMouseMsg();
        //鼠标变量msg里面有x,y,但是没有行和列,需要自己求
        int r = msg.y / imagesize;
        int c = msg.x / imagesize;
        //鼠标左键点击打开对应格子,让数组元素-date
        if (msg.uMsg == WM_LBUTTONDOWN)
        {
            //避免越界
            if (map[r][c] >= -1 + date && map[r][c] <=8 + date)
            {
                map[r][c] -= date;
                gameover(r,c);
                draw();//每次鼠标点完以后重新贴图
            }
        }
      }

插旗子也是如此

//右键按下插旗
        if (msg.uMsg == WM_RBUTTONDOWN)
        {
            if (map[r][c] >= -1 + date && map[r][c] <= 8 + date)//标记
            {
                map[r][c] += date;
                draw();//每次鼠标点完以后重新贴图
            }
            else if (map[r][c] > 8 + date)//再次点击取消标记
            {
                map[r][c] -= date;
                draw();
            }

然后就是输出旗子图片

else if(map[i][j]>8+date)
            {
                putimage(j * imagesize, i * imagesize, img + 11);
            }

最后就是游戏结束的相关数据

void gameover(int x, int y)
{
    //如果点到雷,就结束
    if (map[x][y] == -1)
    {
        //打开所有的雷
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                //没标记的要打开
                if (map[i][j] == -1 + date)
                {
                    map[i][j] -= date;
                }
                //被标记的也要打开
                else if (map[i][j] == -1 + date + date)
                {
                    map[i][j] -= 2 * date;
                }
            }
        }
        draw();
        //弹窗
        int ret = MessageBox(GetHWnd(), "游戏结束", "提示", MB_OK);
        if (ret == IDOK)
        {
            exit(0);//退出
        }
    }
}

将其汇总到主函数中即可

int main()
{
    srand((unsigned int)time(0));//生成随机数种子
    initgraph(row * imagesize, col * imagesize);
    load();
    initmap();
    draw();
    drawmap();
    while (1)
    {
        mouse();
    }
    closegraph();
    return 0;
}

总体代码就是这样,如果大家发现bug或者有更好的方法 ,欢迎大家一起来讨论呀,一起加油

#define _CRT_SECURE_NO_WARNINGS 1//忽略安全检测
#include<stdio.h>
#include<graphics.h>
#include<stdlib.h>
#include<time.h>
#define row 10//行
#define col 10//列
#define imagesize 40//定义图片大小
int map[row][col] = { 0 };//定义地图
#define date 20
IMAGE img[12];//定义图形
void drawmap()//绘制地图
{
  for (int i = 0; i < row; i++)
  {
    for (int j = 0; j < col; j++)
    {
      printf(" %2d ", map[i][j]); //2d表示每个字符占两位
    }
    printf("\n");
  }
}
//初始化数据
void initmap()
{
  //给数组随机埋雷,雷用-1表示,只要10个雷
  for (int i = 0; i < 10;)
  {
    //雷的行列
    int a = rand()%row;
    int b = rand()%col;
    if (map[a][b] == 0)//防止重复
    {
      map[a][b] = -1;
      i++;//只有当-1赋值成功以后,才去遍历下一个雷
    }
  }
  //雷周围的九宫格数字都加1,(雷自己除外)
  for (int i = 0; i < row; i++)
  {
    for (int j = 0; j < col; j++)
    {
      if (map[i][j] == -1)
      {
        for (int a = i - 1; a <= i + 1; a++)
        {
          for (int b = j - 1; b <= j + 1; b++)
          {
            if ((a>=0&&a<row&&b>=0&&b<col)&&map[a][b] != -1)//防止越界且不能为雷
            {
              map[a][b]++;
            }
          }
        }
      }
    }
  }
  //加密数据
  for (int m = 0; m < row; m++)
  {
    for (int n = 0; n < col; n++)
    {
      map[m][n] += date;
    }
  }
}
//void load()//加载图片
//{
//  for (int i = 0; i < 12; i++)
//  {
//    //字符串格式化
//    char imagename[50];
//    sprintf(imagename, "./图片库/%d.jpg", i);
//    loadimage(img + i,imagename, imagesize, imagesize);
//  }
//}
void load()
{
  loadimage(img + 0, "./图片库/0.jpg", imagesize, imagesize);
  loadimage(img + 1, "./图片库/1.jpg", imagesize, imagesize);
  loadimage(img + 2, "./图片库/2.jpg", imagesize, imagesize);
  loadimage(img + 3, "./图片库/3.jpg", imagesize, imagesize);
  loadimage(img + 4, "./图片库/4.jpg", imagesize, imagesize);
  loadimage(img + 5, "./图片库/5.jpg", imagesize, imagesize);
  loadimage(img + 6, "./图片库/6.jpg", imagesize, imagesize);
  loadimage(img + 7, "./图片库/7.jpg", imagesize, imagesize);
  loadimage(img + 8, "./图片库/8.jpg", imagesize, imagesize);
  loadimage(img + 9, "./图片库/9.jpg", imagesize, imagesize);
  loadimage(img + 10, "./图片库/10.jpg", imagesize, imagesize);
  loadimage(img + 11, "./图片库/11.jpg", imagesize, imagesize);
}
//输出图片
void draw()
{
  for (int i = 0; i < row; i++)
  {
    for (int j = 0; j < col; j++)
    {
      if (map[i][j] >= 0 && map[i][j] <= 8)
      {
        putimage(j * imagesize, i * imagesize, img + map[i][j]);
      }
      else if(map[i][j]==-1)//贴雷
      {
        putimage(j * imagesize, i * imagesize, img + 9);
      }
      //加密
      else if (map[i][j] >= -1 + date && map[i][j] <= 8 + date)
      {
        putimage(j * imagesize, i * imagesize, img + 10);
      }
      //插旗子
      else if(map[i][j]>8+date)
      {
        putimage(j * imagesize, i * imagesize, img + 11);
      }
    }
  }
}
//结束游戏
void gameover(int x, int y)
{
  //如果点到雷,就结束
  if (map[x][y] == -1)
  {
    //打开所有的雷
    for (int i = 0; i < row; i++)
    {
      for (int j = 0; j < col; j++)
      {
        //没标记的要打开
        if (map[i][j] == -1 + date)
        {
          map[i][j] -= date;
        }
        //被标记的也要打开
        else if (map[i][j] == -1 + date + date)
        {
          map[i][j] -= 2 * date;
        }
      }
    }
    draw();
    //弹窗
    int ret = MessageBox(GetHWnd(), "游戏结束", "提示", MB_OK);
    if (ret == IDOK)
    {
      exit(0);//退出
    }
  }
}
//鼠标操作
void mouse()
{
  if (MouseHit())//判断是否有鼠标操作
  {
    MOUSEMSG msg = GetMouseMsg();
    //鼠标变量msg里面有x,y,但是没有行和列,需要自己求
    int r = msg.y / imagesize;
    int c = msg.x / imagesize;
    //鼠标左键点击打开对应格子,让数组元素-date
    if (msg.uMsg == WM_LBUTTONDOWN)
    {
      //避免越界
      if (map[r][c] >= -1 + date && map[r][c] <=8 + date)
      {
        map[r][c] -= date;
        gameover(r,c);
        draw();//每次鼠标点完以后重新贴图
      }
    }
    //右键按下插旗
    if (msg.uMsg == WM_RBUTTONDOWN)
    {
      if (map[r][c] >= -1 + date && map[r][c] <= 8 + date)//标记
      {
        map[r][c] += date;
        draw();//每次鼠标点完以后重新贴图
      }
      else if (map[r][c] > 8 + date)//取消标记
      {
        map[r][c] -= date;
        draw();
      }
    }
  }
}
int main()
{
  srand((unsigned int)time(0));//生成随机数种子
  initgraph(row * imagesize, col * imagesize);
    load();
  initmap();
  draw();
  drawmap();
  while (1)
  {
    mouse();
  }
  closegraph();
  return 0;
}
相关文章
|
10天前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
46 0
|
10天前
|
C语言 C++
【C语言】编写“猜数字“小游戏
【C语言】编写“猜数字“小游戏
|
1月前
|
定位技术 API C语言
C语言——实现贪吃蛇小游戏
本文介绍了一个基于Windows控制台的贪吃蛇游戏的实现方法。首先,需调整控制台界面以便更好地显示游戏。接着,文章详细描述了如何使用Win32 API函数如`COORD`、`GetStdHandle`、`GetConsoleCursorInfo`等来控制控制台的光标和窗口属性。此外,还介绍了如何利用`GetAsyncKeyState`函数实现键盘监听功能。文中还涉及了`&lt;locale.h&gt;`库的使用,以支持本地化字符显示。
47 1
C语言——实现贪吃蛇小游戏
|
1月前
|
存储 安全 算法
C 语言——实现扫雷小游戏
本文介绍了使用二维数组创建棋盘并实现扫雷游戏的方法。首先,通过初始化数组创建一个9x9的棋盘,并添加行列标识以便操作。接着,利用随机数在棋盘上布置雷。最后,通过判断玩家输入的坐标来实现扫雷功能,包括显示雷的数量和处理游戏胜利或失败的情况。文中提供了完整的代码实现。
39 1
C 语言——实现扫雷小游戏
|
15天前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
18天前
|
C语言 开发者
C语言实现猜数字小游戏(详细教程)
C语言实现猜数字小游戏(详细教程)
|
18天前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
11天前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
23 0
|
13天前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
31 0
|
15天前
|
C语言
【C语言】实践:贪吃蛇小游戏(附源码)(三)
【C语言】实践:贪吃蛇小游戏(附源码)