制作控制台应用程序生存游戏的初学者,不确定如何在方形网格上生成房间位置

Beginner making a Console app survival game, unsure on how to generate room positions on a square grid

我将复习一下目前的情况,然后解释问题。

我有一个名为 Room 的 class,每个房间都有一个 XPos 和一个 YPos,以及其他多个不相关的参数。到目前为止,我一直在 main 方法中分配这些值,手动创建一个具有指定值的新房间。这变得不切实际且无聊,所以我决定尝试随机生成房间。

我首先创建了一个名为 GenerateRooms 的方法,其中包含 return 类型的列表。这被分配给在运行时与之通信的房间列表。 生成房间:

private static List<Room> GenerateRooms(int gridSize)
    {
        RandomRoomGenerator randomRoomGenerator = new RandomRoomGenerator();
        int numRooms = gridSize * gridSize;
        List<Room> rooms = new List<Room>();

        for (int i = 0; i < numRooms; i++)
        {
            rooms.Add(randomRoomGenerator.GenerateRoom(gridSize, rooms));
        }

        return rooms;
    }

如您所见,它还接受一个名为 gridSize 的参数。这就是世界的length/width。它稍后用于我尝试生成房间位置。 在 GenerateRoom 内部,我将值分配给房间构造函数。房间的描述或者物品之类的东西,我在随机化的时候没有遇到太多的问题,但是位置给我带来了很大的麻烦。

生成房间:

public class RandomRoomGenerator
{
    public Room GenerateRoom(int gridSize, List<Room> rooms)
    {
        RandomRoomDescriptions randomRoomDescriptions = new RandomRoomDescriptions();
        RandomItemGenerator randomItemGenerator = new RandomItemGenerator();
        ItemDB itemDb = new ItemDB();

        string description = randomRoomDescriptions.roomDescriptions[new Random().Next(0, randomRoomDescriptions.roomDescriptions.Count)];

        Room room = new Room(description, GenerateXPos(rooms, gridSize), GenerateYPos(rooms, gridSize), new Random().Next(1, 7), new Random().Next(1, 7), new Random().Next(1, 7), randomItemGenerator.GenerateRandomItems(itemDb));
        return room;
    }

    private int GenerateXPos(List<Room> rooms, int gridSize)
    {
        int xPos = 0;

        foreach (var room in rooms)
        {
            if (room.XPos == xPos)
            {
                xPos++;
                if (xPos == gridSize)
                {
                    return xPos;
                }
            } 
        }


        return xPos;

    }

    private int GenerateYPos(List<Room> rooms, int gridSize)
    {
        int yPos = 0;

        foreach (var room in rooms)
        {
            if (room.XPos == gridSize && room.YPos == yPos)
            {
                yPos++; 
                return yPos;
            }
        }

        return yPos;

    }

使用您可以在此处看到的代码,我能够创建一条水平线的房间,三个房间长,以及在 (3, 1) 处的六个堆叠房间。

问题:我需要让 GenerateXPos 只遍历当前行的房间。我尝试在 GenerateRoom class 中创建一个名为 YPos 的变量,并在 XPos 达到 GridSize 时递增它,但这没有用。

我认为另一种解决方案可能是完全消除 Room 构造函数中对 X 和 Y pos 的需要,并在 main 方法中分配位置。但这是最后的手段。我想增加我的经验并揭开编码的神秘面纱,以便我可以学得更好。如果我没有提供足够的信息,请告诉我。为了以防万一,这里有一些相关的 classes: 主要:

static void Main(string[] args)
    {
        Console.WriteLine("Welcome to the wasteland.");
        List<Room> rooms = GenerateRooms(3);
        var currentRoom = rooms[0];



        Player player = new Player(100, 10, 10, 10, 0,0);
        player.Inventory.Add(player.CurrentWeapon = new Weapon("Fists", "Regular fists.", 1));

        GameState.GameStates currentGameState = GameState.GameStates.Exploring;


        while (player.Health > 0 && player.Hunger < 50 && player.Thirst < 50 && player.Radiation < 50)
        {
            while (currentGameState == GameState.GameStates.Exploring)
            {
                Input.HandleExplorationInput(player, ref currentRoom, rooms, ref currentGameState);

            }

            while (currentGameState == GameState.GameStates.Fighting)
            {
                Input.HandleEncounterInput(player, currentRoom.Enemy, player.CurrentWeapon, ref currentGameState, currentRoom);
            }
        }

        Console.WriteLine("You died!");

    }

房间:

public class Room
{
    public string Description { get; set; }
    public int XPos { get; set; }
    public int YPos { get; set; }
    public int HungerToAdd { get; set; }
    public int ThirstToAdd { get; set; }
    public int RadiationToAdd { get; set; }
    public List<Item> Items { get; set; }
    public Enemy Enemy { get; set; }


