SaxonRahs Tutorial Thread - Random Maze Generation & Solving

Source Code
MazeHUD.h


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

#pragma once


#include "GameFramework/HUD.h"
#include "MazeHud.generated.h"


UCLASS()
class AMazeHud : public AHUD
{
    GENERATED_UCLASS_BODY()


    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MazeHUD)
        bool ShowTests;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MazeGen101isMax)
        float MazeXKeepODD;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MazeGen101isMax)
        float MazeYKeepODD;
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = MazeTiles)
        UClass* TileGroundBP;
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = MazeTiles)
        UClass* TileBlockBP;
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = MazeTiles)
        UClass* TilePillarBP;
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = MazeTiles)
        UClass* TileStartBP;
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = MazeTiles)
        UClass* TileEndBP;
    UFUNCTION(BlueprintCallable, Category = MazeGen)
        void GenMaze(float tileX, float tileY);
    public:
    virtual void DrawHUD() OVERRIDE;
    virtual void PostInitializeComponents() OVERRIDE;
};


template <typename AMazeGen>
FORCEINLINE AMazeGen* SpawnBP(
    UWorld* TheWorld,
    UClass* TheBP,
    const FVector& Loc,
    const FRotator& Rot,
    const bool bNoCollisionFail = true,
    AActor* Owner = NULL,
    APawn* Instigator = NULL
    ){
    if (!TheWorld) return NULL;
    if (!TheBP) return NULL;
    //~~~~~~~~~~~


    FActorSpawnParameters SpawnInfo;
    SpawnInfo.bNoCollisionFail = bNoCollisionFail;
    SpawnInfo.Owner = Owner;
    SpawnInfo.Instigator = Instigator;
    SpawnInfo.bDeferConstruction = false;


    return TheWorld->SpawnActor<AMazeGen>(TheBP, Loc, Rot, SpawnInfo);
}

MazeHUD.cpp


// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

#include "YourProject.h"
#include "MazeHud.h"

const int MazeSizeMax = 101;

AMazeHud::AMazeHud(const class FPostConstructInitializeProperties& PCIP)
    : Super(PCIP)
{
    MazeXKeepODD = MazeSizeMax;
    MazeYKeepODD = MazeSizeMax;
}
void AMazeHud::PostInitializeComponents(){
    Super::PostInitializeComponents();
    //Initial Message
    if (ShowTests){
        GenMaze(MazeXKeepODD, MazeYKeepODD);
    }
}
void AMazeHud::DrawHUD(){
    Super::DrawHUD();
}
void AMazeHud::GenMaze(float tileX, float tileY){
    float CaptureX = 0.0f;
    float CaptureY = 0.0f;
    float offset = 400.0f;
    float iter = 0;
    int tileID = 0;
    int RandomEndTileLoc = rand() % ((int)tileX - 1) + 1;

    AStaticMeshActor* grid[MazeSizeMax][MazeSizeMax];

    for (int x = 0; x<tileX; x++){
        for (int y = 0; y<tileY; y++){
            if (y == 0 || x == 0 || y == tileY - 1 || x == tileX - 1 || y % 2 == 0 && x % 2 == 0){
                //                          (X.Xf,Y.Yf,Z.Zf)
                const FVector  GenSpawnLoc(CaptureX, CaptureY, 0.0f);
                const FRotator GenSpawnRot(0.0f, 0.0f, 0.0f);
                AStaticMeshActor* BlockTile = SpawnBP<AStaticMeshActor>(GetWorld(), TileBlockBP, GenSpawnLoc, GenSpawnRot);

                grid[x][y] = BlockTile;
            }
            else{
                const FVector  GenSpawnLoc(CaptureX, CaptureY, 0.0f);
                const FRotator GenSpawnRot(0.0f, 0.0f, 0.0f);

                AStaticMeshActor* GroundTile = SpawnBP<AStaticMeshActor>(GetWorld(), TileGroundBP, GenSpawnLoc, GenSpawnRot);

                grid[x][y] = GroundTile;
            }
            //-------------Starting Tile Spawn---------------
            if (CaptureX == offset && CaptureY == offset){
                grid[1][1]->Destroy();

                const FVector  GenSpawnLoc(400.0f, 400.0f, 0.0f);
                const FRotator GenSpawnRot(0.0f, 0.0f, 0.0f);
                //Tile Start
                AStaticMeshActor* StartTile = SpawnBP<AStaticMeshActor>(GetWorld(), TileStartBP, GenSpawnLoc, GenSpawnRot);

                grid[1][1] = StartTile;
            }
            //-------------Ending Tile Spawn---------------
            if (y == tileY - 1 && x == tileX - 1){
                grid[x - 1][y - 1]->Destroy();

                const FVector  GenSpawnLoc(((tileX - 2) * offset), ((tileY - 2) * offset), 0);
                const FRotator GenSpawnRot(0.0f, 0.0f, 0.0f);
                // Tile End
                AStaticMeshActor* EndTile = SpawnBP<AStaticMeshActor>(GetWorld(), TileEndBP, GenSpawnLoc, GenSpawnRot);

                grid[x - 1][y - 1] = EndTile;
            }
            CaptureY += offset;
            if (CaptureY >= offset * tileY){ CaptureY = 0; }
        }
        CaptureX += offset;
        if (CaptureX >= offset * tileX){ CaptureX = 0; }
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    for (int y = 2; y < tileY - 1; y += 2) {
        int dx = 2;
        int dy = y;
        int rnd4;

        switch (rnd4 = rand() % 4){
        case 0: dx++; break;
        case 1: dx--; break;
        case 2: dy++; break;
        case 3: dy--; break;
        }
        //if (bd.getPixel(dx, dy) != Status.WALL) {
        if (grid[dx][dy]->GetActorLabel() != "Block") {
            FVector f = grid[dx][dy]->GetActorLocation();
            grid[dx][dy]->Destroy();

            const FVector  GenSpawnLoc(f);
            const FRotator GenSpawnRot(0.0f, 0.0f, 0.0f);

            AStaticMeshActor* BlockTile = SpawnBP<AStaticMeshActor>(GetWorld(), TileBlockBP, GenSpawnLoc, GenSpawnRot);
            grid[dx][dy] = BlockTile;
        }
        else{
            y -= 2;
        }
    }
    for (int x = 4; x < tileX - 1; x += 2) {
        for (int y = 2; y < tileY - 1; y += 2) {
            int dx = x;
            int dy = y;
            int rnd3;

            switch (rnd3 = rand() % 3){
            case 0: dy++; break;
            case 1: dy--; break;
            case 2: dx++; break;
            }
            //if (bd.getPixel(dx, dy) != Status.WALL) {
            if (grid[dx][dy]->GetName() != "Block") {
                FVector f = grid[dx][dy]->GetActorLocation();
                grid[dx][dy]->Destroy();

                const FVector  GenSpawnLoc(f);
                const FRotator GenSpawnRot(0.0f, 0.0f, 0.0f);

                AStaticMeshActor* BlockTile = SpawnBP<AStaticMeshActor>(GetWorld(), TileBlockBP, GenSpawnLoc, GenSpawnRot);
                grid[dx][dy] = BlockTile;
            }
            else{
                y -= 2;
            }
        }
    }
}