【c语言】迷宫游戏

简介: 【c语言】迷宫游戏

之前想写的迷宫游戏今天终于大功告成,解决了随机生成迷宫地图的问题,使用的是深度优先算法递归版本,之前的迷宫找通路问题用的是深度优先算法的非递归实现.之前写过推箱子,推箱子用到了人物的移动,以及碰到墙就不会走,我们可以稍微变一下就变成了迷宫游戏

1.游戏演示

迷宫演示

2.游戏整体思路

1.迷宫的生成(难点)

2.人物的移动

3.走到出口的判定

4.使用图形库添加人物图片,墙,路的图片

3.预备准备

将每个状态用数字表示,则创建一个枚举类型,以及定义地图的高和宽

#define Height 9
#define Width 9
enum  Mine
{
 Road,
 Wall, 
 Start,
 End, 
 Player };

由枚举类型可知,Road(路)为0,Wall(墙)为1,Start(起点)为2,End(终点)为3,Player(玩家)为4,初始化地图大小为9*9;

int map[Height+2][Width+2];
int flag = 0;

定义一个二维数组大小为11*11;

4.迷宫的初始化

迷宫的创建

void create_map(int x, int y)
{
  int c[4][2] = { 0,1,1,0,0,-1,-1,0 };
  int i, j, t;
  for (i = 0; i < 4; i++)
  {
    j = rand() % 4;
    t = c[i][0]; c[i][0] = c[j][0]; c[j][0] = t;
    t = c[i][1]; c[i][1] = c[j][1]; c[j][1] = t;
  }
  map[x][y] = Road;
  for (int i = 0; i < 4; i++)
  {
    if (map[x + 2 * c[i][0]][y + 2 * c[i][1]] == Wall)
    {
      map[x + c[i][0]][y + c[i][1]] = Road;
      create_map(x + 2 * c[i][0], y + 2 * c[i][1]);
    }
  }
}
void init()
{
  for (int i = 0; i <= Height + 1; i++)
  {
    for (int j = 0; j <= Width + 1; j++)
    {
      if (i == 0 || i == Height + 1 || j == 0 || j == Width + 1)
        map[i][j] = Road;
      else
        map[i][j] = Wall;
    }
  }
  create_map(2 * (rand() % (Height / 2) + 1), 2 * (rand() % (Width / 2) + 1));
  for (int i = 0; i <= Height + 1; i++)
  {
    map[i][0] = Wall;
    map[i][Width + 1] = Wall;
  }
  for (int j = 0; j <= Height + 1; j++)
  {
    map[0][j] = Wall;
    map[Height + 1][j] = Wall;
  }
  map[2][1] = Start+Player;
  map[Height - 1][Width] = End;
}

5.键盘控制人物移动

这里推箱子那节有讲,稍微改变一下即可

void keyevent()
{
  int i = 0; int j = 0;
  for (i = 1; i <= Height; i++)
  {
    for (j = 1; j <= Width; j++)
    {
      if (map[i][j] == Player|| map[i][j] == Player +Start|| map[i][j] == Player +End)//,遍历二维数组,如果二维数组某个元素为4,6,7的话直接跳出两个循环,
      {
        goto end;
      }
    }
  }
end:;//获取当前人物坐标
  char ch = _getch();
  //printf("%d    %c", ch, ch);//w 119 a 97 s 115  d 100
  switch (ch)
  {
  case 119:
  case 'w ':
  case 'W':
    if (map[i - 1][j] == Road|| map[i - 1][j]== End|| map[i - 1][j] ==Start)//当人物当前位置上面是路或者出口或者入口都可以走
    {
      map[i - 1][j] += Player;//移动后的位置+4,表示玩家出现在此坐标
      map[i][j] -= Player;//起始位置-4,表示玩家消失在此坐标
    }
    break;
  case 97:
  case 'a ':
  case'A':
    if (map[i][j - 1]== Road || map[i][j - 1] == End || map[i][j - 1] ==Start)
    {
      map[i][j - 1] += Player;
      map[i][j] -= Player;
    }
    break;
  case 115:
  case 's ':
  case'S':
    if (map[i + 1][j] == Road || map[i + 1][j] == End|| map[i + 1][j] == Start)
    {
      map[i + 1][j] += Player;
      map[i][j] -= Player;
    }
    break;
  case 100:
  case 'd ':
  case'D':
    if (map[i][j + 1] == Road || map[i][j + 1] == End|| map[i][j + 1]==Start)
    {
      map[i][j + 1] += Player;
      map[i][j] -= Player;
    }
    break;
  }
  for (i = 1; i <= Height; i++)
  {
    for (j = 1; j <= Width; j++)
    {
      if (map[i][j] == Player || map[i][j] == Player + Start || map[i][j] == Player + End)
      {
        goto end1;
      }
    }
  }
end1:;//移动后找到玩家当前位置
}

