制作控制台应用程序生存游戏的初学者,不确定如何在方形网格上生成房间位置
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" 直到集合达到你想要的大小。
我将复习一下目前的情况,然后解释问题。
我有一个名为 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" 直到集合达到你想要的大小。