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