6.打印地图函数

void gamedraw()
{
  for (int i = 1; i <=Height; i++)//遍历二维数组
  {
    for (int j = 1; j <=Width; j++)
    {
        switch (map[i][j])
        {case Road:
          printf("  ");  //路        //一个中文字符相当于二个英文字符
          break;
        case Wall:
          printf("■");//墙
          break;
        case Start:
          printf("入");//入口
          break;
        case End:
          printf("出");//出口
          break;
        case Player:
          printf("♂");//玩家
          break;
        case Player+ Start:
          printf("♂");//玩家在起点
          break;
        case Player +End://玩家在终点
          printf("♂");
          break;
                }
    }
printf("\n");
  }
}

7.判断到出口函数

void iswin()
{
  if (map[Height - 1][Width]==Player+End)
  {
    flag = 1;
  }
}

如果终点的坐标map[Height - 1][Width]7,说明玩家到终点,将flag置为1;
然后 在主函数中加个判断语句,如果flag
1,退出 程序

8.主函数

int main()
{  
  srand((unsigned)time(NULL));
  init();//初始化地图
  //initgraph(Height * 40, Width * 40);
  //bgm();
  //loadimg();
  while (1)
  {
    gamedraw();//画地图函数
    keyevent();//获取方向函数
    iswin();//判断是否到终点
    if (flag == 1)
    {
      exit(-1);//到了退出程序
    }
    system("cls");//清屏函数,如果不知道为什么加这一步的话,你可以先不加试试
  }
  getchar();
  return 0;
}

9.不加图形库的话的头文件

#include<stdio.h>
#include<time.h>//time的头文件
#include <stdlib.h>//srand的头文件
#include <conio.h>//-getch()头文件
#include <windows.h>//清屏函数头文件