    //Description, coord, and stats.
    public Room(string description, int xPos, int yPos, int hungerToAdd, int thirstToAdd, int radiationToAdd)
    {
        this.Description = description;
        this.XPos = xPos;
        this.YPos = yPos;
        this.HungerToAdd = hungerToAdd;
        this.ThirstToAdd = thirstToAdd;
        this.RadiationToAdd = radiationToAdd;
    }

    //Description, coord, stats, and items.
    public Room(string description, int xPos, int yPos, int hungerToAdd, int thirstToAdd, int radiationToAdd, List<Item> items)
    {
        this.Description = description;
        this.XPos = xPos;
        this.YPos = yPos;
        this.Items = items;
        this.HungerToAdd = hungerToAdd;
        this.ThirstToAdd = thirstToAdd;
        this.RadiationToAdd = radiationToAdd;
    }

    //Description, coord, stats, items, and enemy.
    public Room(string description, int xPos, int yPos, int hungerToAdd, int thirstToAdd, int radiationToAdd, List<Item> items, Enemy enemy)
    {
        this.Description = description;
        this.XPos = xPos;
        this.YPos = yPos;
        this.Items = items;
        this.Enemy = enemy;
        this.HungerToAdd = hungerToAdd;
        this.ThirstToAdd = thirstToAdd;
        this.RadiationToAdd = radiationToAdd;

    }

    //Description, coord, stats, and enemy.
    public Room(string description, int xPos, int yPos, int hungerToAdd, int thirstToAdd, int radiationToAdd, Enemy enemy)
    {
        this.Description = description;
        this.XPos = xPos;
        this.YPos = yPos;
        this.Enemy = enemy;
        this.HungerToAdd = hungerToAdd;
        this.ThirstToAdd = thirstToAdd;
        this.RadiationToAdd = radiationToAdd;

    }
}

看来您是创建房间网格(宽度和高度 = gridSize 的单元格)的方法,其中您有多个属性。其中之一是房间描述。此房间描述应从您(某处)的列表中随机选择。为此,您真正需要做的就是创建一个随机整数列表(在本例中为 HashSet——请参阅下面的原因),其中 HashSet 中的最大值最多应该是最大数量"randomRoomDescriptions" 列表(或数组?)中的元素。

因此,您的代码可以大大简化。

Room class 可能看起来像:

public class Room
{
    public string Description { get; set; }
    public int XPos { get; set; }
    public int YPos { get; set; }
    public int HungerToAdd { get; set; }
    public int ThirstToAdd { get; set; }
    public int RadiationToAdd { get; set; }
    public List<int> Items { get; set; }
    public string Enemy { get; set; }

    //Description, coord, and stats.
    public Room(string description, int xPos, int yPos)
    {
        CreateDescriptionList();
        Random rand = new Random();

        this.Description = description;
        this.XPos = xPos;
        this.YPos = yPos;
        this.HungerToAdd = rand.Next(1, 7);
        this.ThirstToAdd = rand.Next(1, 7);
        this.RadiationToAdd = rand.Next(1, 7);
        //this.Items = do something here!
        //this.Enemy = "Fred"; //Do something here, too!
    }
}

现在只需填充 Room 列表 "rooms":

        var maxGrid = 3;
        var rooms = CreateRandomRooms(maxGrid);

使用以下方法:

    private List<Room> CreateRandomRooms(int grid)
    {
        RandomRoomDescriptions randomRoomDescriptions = new RandomRoomDescriptions();
        var listRooms = new List<Room>();
        var rand = GetRandomRoomIndicies(grid, Room.maxDecriptionEntries);

        int index = 0;
        for (int x = 0; x < grid; x++)
        {
            for (int y = 0; y < grid; y++)
            {
                var i = rand.ElementAt(index);
                var descr = randomRoomDescriptions.roomDescriptions[i];
                var room = new Room(descr, x, y);
                listRooms.Add(room);
                index++;
            }
        }

        return listRooms;
    }



    private HashSet<int> GetRandomRoomIndicies(int grid, int maxRand)
    {
        int minRand = 0;
        int maxCount = grid * grid;
        var rand = new Random();

        var randHashset = new HashSet<int>();

        while (randHashset.Count < maxCount)
        {
            randHashset.Add(rand.Next(minRand, maxRand));
        }

        return randHashset;
    }

关键在于方法"GetRandomRoomIndicies"。它创建一个 HashSet 的随机整数值(最大值 = 描述列表中的最大描述数)。此 HashSet 将用于从您的列表中获取随机描述并使用它来描述 Room。在创建 Room 时,随机数生成器用于填充 "Hunger"、"Thirst" 和 "Radiation" 等内容。您需要对 "Items" 和 "Enemy".

做一些事情

HashSet 的好处是它只允许添加唯一值。所以你只要保持 "Adding" 直到集合达到你想要的大小。