私は現在、C# (WPF) で学校のプロジェクトとしてテキスト ゲームを作成しています。使用する必要がある構造と OOP 原則 (クラス、継承、例外など) に関していくつかの制限があったため、最終的に 3 つの基本クラスを作成しました。
Scenery(Scene I quess のはず)
{
public class Scenery
{
/* VARIABLES */
// used as reference for the creator, possibly for printout into label
internal string _ID;
public string ID { get { return _ID; } }
// is written into text box after entering the scene
// records changes the user made on the scene
private string _phrase;
internal string Phrase { get { return _phrase; } }
// keys are IDs of game items within the scene
// values are items themselves
internal Dictionary<string, Item> _items;
// keys are IDs of people within the scene
// values are people themselves
internal Dictionary<string, Person> _people;
public Dictionary<string, Person> People { get { return _people; } }
// directions in which the player can go
internal Scenery[] _directions;
/* CONSTRUCTORS */
/* METHODS */
人
{
public class Person
{
/* VARIABLES */
// basic identifier
internal string _ID;
public string ID { get { return _ID; } }
// keys are keywords the person knows about
// values are answers given when asking about a specific keyword
internal Dictionary<string, string> _answers;
public bool Answering { get { if (_answers == null) return false; else return true; } }
// tree-like structure used to have a dialog with this person
internal Node _talk;
public bool Talking { get { if (_talk == null) return false; else return true; } }
// phrase to be written out when you start talking to the person
// when reseting/looping is set to current _talk value
private string _firstPhrase;
public string FirstPhrase { get { return _firstPhrase; } }
// talking interface window
internal Dialog _dialog;
public Dialog Dialog { get { return _dialog; } }
/* CONSTRUCTORS */
/* METHODS */
アイテム
{
public class Item
{
/* VARIABLES */
// identifier, used for writing out general messages and identifying user input
private string _ID;
public string ID { get { return _ID; } }
// indicates if this item can be broken
protected bool _breakable;
// message to be written out after this item is broken
protected string _breakPhrase;
public string BreakPhrase { get { return _breakPhrase; } }
// list of item got after breaking this item
protected Dictionary<string, Item> _afterBreak;
public Dictionary<string, Item> AfterBreak { get { return _afterBreak; } }
public string AfterBreakPrint
{
get
{
string toPrint = "";
foreach (string key in _afterBreak.Keys) toPrint += '\n' + key;
return toPrint;
}
}
// indicates if this item can be investigated
private bool _investigate;
public bool Investigate { get { return _investigate; } }
// reference to the investigation scene
private Scenery _investigation;
public Scenery Investigation { get { return _investigation; } }
/* CONSTRUCTORS */
/* METHODS */
PickableItem、UsableItem などのいくつかのサブクラスがあります。構造はかなり複雑です (サブクラスで Dictionary> などを取得しています) が、少なくとも私の観点からは、これらはメソッドで操作するのが非常に簡単です。
ここで質問: 別のクラス GameData を取得しました。ここで、ゲームのすべてのインスタンス (シーン、アイテム、人) を初期化し、適切な構造に配置します。さらに、1 つの関数で使用して適切なアイテム キーを決定する特別なパブリック変数があります。 . 現在、次のようになっています。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
namespace Textova_Hra
{
public static class GameData
{
public static Scenery start; // starting location
public static List<string> NA_ID_LIST = new List<string>(); // list of IDs in format 'x na y'
// used in Addons -> GetTwoItems
// Basically compiles the whole game returning the starting point
// Declarations must be written from the inside out
// Hra je pro češtinu, ID objektů zadávejte ve 4.pádě, jinak nebude správně fungovat!
// First goes items and people "containing" only strings(and numbers)
// Then goes lists of these items which you want to use in other items etc.
// Last goes sceneries with directions arrays declared first, then scenery declarations,
// then filling corresponding directions arrays
// Finaly the starting scene is saved into the start variable and returned
// The game may begin!
public static Scenery make_start()
{
Dictionary<string, Node> alisTalk1 = new Dictionary<string, Node>();
Dictionary<string, Node> alisLoop = new Dictionary<string, Node>();
Dictionary<string, string> alisAnswers = new Dictionary<string, string>();
alisAnswers.Add("cestu", "Tady zrovna žádné cesty nevedou.");
Node alisTalk11 = new Node("Tak to je skvělé. Už musím běžet.");
Node alisTalk12 = new Node("To je ale velice smutné. No nic, už budu muset jít.", alisLoop, true);
alisTalk1.Add("dobře", alisTalk11);
alisTalk1.Add("špatně", alisTalk12);
Node alisTalk = new Node("Ahoj, jak se máš?", alisTalk1, false);
alisLoop.Add("reset", alisTalk);
Person Alis = new Person("Alis", alisAnswers, alisTalk);
Dictionary<string, Person> start_people = new Dictionary<string, Person>();
start_people.Add("Alis", Alis);
Dictionary<string, Item> canBreak = new Dictionary<string, Item>();
UsableItem hammer = new UsableItem("kladivo", "Sebrali jste pevné železné kladivo. Určitě se jen tak nerozbije.", -1, "", canBreak);
Dictionary<string, Item> flowerVaseAfter = new Dictionary<string, Item>();
Item flowerVase = new Item("váza s květinou", false, "Váza se s ohlušujícím třískotem rozbila na střepy, vypadly z ní mince. Květina leží uvadle na zemi.", flowerVaseAfter);
Dictionary<string, Tuple<string, Item>> flowerChange = new Dictionary<string, Tuple<string, Item>>();
Tuple<string, Item> flowervaset = new Tuple<string, Item>("vázu s květinou", flowerVase);
flowerChange.Add("vázu", flowervaset);
Dictionary<string, string> flowerPhrase = new Dictionary<string, string>();
flowerPhrase.Add("vázu", "Dali jste květinu do vázy. Toto aranžmá místnost poněkud oživilo.");
UsableItem flower = new UsableItem("květina", "Sebrali jste zvláštní namodralou květinu, poněkud uvadlou.", 1, "Květina je nyní ve váze.", flowerChange, flowerPhrase);
PickableItem fragments = new PickableItem("střepy", "Sebrali jste hromádku střepů, třeba se budou ještě k něčemu hodit.");
PickableItem coins = new PickableItem("mince", "Sebrali jste pár zlatých mincí, kterým jste zkrátka nemohli ododlat.");
Dictionary<string, Item> afterVase = new Dictionary<string, Item>();
afterVase.AddMany(fragments, coins);
flowerVaseAfter.AddRange(afterVase);
Scenery[] vaseBack = new Scenery[4];
Scenery vaseInvestigate = new Scenery("Zkoumáte vázu", "Ve váze vidíte několik mincí, ale hrdlo je příliš úzké, aby se daly vysypat.", vaseBack);
Item vase = new Item("váza", true, "Váza se s ohlušujícím třískotem rozbila na střepy a vypadly z ní mince.", afterVase, vaseInvestigate);
canBreak.Add("vázu", vase);
canBreak.Add("vázu s květinou", flowerVase);
Dictionary<string, Item> startItems = new Dictionary<string, Item>();
startItems.Add("vázu", vase);
startItems.Add("květinu", flower);
startItems.Add("kladivo", hammer);
Scenery[] startDirs = new Scenery[4];
Scenery x = new Scenery("Úvod", "Vítejte v nové hře." + '\n' + "Jste v místnosti v malém domku. Mítnost je poloprázdná, je zde akorát malý stůl s vázou, vedle vázy leží květina a pod stolem někdo zapomněl kladivo.", startItems, start_people, startDirs);
vaseBack[0] = x;
start = x;
return start;
}
}
}
これにより、合計 5 つの項目と 1 人の人物で、会話ができ、簡単な質問に答えることができる 1 つのシーンが初期化されます。私はそれを次のように呼びます:
public MainWindow()
{
InitializeComponent();
/* GameData - static class containing declarations of all game instances + helpful variables
method make_start inicializes all game instances and returns a starting point */
current = GameData.make_start();
// print out starting scene description
tbStory.Text = current.Phrase;
lblSceneName.Content = current.ID;
Application.Current.MainWindow.Closed += new EventHandler(MainWindow_Closed);
}
ゲーム自体は、ユーザー入力に使用されるコンボボックス、すべてのテキストを表示するためのテキストボックス、およびインベントリを含むリストボックスを備えた wpf ウィンドウ内で再生されます。すべて正常に動作しますが、ゲームの初期化は非常に面倒で追跡できません。
インスタンス マネージャー (Visual Studio 2012 を使用) のようなものがあるかどうか、またはより簡単な方法で実行できるかどうか疑問に思っていました。また、ゲーム用のインスタンス マネージャーを自分で作成して、使用可能なエンジンにすることも考えていましたが、そのための十分な時間がなく、それを行うためのプログラミングはまだ得意ではありません (C# で 6 週間のみの作業)。 .
何か案は?
PS: クラスが持つことができるコンストラクターの数に制限はありますか? 私の UsableItem クラスは、すべての種類の使用可能なアイテムをカバーする 24 個のクラスになり、私には多すぎるように思えます...