10.不加图形库游戏源码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#define Height 9
#define Width 9
enum  Mine
{
 Road,
 Wall, 
 Start,
 End, 
 Player 
};
int map[Height+2][Width+2];
int flag = 0;
void iswin()
{
  if (map[Height - 1][Width]==Player+End)
  {
    flag = 1;
  }
}
void gamedraw()
{
  for (int i = 1; i <=Height; i++)
  {
    for (int j = 1; j <=Width; j++)
    {
        switch (map[i][j])
        {case Road:
          printf("  ");          //一个中文字符相当于二个英文字符
          break;
        case Wall:
          printf("■");
          break;
        case Start:
          printf("入");
          break;
        case End:
          printf("出");
          break;
        case Player:
          printf("♂");
          break;
        case Player+ Start:
          printf("♂");
          break;
        case Player +End:
          printf("♂");
          break;
                }
    }
printf("\n");
  }
}
void keyevent()
{
  int i = 0; int j = 0;
  for (i = 1; i <= Height; i++)
  {
    for (j = 1; j <= Width; j++)
    {
      if (map[i][j] == Player|| map[i][j] == Player +Start|| map[i][j] == Player +End)
      {
        goto end;
      }
    }
  }
end:;
  char ch = _getch();
  //printf("%d    %c", ch, ch);//w 119 a 97 s 115  d 100
  switch (ch)
  {
  case 119:
  case 'w ':
  case 'W':
    if (map[i - 1][j] == Road|| map[i - 1][j]== End|| map[i - 1][j] ==Start)
    {
      map[i - 1][j] += Player;
      map[i][j] -= Player;
    }
    break;
  case 97:
  case 'a ':
  case'A':
    if (map[i][j - 1]== Road || map[i][j - 1] == End || map[i][j - 1] ==Start)
    {
      map[i][j - 1] += Player;
      map[i][j] -= Player;
    }
    break;
  case 115:
  case 's ':
  case'S':
    if (map[i + 1][j] == Road || map[i + 1][j] == End|| map[i + 1][j] == Start)
    {
      map[i + 1][j] += Player;
      map[i][j] -= Player;
    }
    break;
  case 100:
  case 'd ':
  case'D':
    if (map[i][j + 1] == Road || map[i][j + 1] == End|| map[i][j + 1]==Start)
    {
      map[i][j + 1] += Player;
      map[i][j] -= Player;
    }
    break;
  }
  for (i = 1; i <= Height; i++)
  {
    for (j = 1; j <= Width; j++)
    {
      if (map[i][j] == Player || map[i][j] == Player + Start || map[i][j] == Player + End)
      {
        goto end1;
      }
    }
  }
end1:;
}
void create_map(int x, int y)
{//8,8
  int c[4][2] = { 0,1,1,0,0,-1,-1,0 };
  int i, j, t;
  for (i = 0; i < 4; i++)
  {
    j = rand() % 4;
    t = c[i][0]; c[i][0] = c[j][0]; c[j][0] = t;
    t = c[i][1]; c[i][1] = c[j][1]; c[j][1] = t;
  }
  map[x][y] = Road;
  for (int i = 0; i < 4; i++)
  {
    if (map[x + 2 * c[i][0]][y + 2 * c[i][1]] == Wall)
    {
      map[x + c[i][0]][y + c[i][1]] = Road;
      create_map(x + 2 * c[i][0], y + 2 * c[i][1]);
    }
  }
}
void init()
{
  for (int i = 0; i <= Height + 1; i++)
  {
    for (int j = 0; j <= Width + 1; j++)
    {
      if (i == 0 || i == Height + 1 || j == 0 || j == Width + 1)
        map[i][j] = Road;
      else
        map[i][j] = Wall;
    }
  }
  create_map(2 * (rand() % (Height / 2) + 1), 2 * (rand() % (Width / 2) + 1));
  for (int i = 0; i <= Height + 1; i++)
  {
    map[i][0] = Wall;
    map[i][Width + 1] = Wall;
  }
  for (int j = 0; j <= Height + 1; j++)
  {
    map[0][j] = Wall;
    map[Height + 1][j] = Wall;
  }
  map[2][1] = Start+Player;
  map[Height - 1][Width] = End;
}
int main()
{  
  srand((unsigned)time(NULL));
  init();
  //initgraph(Height * 40, Width * 40);
  //bgm();
  //loadimg();
  while (1)
  {
    gamedraw();
    keyevent();
    iswin();
    if (flag == 1)
    {
      exit(-1);
    }
    system("cls");
  }
  getchar();
  return 0;
}

11.加图形库版本

12.头文件改变

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <graphics.h>//图形库头文件
#include<mmsystem.h>//包含多媒体设备接口头文件
#pragma comment(lib,"winmm.lib")//加载静态库

13.加载图片

这里将游戏的素材,墙,玩家,路,起点,终点的图片放到.cpp的统一目录下,这里可以去看一下我写的推箱子.

void loadimg()
{
  for (int i = 0; i < 5; i++)
  {
    char file[20] = "";
    sprintf(file, "./image/%d.png", i);
    loadimage(ima_all + i, file, 40, 40);
  }
}

14.gamedraw函数修改

因为不会在控制台玩游戏,所以要修改这个函数,这里也可以借鉴推箱子那节的

void gamedraw()
{
  for (int i =1; i <= Height; i++)
  {
    for (int j = 1; j <=Width; j++)
    {
      int x = (j-1)* 40;
      int y = (i-1) * 40;
      switch (map[i][j])
      {
      case Road:
        putimage(x, y, ima_all);         //一个中文字符相当于二个英文字符
        break;
      case Wall:
        putimage(x, y, ima_all + 1);
        break;
      case Player:
        putimage(x, y, ima_all+4);
        break;
      case Player +Start:
        putimage(x, y, ima_all+4);
        break;
      case Start:
        putimage(x, y, ima_all+2);
        break;
      case End:
        putimage(x, y, ima_all+3);
        break;
      case Player+End:
        putimage(x, y, ima_all+4);
        break;
      }
    }
  }
}

