通过本文主要向大家介绍了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; // 根据房间朝向随机出房间起始和终结位