• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C++实现随机生成迷宫地牢

C++实现随机生成迷宫地牢

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++迷宫游戏代码,c++迷宫问题,c++迷宫,c++迷宫程序,c++实现二叉树等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

可以用这个地图核心做成一个无限迷宫类的游戏

main.cpp

// Author: FreeKnight 2014-09-02
#include "stdafx.h"
#include <iostream>
#include <string>
#include <random>
#include <cassert>
 
/*
简单逻辑流程描述:
将整个地图填满土
在地图中间挖一个房间出来
选中某一房间(如果有多个的话)的墙壁
确定要修建某种新元素
查看从选中的墙延伸出去是否有足够的空间承载新的元素
如果有的话继续,不然就返回第 3 步
从选中的墙处增加新的元素
返回第 3 步,直到地牢建设完成
在地图的随机点上安排上楼和下楼的楼梯
最后,放进去怪兽和物品
*/
//-------------------------------------------------------------------------------
// 暂时支持的最大的地图块个数
#define MAX_TILES_NUM  10000
 
// 房间的大小
#define MAX_ROOM_WIDTH  8
#define MAX_ROOM_HEIGHT 8
#define MIN_ROOM_WIDTH  4
#define MIN_ROOM_HEIGHT 4
 
// 房间和走廊的合计最大个数
#define DEFAULT_FEATURE_NUM 1000
 
// 尝试生成房间和走廊的测试次数(即步长)
#define MAX_TRY_TIMES  1000
 
// 默认创建房间的概率(100-该值则为创建走廊的概率)
#define DEFAULT_CREATE_ROOM_CHANCE  70
 
// 走廊长度
#define MIN_CORRIDOR_LEN   3
#define MAX_CORRIDOR_LEN   6
//-------------------------------------------------------------------------------
// 格子块
enum class Tile
{
  Unused, // 没用的格子(土块)
  DirtWall,  // 墙壁
  DirtFloor,  // 房间地板
  Corridor,  // 走廊
  Door,  // 房门
  UpStairs,  // 入口
  DownStairs // 出口
};
//-------------------------------------------------------------------------------
// 朝向
enum class Direction
{
  North,  // 北
  South,  // 南
  East,  // 东
  West,  // 西
};
//-------------------------------------------------------------------------------
class Map
{
public:
 
  Map():
    xSize(0), ySize(0),
    data() { }
 
  // 构造函数,全屏填土
  Map(int x, int y, Tile value = Tile::Unused):
    xSize(x), ySize(y),
    data(x * y, value) { }
 
  // 填充某块类型
  void SetCell(int x, int y, Tile celltype)
  {
    assert(IsXInBounds(x));
    assert(IsYInBounds(y));
 
    data[x + xSize * y] = celltype;
  }
 
  // 获取某块类型
  Tile GetCell(int x, int y) const
  {
    assert(IsXInBounds(x));
    assert(IsYInBounds(y));
 
    return data[x + xSize * y];
  }
 
  // 设置一块区域为指定类型块
  void SetCells(int xStart, int yStart, int xEnd, int yEnd, Tile cellType)
  {
    assert(IsXInBounds(xStart) && IsXInBounds(xEnd));
    assert(IsYInBounds(yStart) && IsYInBounds(yEnd));
 
    assert(xStart <= xEnd);
    assert(yStart <= yEnd);
 
    for (auto y = yStart; y != yEnd + 1; ++y)
    {
      for (auto x = xStart; x != xEnd + 1; ++x)
      {
        SetCell(x, y, cellType);
      }
    }
  }
 
  // 判断一块是否在有效范围内
  bool IsXInBounds(int x) const
  {
    return x >= 0 && x < xSize;
  }
 
  // 判断一块是否在有效范围内
  bool IsYInBounds(int y) const
  {
    return y >= 0 && y < ySize;
  }
 
  // 判断一个区域是否已被使用过
  bool IsAreaUnused(int xStart, int yStart, int xEnd, int yEnd)
  {
    assert(IsXInBounds(xStart) && IsXInBounds(xEnd));
    assert(IsYInBounds(yStart) && IsYInBounds(yEnd));
 
    assert(xStart <= xEnd);
    assert(yStart <= yEnd);
 
    for (auto y = yStart; y != yEnd + 1; ++y)
    {
      for (auto x = xStart; x != xEnd + 1; ++x)
      {
        if (GetCell(x, y) != Tile::Unused)
        {
          return false;
        }
      }
    }
 
    return true;
  }
 
  // 判断一个地图块周围是否临接某种地图块
  bool IsAdjacent(int x, int y, Tile tile)
  {
    assert(IsXInBounds(x - 1) && IsXInBounds(x + 1));
    assert(IsYInBounds(y - 1) && IsYInBounds(y + 1));
 
    return (GetCell(x - 1, y) == tile || GetCell(x + 1, y) == tile ||
      GetCell(x, y - 1) == tile || GetCell(x, y + 1) == tile);
  }
 