具体说一下为什么这里的int x = (j-1)* 40;int y = (i-1) * 40;x,y表示要贴的图片的左上角贴在游戏的哪个位置,因为二维数组是将1,1的坐标贴在界面的左上角,界面的左上角坐标就是0,0.x表示行,y表示列.

15.主函数的修改

int main()
{  
  srand((unsigned)time(NULL));
  init();
  initgraph(Height * 40, Width * 40);
  //bgm();
  loadimg();
  while (1)
  {
    gamedraw();
    keyevent();
    iswin();
    if (flag == 1)
    {
      exit(-1);
    }
    system("cls");
  }
  getchar();
  return 0;
}

16.加图形库的程序源码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <graphics.h>
//#include<mmsystem.h>//包含多媒体设备接口头文件
//#pragma comment(lib,"winmm.lib")//加载静态库
#define Height 9 //如果要修改难度可以修改这里,必须是奇数
#define Width 9  //如果要修改难度可以修改这里,必须是奇数
enum  Mine
{
 Road,
 Wall, 
 Start,
 End, 
 Player 
};
int map[Height+2][Width+2];
int flag = 0;
IMAGE  ima_all[5];
//void bgm()
//{    //打开音乐
//  mciSendString("open ./music.MP3", 0, 0, 0);//后面参数不用管
  //播放音乐
//  mciSendString("play ./music.MP3", 0, 0, 0);//后面参数不用管
//}
void loadimg()
{
  for (int i = 0; i < 5; i++)
  {
    char file[20] = "";
    sprintf(file, "./image/%d.png", i);
    loadimage(ima_all + i, file, 40, 40);//修改难度时将图片大小放成10,地图才能放得下
  }
}
void iswin()
{
  if (map[Height - 1][Width]==Player+End)
  {
    flag = 1;
  }
}
void gamedraw()
{
  for (int i =1; i <= Height; i++)
  {
    for (int j = 1; j <=Width; j++)
    {
      int x = (j-1)* 40;//修改难度时将图片大小放成10,地图才能放得下*40改为*10
      int y = (i-1) * 40;//修改难度时将图片大小放成10,地图才能放得下*40改为*10
      switch (map[i][j])
      {
      case Road:
        putimage(x, y, ima_all);         
        break;
      case Wall:
        putimage(x, y, ima_all + 1);
        break;
      case Player:
        putimage(x, y, ima_all+4);
        break;
      case Player +Start:
        putimage(x, y, ima_all+4);
        break;
      case Start:
        putimage(x, y, ima_all+2);
        break;
      case End:
        putimage(x, y, ima_all+3);
        break;
      case Player+End:
        putimage(x, y, ima_all+4);
        break;
      }
    }
  }
}
void keyevent()
{
  int i = 0; int j = 0;
  for (i = 1; i <= Height; i++)
  {
    for (j = 1; j <= Width; j++)
    {
      if (map[i][j] == Player|| map[i][j] == Player +Start|| map[i][j] == Player +End)
      {
        goto end;
      }
    }
  }
end:;
  char ch = _getch();
  //printf("%d    %c", ch, ch);//w 119 a 97 s 115  d 100
  switch (ch)
  {
  case 119:
  case 'w ':
  case 'W':
    if (map[i - 1][j] == Road|| map[i - 1][j]== End|| map[i - 1][j] ==Start)
    {
      map[i - 1][j] += Player;
      map[i][j] -= Player;
    }
    break;
  case 97:
  case 'a ':
  case'A':
    if (map[i][j - 1]== Road || map[i][j - 1] == End || map[i][j - 1] ==Start)
    {
      map[i][j - 1] += Player;
      map[i][j] -= Player;
    }
    break;
  case 115:
  case 's ':
  case'S':
    if (map[i + 1][j] == Road || map[i + 1][j] == End|| map[i + 1][j] == Start)
    {
      map[i + 1][j] += Player;
      map[i][j] -= Player;
    }
    break;
  case 100:
  case 'd ':
  case'D':
    if (map[i][j + 1] == Road || map[i][j + 1] == End|| map[i][j + 1]==Start)
    {
      map[i][j + 1] += Player;
      map[i][j] -= Player;
    }
    break;
  }
  for (i = 1; i <= Height; i++)
  {
    for (j = 1; j <= Width; j++)
    {
      if (map[i][j] == Player || map[i][j] == Player + Start || map[i][j] == Player + End)
      {
        goto end1;
      }
    }
  }
end1:;
}
void create_map(int x, int y)
{//8,8
  int c[4][2] = { 0,1,1,0,0,-1,-1,0 };
  int i, j, t;
  for (i = 0; i < 4; i++)
  {
    j = rand() % 4;
    t = c[i][0]; c[i][0] = c[j][0]; c[j][0] = t;
    t = c[i][1]; c[i][1] = c[j][1]; c[j][1] = t;
  }
  map[x][y] = Road;
  for (int i = 0; i < 4; i++)
  {
    if (map[x + 2 * c[i][0]][y + 2 * c[i][1]] == Wall)
    {
      map[x + c[i][0]][y + c[i][1]] = Road;
      create_map(x + 2 * c[i][0], y + 2 * c[i][1]);
    }
  }
}
void init()
{
  for (int i = 0; i <= Height + 1; i++)
  {
    for (int j = 0; j <= Width + 1; j++)
    {
      if (i == 0 || i == Height + 1 || j == 0 || j == Width + 1)
        map[i][j] = Road;
      else
        map[i][j] = Wall;
    }
  }
  create_map(2 * (rand() % (Height / 2) + 1), 2 * (rand() % (Width / 2) + 1));
  for (int i = 0; i <= Height + 1; i++)
  {
    map[i][0] = Wall;
    map[i][Width + 1] = Wall;
  }
  for (int j = 0; j <= Height + 1; j++)
  {
    map[0][j] = Wall;
    map[Height + 1][j] = Wall;
  }
  map[2][1] = Start+Player;
  map[Height - 1][Width] = End;
}
int main()
{  
  srand((unsigned)time(NULL));
  init();
  initgraph(Height * 40, Width * 40);
  //bgm();这个音乐也不加了
  loadimg();
  while (1)
  {
    gamedraw();
    keyevent();
    iswin();
    if (flag == 1)
    {
      exit(-1);
    }
    //system("cls");这里不需要,因为用不到控制台
  }
  getchar();
  return 0;
}

