';项目1.Player';是一个';type';而是像';变量';
本文关键字:一个 type 变量 项目 Player | 更新日期: 2023-09-27 18:26:39
我正在通过改进一个基于C#文本的开源冒险来学习一些C#。我正在努力保存所有的播放器数据到一个文件并加载它。
当我尝试序列化播放器类时,编译器抛出错误:
'Project1.Player' is a 'type' but is used like a 'variable' Program.cs:72
更新好的,为了让事情变得更容易,我将所有代码更新到了当前状态。每次我提到玩家时,我都会遇到一个新错误:The name 'player' does not exist in the current context
程序.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Project1
{
class Program
{
public static int windowWidth = 80;
public static int windowHeight = 35;
public static bool run = true;
public static string errorMessage;
public static bool isError = false;
static void Main(string[] args)
{
// setup console window
Console.Clear();
// set size
Console.SetWindowSize(windowWidth, windowHeight);
// remove scroll bar with buffer size equal to window size
Console.BufferWidth = windowWidth;
Console.BufferHeight = windowHeight;
// generate world
Player player = new Player();
World.GenerateWorld();
// begin character creation
string name = Text.Prompt("Welcome stranger. What is your name?");
player.name = name;
player.inventory.Add(new Item("Candle", "A single white candle.", 22));
Text.WriteLine("Thanks, " + name);
Text.WriteLine("Press any key to get started.");
Console.ReadKey();
Console.Clear();
Text.WriteLine("The last thing you remember is battling the Ancient LichLord deep within a cavern beneath Death Mountain. Now suddenly, you are surrounded by the darkness of true night as you stand in front of an ancient stone castle of complex architecture. Looking up, you notice the faint glow of a light coming from an old clock tower, high above the castle. The doors to the castle are large and covered in an ancient mold. Unsure of what to do, you drag open the large wooden door, light the candle you found in your pocket, and step into the castle. 'n 'nPress a key...");
Console.ReadKey();
Console.Clear();
while (run)
{
if (!isError)
{
Text.SetPrompt();
World.LocationDescription();
string temp = Text.Prompt("");
Console.Clear();
player.Do(temp);
}
// there is an error
else
{
DisplayError();
}
}
}
// stream writer to write to file.
public static void SaveGame()
{
try
{
using (Stream stream = File.Open("save.dat", FileMode.Create))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, player);
}
}
catch (IOException)
{
}
}
public static void LoadGame()
{
if (File.Exists("save.dat"))
{
try
{
using (Stream stream = File.Open("save.dat", FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
var player = bin.Deserialize(stream);
}
}
catch (IOException)
{
}
}
else
{
Program.SetError("The savegame does not exist!");
}
}
// stream reader to find file
//public static void LoadGame()
//{
// try
// {
// using (Stream stream = File.Open("data.bin", FileMode.Open))
// {
// BinaryFormatter bin = new BinaryFormatter();
// World.map = (List<Location>)bin.Deserialize(stream);
// }
// }
// catch (IOException)
// {
// }
//}
public static void WinGame()
{
run = false;
Text.WriteLine("As you place the crown upon your head, your vision begins to blur and you fall to the floor. You wake up in a hot cavern, lit by a few torches on the wall. This is the cavern of the Ancient LichLord, and you have escaped his twisted maze. ");
}
#region Error Handling
public static void SetError(string aText)
{
isError = true;
errorMessage = aText;
}
public static void UnsetError()
{
isError = false;
errorMessage = "";
}
public static void DisplayError()
{
Text.WriteColor("|r|" + errorMessage + "|g|");
Text.BlankLines(2);
UnsetError();
}
#endregion
}
}
Player.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Project1
{
[Serializable()]
class Player
{
public string name;
//public static string desc;
//public static int[] stats;
public int location;
public List<Item> inventory = new List<Item>();
public string[] possibleActions = new string[] { "move", "m", "look", "l", "take", "t", "drop", "d", "use", "u", "inventory", "i", "help", "h", "quit", "exit", "save", "load", "name" };
/// <summary>
/// Player action, array of predicate and target
/// </summary>
/// <param name="aAction"></param>
/// <returns></returns>
public void Do(string aText)
{
string verb = "";
string noun = "";
// check if there is a space in the given command
if (aText.IndexOf(' ') != -1)
{
// split the string into the verb and noun
string[] temp = aText.Split(new char[] { ' ' }, 2);
verb = temp[0].ToLower();
noun = temp[1].ToLower();
}
else
{
// verb only
verb = aText.ToLower();
}
if (IsAction(verb))
{
// do whatever action
switch (verb)
{
case "move":
case "m":
if (noun == "")
Program.SetError("You must specify a location to move.");
else
MoveTo(noun);
break;
case "look":
case "l":
if (noun == "")
noun = World.map[player.location].name;
LookAt(noun);
break;
case "take":
case "t":
if (noun == "")
Program.SetError("You must specify an item to take.");
else
PickUpItem(noun);
break;
case "drop":
case "d":
if (noun == "")
Program.SetError("You must specify an item to drop.");
else
DropItem(noun);
break;
case "use":
case "u":
if (noun == "")
Program.SetError("You must specify an item to use.");
else
UseItem(noun);
break;
case "inventory":
case "i":
ListInventory();
break;
case "help":
case "h":
ListActions();
break;
case "quit":
case "exit":
QuitPrompt();
break;
case "save":
Program.SaveGame();
break;
case "load":
Program.LoadGame();
break;
case "name":
Console.WriteLine("Your name is {0}", player.name);
Console.WriteLine("");
break;
}
}
else
{
// not a real action
Program.SetError("Action not found.");
}
}
public void MoveTo(string location)
{
// is location?
if (World.IsLocation(location))
{
int locationId = World.GetLocationIdByName(location);
if (World.IsLocationExit(location))
{
// set the player's new location
player.location = locationId;
}
else
{
Program.SetError("You can't get there from here.");
}
}
else
{
Program.SetError("That is not a real location.");
}
}
public void LookAt(string noun)
{
// is location?
if (World.IsLocation(noun))
{
Console.Clear();
World.ShowHiddenItems();
Text.BlankLines(2);
}
// is item?
else if (Item.IsItemInInventory(noun) || Item.IsItemInLocation(noun))
{
Console.Clear();
Text.WriteLine(Item.GetItemDescByName(noun));
Text.BlankLines(2);
}
}
public void PickUpItem(string item)
{
// is item?
if (Item.IsItemInLocation(item))
{
// get description
string desc = Item.GetItemDescByName(item);
int actionLocationId = Item.GetItemActionLocationIdByName(item);
// remove item from location
Item.RemoveItemFromLocation(item);
// add item to inventory
player.inventory.Add(new Item(item, desc, actionLocationId));
}
else
{
Program.SetError("Item not found in this location.");
}
}
public void DropItem(string item)
{
//is item?
if (Item.IsItemInInventory(item))
{
string desc = Item.GetItemDescByName(item);
int actionLocationId = Item.GetItemActionLocationIdByName(item);
// remove item from inventory
RemoveInventoryItem(item);
// add item to location
World.map[player.location].items.Add(new Item(item, desc, actionLocationId));
}
else
{
Program.SetError("Item not in inventory.");
}
}
public void RemoveInventoryItem(string item)
{
for (int i = 0; i < player.inventory.Count; i++)
{
if (player.inventory[i].name.ToLower() == item.ToLower())
{
player.inventory.RemoveAt(i);
}
}
}
public void UseItem(string item)
{
// is item?
if (Item.IsItemInInventory(item))
{
// get item actionLocationId
int itemActionLocationId = Item.GetItemActionLocationIdByName(item);
if (itemActionLocationId == player.location)
{
World.UseItemInLocation(item);
}
else
{
Program.SetError("You're not sure how that helps here.");
}
}
else
{
Program.SetError("Item not in inventory");
}
}
public void ListInventory()
{
Text.WriteLine("'n-- Inventory -- 'n");
for (int i = 0; i < player.inventory.Count; i++)
{
Text.WriteLine(i.ToString() + ": "+ player.inventory[i].name);
}
Text.BlankLines(2);
}
public void ListActions()
{
Text.BlankLines(2);
//"move", "look", "take", "drop", "use", "inventory", "help"
Text.WriteLine("'n-- Actions -- 'n");
Text.WriteLine("move - travel to another location. usage: move entrance hall (or) m entrance hall");
Text.WriteLine("look - look at a location or an item. usage: look entrance hall (or) look sword (or) l entrance hall (or) l sword");
Text.WriteLine("take - pick up an item in a location. usage: take sword (or) t sword");
Text.WriteLine("drop - drop an item from your inventory. usage: drop sword (or) d sword");
Text.WriteLine("use - use an item in your inventory. usage: use key (or) u key");
Text.WriteLine("inventory - show items in your inventory. usage: inventory (or) i");
Text.WriteLine("help - show this screen. usage: help (or) h");
Text.WriteLine("exit - quit the game. usage: quit (or) exit");
Text.BlankLines(2);
}
/// <summary>
/// Check the legitmacy of the action
/// </summary>
/// <param name="aText"></param>
/// <returns></returns>
public bool IsAction(string aText)
{
for (int i = 0; i < possibleActions.Length; i++)
{
if (aText == possibleActions[i])
{
return true;
}
}
return false;
}
public void QuitPrompt()
{
Text.WriteLine("Are you sure you want to leave? y/n");
string answer = Console.ReadLine().ToLower();
if (answer == "y" || answer == "yes")
{
Program.run = false;
}
}
}
}
项目.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Project1
{
class Item : Entity
{
public bool isHidden = false;
public int actionLocationId;
public string actionName;
public Item(string aName, string aDesc, int aActionLocationId, bool aIsHidden = false, string aActionName = "use")
:base(aName, aDesc)
{
actionLocationId = aActionLocationId;
actionName = aActionName;
if (aIsHidden)
isHidden = aIsHidden;
}
/// <summary>
/// Looks for item in player.inventory
/// </summary>
/// <param name="aName">name of the Item</param>
/// <returns></returns>
public static bool IsItemInInventory(string aName)
{
// look for item in inventory
for (int i = 0; i < player.inventory.Count; i++)
{
if (player.inventory[i].name.ToLower() == aName.ToLower())
{
return true;
}
}
// not found
return false;
}
/// <summary>
/// Looks for item in current location
/// </summary>
/// <param name="aName">name of the Item</param>
/// <returns></returns>
public static bool IsItemInLocation(string aName)
{
// look for item in location
for (int i = 0; i < World.map[player.location].items.Count; i++)
{
if (World.map[player.location].items[i].name.ToLower() == aName.ToLower())
{
return true;
}
}
// not found
return false;
}
/// <summary>
/// Items are only items if in player.inventory or player.location
/// </summary>
/// <param name="aName">name of the Item</param>
/// <returns></returns>
public static string GetItemDescByName(string aName)
{
// look for item in location
for (int i = 0; i < World.map[player.location].items.Count; i++)
{
if (World.map[player.location].items[i].name.ToLower() == aName.ToLower())
{
return World.map[player.location].items[i].description;
}
}
// look for item in inventory
for (int i = 0; i < player.inventory.Count; i++)
{
if (player.inventory[i].name.ToLower() == aName.ToLower())
{
return player.inventory[i].description;
}
}
// not found
return "Item not found";
}
public static int GetItemActionLocationIdByName(string aName)
{
// look for item in inventory
for (int i = 0; i < player.inventory.Count; i++)
{
if (player.inventory[i].name.ToLower() == aName.ToLower())
{
return player.inventory[i].actionLocationId;
}
}
// look for item in location
for (int i = 0; i < World.map[player.location].items.Count; i++)
{
if (World.map[player.location].items[i].name.ToLower() == aName.ToLower())
{
return World.map[player.location].items[i].actionLocationId;
}
}
return -1;
}
public static void RemoveItemFromLocation(string item)
{
for (int i = 0; i < World.map[player.location].items.Count; i++ )
{
if (World.map[player.location].items[i].name.ToLower() == item.ToLower())
{
World.map[player.location].items.RemoveAt(i);
}
}
}
}
}
请注意3件事:
- 我正在学习C#,我来自JS背景
- 我意识到我试图保存球员数据的方式有一些严重的问题,但这就是我来这里的原因
- 这是我第一次尝试在程序中保存大量数据,所以这里有很多实验
在使用Player
对象之前,您需要实例化它,因此:
Player.name = name;
Player.inventory.Add(new Item("Candle", "A single white candle.", 22));
应该是这样的:
var player = new Player();
player.name = name;
player.inventory.Add(new Item("Candle", "A single white candle.", 22));
// etc...
在实例化Player
对象(使用new
关键字)后,只需将所有Player.
调用替换为player.
(或您决定调用播放器变量的任何调用)。
更新
Player
类实际上是静态的(意味着一次只能定义一个)。我建议将其更改为类似的内容
class Player
{
public string name;
public int location;
public List<Item> inventory = new List<Item>();
public string[] possibleActions = new string[] { "move", "m", "look", "l", "take", "t", "drop", "d", "use", "u", "inventory", "i", "help", "h", "quit", "exit", "save", "load", "name" };
/// <summary>
/// Player action, array of predicate and target
/// </summary>
/// <param name="aAction"></param>
/// <returns></returns>
public void Do(string aText)
{
// ...
}
public void MoveTo(string location)
{
// ...
}
public void LookAt(string noun)
{
// ...
}
public void PickUpItem(string item)
{
// ...
}
public void DropItem(string item)
{
// ...
}
public void RemoveInventoryItem(string item)
{
// ...
}
public void UseItem(string item)
{
// ...
}
public void ListInventory()
{
// ...
}
public void ListActions()
{
// ...
}
/// <summary>
/// Check the legitmacy of the action
/// </summary>
/// <param name="aText"></param>
/// <returns></returns>
public bool IsAction(string aText)
{
// ...
}
public void QuitPrompt()
{
// ...
}
}
然后,如果您真的只需要Player
的一个全局实例,那么在Program
:中将其定义为静态
public static Player CurrentPlayer = new Player();
如果你这样做,那么你可以访问Player
实例,比如:
CurrentPlayer.name = name;
CurrentPlayer.inventory.Add(new Item("Candle", "A single white candle.", 22));
另一方面,如果只处理Player
的一个实例并不重要,那么您可以从Player
类中删除所有static
关键字。这应该可以让你克服错误。
更新
我在下面的评论中推荐的解决方案大致如下(没有你问题中代码的所有细节):
public class Player
{
public static Player CurrentPlayer = new Player(); // This is your global instance
public string name;
// All of your other content here
}
public class Program
{
public static void Main()
{
// In here we can access our global instance of `Player` to change it as needed
Player.CurrentPlayer.name = "Some Name Here";
}
}
将静态CurrentPlayer
字段添加到Player
类后,您可以将所有三个代码文件中对player
的所有引用更改为Player.CurrentPlayer
。
要使代码正常工作,您必须将Player类实现为静态类。但是,只有在必要时才使用静态类。
否则,你必须创建一个Player类的实例来处理它
Player player = new Player();
player.name = name;
....
正如错误消息明确指出的那样,您需要将变量作为参数(播放器的实例),而不是类,例如播放器类。
你似乎误解了类的使用,因为播放器类中的所有东西都是静态的,所以类的每个实例都共享,所以实例化变得毫无用处。如果您只希望拥有一个播放器实例,那么您应该了解singleton模式。
在您的示例中,正确的方法是删除播放器类中的静态声明,并在游戏中使用它之前初始化播放器类的新实例。
示例:
Player p = new Player();
p.Name = "Something"
...
try
{
using (Stream stream = File.Open("save.dat", FileMode.Create))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, p);
}
}
catch (IOException)
{
}