  // 输出地图
  void Print() const
  {
    for (auto y = 0; y != ySize; y++)
    {
      for (auto x = 0; x != xSize; x++)
      {
        switch(GetCell(x, y))
        {
        case Tile::Unused:
          std::cout << " ";
          break;
        case Tile::DirtWall:
          std::cout << "#";
          break;
        case Tile::DirtFloor:
          std::cout << "_";
          break;
        case Tile::Corridor:
          std::cout << ".";
          break;
        case Tile::Door:
          std::cout << "+";
          break;
        case Tile::UpStairs:
          std::cout << "<";
          break;
        case Tile::DownStairs:
          std::cout << ">";
          break;
        };
      }
 
      std::cout << std::endl;
    }
 
    std::cout << std::endl;
  }
 
private:
  // 地图总宽高
  int xSize, ySize;
  // 全部地图块数据
  std::vector<Tile> data;
};
//-------------------------------------------------------------------------------
class DungeonGenerator
{
public:
  int m_nSeed;   // 随机数种子
  int m_nXSize, m_nYSize; // 地图最大宽高 
  int m_nMaxFeatures; // 房间和走廊的最大个数
  int m_nChanceRoom;  // 创建房间的概率【0,100】
  int m_nChanceCorridor;  // 创建走廊的概率【0,100】 该概率+创建房间的概率应当 = 100
 
  typedef std::mt19937 RngT;
public:
  DungeonGenerator( int XSize, int YSize ):
    m_nSeed(std::random_device()()),
    m_nXSize( XSize ), m_nYSize( YSize ),
    m_nMaxFeatures( DEFAULT_FEATURE_NUM ),
    m_nChanceRoom( DEFAULT_CREATE_ROOM_CHANCE )
  {
    m_nChanceCorridor = 100 - m_nChanceRoom;
  }
 
  Map Generate()
  {
    assert( m_nMaxFeatures > 0 && m_nMaxFeatures <= DEFAULT_FEATURE_NUM);
    assert( m_nXSize > 3 );
    assert( m_nYSize > 3 );
 
    auto rng = RngT(m_nSeed);
    // step1: 满地图填土
    auto map = Map(m_nXSize, m_nYSize, Tile::Unused);
 
    MakeDungeon(map, rng);
 
    return map;
  }
 
private:
  // 获取随机int
  int GetRandomInt(RngT& rng, int min, int max) const
  {
    return std::uniform_int_distribution<int>(min, max)(rng);
  }
 
  // 获取随机方向
  Direction GetRandomDirection(RngT& rng) const
  {
    return Direction(std::uniform_int_distribution<int>( static_cast<int>(Direction::North), static_cast<int>(Direction::West) )(rng));
  }
 
  // 创建走廊
  bool MakeCorridor(Map& map, RngT& rng, int x, int y, int maxLength, Direction direction) const
  {
    assert(x >= 0 && x < m_nXSize);
    assert(y >= 0 && y < m_nYSize);
 
    assert(maxLength > 0 && maxLength <= std::max(m_nXSize, m_nYSize));
 
    // 设置走廊长度
    auto length = GetRandomInt(rng, MIN_CORRIDOR_LEN, maxLength);
 
    auto xStart = x;
    auto yStart = y;
 
    auto xEnd = x;
    auto yEnd = y;
 
    if (direction == Direction::North)
      yStart = y - length;
    else if (direction == Direction::East)
      xEnd = x + length;
    else if (direction == Direction::South)
      yEnd = y + length;
    else if (direction == Direction::West)
      xStart = x - length;
 
    // 检查整个走廊是否在地图内
    if (!map.IsXInBounds(xStart) || !map.IsXInBounds(xEnd) || !map.IsYInBounds(yStart) || !map.IsYInBounds(yEnd))
      return false;
 
    // 检查走廊区域是否有被占用
    if (!map.IsAreaUnused(xStart, yStart, xEnd, yEnd))
      return false;
 
    map.SetCells(xStart, yStart, xEnd, yEnd, Tile::Corridor);
 
    return true;
  }
 
  // 创造房间
  bool MakeRoom(Map& map, RngT& rng, int x, int y, int xMaxLength, int yMaxLength, Direction direction) const
  {
    assert( xMaxLength >= MIN_ROOM_WIDTH );
    assert( yMaxLength >= MIN_ROOM_HEIGHT );
 
    // 创建的房间最小是4 * 4,随机出房间大小
    auto xLength = GetRandomInt(rng, MIN_ROOM_WIDTH, xMaxLength);
    auto yLength = GetRandomInt(rng, MIN_ROOM_HEIGHT, yMaxLength);
 
    auto xStart = x;
    auto yStart = y;
    auto xEnd = x;
    auto yEnd = y;
 
    // 根据房间朝向随机出房间起始和终结位



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C++ 迷宫游戏实现代码
  • C++实现随机生成迷宫地牢
  • C++实现迷宫算法实例解析

相关文章

  • 2017-05-28详解C语言中的符号常量、变量与算术表达式
  • 2017-05-28浅谈c/c++中使用指针需要注意的问题
  • 2017-05-28C++使用递归函数和栈操作逆序一个栈的算法示例
  • 2017-05-28C语言实现带头结点的链表的创建、查找、插入、删除操作
  • 2017-05-28k均值算法c++语言实现代码
  • 2017-05-28C语言指针入门学习面面观
  • 2017-05-28浅析C语言中printf(),sprintf(),scanf(),sscanf()的用法和区别
  • 2017-05-28打印菱形以及斐波纳契数列的几种解法介绍
  • 2017-05-28C++实现二维图形的傅里叶变换
  • 2017-05-28C++内存查找实例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 讲解C++编程中Address-of运算符&的作用及用法
    • C语言实现排序算法之归并排序详解
    • c语言stack(栈)和heap(堆)的使用详解
    • C++获取多浏览器上网历史记录示例代码(支持获取IE/Chrome/FireFox)
    • 关于统计数字问题的算法
    • c语言的cps实现求fibonacci数列示例
    • 简单掌握C++编程中的while与do-while循环语句使用
    • c++实现十进制转换成16进制示例
    • C/C++中的mem函数和strcopy函数的区别和应用
    • C++设计模式之职责链模式

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有