注意不用图形库的铁铁们可以直接复制10.不加图形库的程序源码可以直接运行的

这里给大家推荐一个电影心迷宫巨巨巨巨巨好看,直接点题,真有我小汁的

目录
相关文章
|
15小时前
|
算法 C语言 C++
【C语言实战项目】三子棋游戏
【C语言实战项目】三子棋游戏
33 1
|
15小时前
|
程序员 C语言
【C语言实战项目】猜数字游戏
【C语言实战项目】猜数字游戏
30 0
【C语言实战项目】猜数字游戏
|
15小时前
|
C语言
关于使用C语言编写一个简单的猜数字游戏
关于使用C语言编写一个简单的猜数字游戏
23 0
|
15小时前
|
算法 C语言
【C语言】三子棋游戏实现代码
【C语言】三子棋游戏实现代码
【C语言】三子棋游戏实现代码
|
15小时前
|
C语言
C语言-------扫雷游戏的代码实现
C语言-------扫雷游戏的代码实现
28 0
|
15小时前
|
算法 C语言 C++
【C语言-扫雷游戏全功能详解】
【C语言-扫雷游戏全功能详解】
39 1
|
15小时前
|
C语言
C语言之详解数组【附三子棋和扫雷游戏实战】(二)
C语言之详解数组【附三子棋和扫雷游戏实战】(二)
|
15小时前
|
C语言
C语言实战演练之游戏框架
C语言实战演练之游戏框架
|
15小时前
|
存储 算法 C语言
【C 言专栏】用 C 语言开发游戏的实践
【5月更文挑战第5天】本文探讨了使用C语言开发游戏的实践,包括选择适合的游戏类型(如贪吃蛇、俄罗斯方块),设计游戏框架、图形界面和逻辑,以及音效添加。文章还强调了性能优化、测试调试、跨平台挑战及未来发展趋势。对于热衷于C语言的开发者,这是一次挑战与乐趣并存的探索之旅。
【C 言专栏】用 C 语言开发游戏的实践
|
15小时前
|
C语言
以c语言为基础实现的简易扫雷游戏(游戏代码附在文章最后,如有需要请自取)
以c语言为基础实现的简易扫雷游戏(游戏代码附在文章最后,如有需要请自取)
46 1