0

更新:下部の編集3を参照してください。

私はC#とプログラミング全般の初心者です(だから優しくしてください!)。私はたくさんのチュートリアルに従い、本を読み、クラスを理解したと思いました。今まで。

2D文字列配列を使用して文字E(空の場合)とF(完全の場合)の10x10グリッドを設定する非常に単純なシングルクラスプロジェクトがあります。intxとintyを使用して配列の座標を参照し、switchを使用して入力を検出し、xとyに加算または減算して、配列セルが空か満杯かを判断します。

class MainGame
{
public MainGame()
{
    string[,] mapTerr = new string[10, 10]
    {
        { "F", "F", "F", "F", "F", "F", "F", "F", "F", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
        { "F", "F", "F", "F", "F", "F", "F", "F", "F", "F" },
    }; // long-winded I know, but helps visualise the array
    int x, y;
    string navDir;
    Console.WriteLine("Enter a command:");
    navDir = Console.ReadLine();
    switch (navDir)
    {
        case "N":
        case "n":
            x -= 1;
            if (mapTerr[x, y] == "F")
            {
                Console.WriteLine("You cannot move North, it is blocked!");
                x += 1;
            }
            else
            {
                Console.WriteLine("You move North.");
            }
            break;
        case "E":
        case "e":
            y += 1;
            if (mapTerr[x, y] == "F")
            {
                Console.WriteLine("You cannot move East, it is blocked!");
                y -= 1;
            }
            else
            {
                Console.WriteLine("You move East.");
            }
            break;
        // etc...

これは正常に機能します。ただし、私はそれを別々のクラスに分割しようとしました。1つは配列を作成するためのもので、もう1つは入力と出力を制御するためのものです。これは私の試みです:

class Program
{
    public static void Main(string[] args)
    {
        Map map = new Map();
        UserControl usercontrol = new UserControl();
    }
}

class Map
{
    string[,] mapTerr = new string[10, 10] {
    { // array contents here
    };
}

class UserControl
{
    int x, y;
    string navDir;

    public UserControl()
    {
        Console.WriteLine("Enter a command:");
        navDir = Console.ReadLine();
        switch (navDir)
        {
            case "N":
            case "n":
                x -= 1;
                if (mapTerr[x, y] == "F") // ERROR: The name 'mapTerr' does not exit in the current context"
                {
                    Console.WriteLine("You cannot move North, it is blocked!");
                    x += 1;
                }
                else
                {
                    Console.WriteLine("You move North.");
                }
                break;
            // etc...

私はそれを機能させる方法を一生理解することができません。エラーは主に、スイッチ内からアレイが呼び出された場合に発生します。

これは、配列がUserControlクラスではなくMapクラスに関連付けられているためだと思います。それでは、配列を表示/使用可能にするにはどうすればよいですか?

ここやオンラインの他の場所で配列/スコープ/クラスのセクションをトロールしているにもかかわらず、単純な言葉で物事を完全に説明するものは何もありません。私はそれが範囲の問題だと思います、そして私は不可能な方法で物事への参照を呼び出そうとしています。誰かが私が間違っていることを説明し、おそらく私が物事について正しい道を進むことができる方法を示唆することができれば、私はそれを本当に感謝します!(長い説明/質問をお詫びします)

編集1:行の横にコメントとして特定のエラーメッセージを追加しました。これは、mapTerrがスイッチ内で参照されるすべての行で発生します。

編集2:インスタンス化とクラス構造を明確にしました。

編集3:さて、文字列配列はMapクラスに公開されており、Programクラスでmapクラスをインスタンス化しますが、 ...public string[,] elsaNav = new string[10, 10] {{/*contents*/};を使用しているにもかかわらず、UserControlクラス内からmapTerr配列を呼び出すことはできません。map.mapTerr

4

4 に答える 4

2
public class Map
{
    public string[,] mapTerr = new string[10, 10] {
    { // array contents here
    };
}

public class UserControl
{
    int x, y;
    string navDir;
    Map myMap = new Map();

    public UserControl()
    {
        Console.WriteLine("Enter a command:");
        navDir = Console.ReadLine();
        switch (navDir)
        {
            case "N":
            case "n":
                x -= 1;
                if (myMap.mapTerr[x, y] == "F")
                {
                    Console.WriteLine("You cannot move North, it is blocked!");
                    x += 1;
                }
                else
                {
                    Console.WriteLine("You move North.");
                }
                break;
            // etc...
于 2012-11-22T10:29:15.470 に答える
0

マップクラスをインスタンス化していません。

public UserControl()内から、Map map = new Map();の線に沿って何かを追加する必要があります。

次に、map.mapTerr [x、y]を介してmapTerrにアクセスします

例として、上記のDejoの応答を見てください。

于 2012-11-22T10:28:29.753 に答える
0

この投稿で与えられた提案で編集した後の最終的な解決策がどのようになるかはよくわかりませんが、コードを修正して、それを操作する1つの方法を提供します。うまくいけば、エラーを特定するのに役立ちます。あなたのコード:)

using System.Collections;
using System;

class Program
{
    public static void Main(string[] args)
    {
        UserControl usercontrol = new UserControl();
    }
}

class Map
{
// Private map
private string[,] mapTerr;

// Public map
public string[,] MapTerr
{
    get {return mapTerr;}
}

public Map(int width, int height)
{
    mapTerr = new string[width, height];

    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            mapTerr[x,y] = "E";
        }
    }
}
}

class UserControl
{
    int x, y;
    string navDir;
Map map;

    public UserControl()
    {
        map = new Map(10, 10);
        Console.WriteLine("Enter a command:");
        navDir = Console.ReadLine();
        switch (navDir)
        {
            case "N":
            case "n":
            x -= 1;
            if (map.MapTerr[x, y] == "F") // ERROR: The name 'mapTerr' does not exit in the current context"
            {
                Console.WriteLine("You cannot move North, it is blocked!");
                x += 1;
            }
            else
            {
                Console.WriteLine("You move North.");
            }
            break;
        // etc...
        }
}
}

インデントが少しずれている場合はお詫びします。急いでいて、現在適切なC#コンパイラにアクセスできませんが、上記のコードは機能するはずです:)

ちなみに、マップとユーザー入力をカプセル化して2つのクラスに分けることをお勧めします。新しいプログラマーにとって素晴らしいスタートです:)

クラスでデータメンバーにアクセスする方法を制御するには、クラスでプロパティを多用することを忘れないでください。ほとんどの場合、メンバーを純粋に公開したくはありません。代わりに、それらをプライベートにし、それらのプロパティを作成して、データの設定またはアクセス方法を制御できるようにします。

もちろん、ソリューションを紹介するためだけに文字で配列を初期化するためのいくつかのサンプルロジックをすばやく作成したので、自分のニーズに合わせてそれを書き直したいと思うでしょう:)

また、mapオブジェクトをどのように操作するかは、クライアントがコードをどのように操作するかについてのあなた自身の考えにも依存します。クライアントコードを操作させずに、MapオブジェクトをUserControlクラスの構成にするだけです。もちろん、別の方法として、クライアントコードに独自のマップオブジェクトを初期化させ、それをUserInputクラスのコンストラクターに渡すこともできます。

お役に立てば幸いです。

[編集]

さて、文字列配列はMapクラスでパブリックに設定されます。publicstring [、] elsaNav = new string [10、10]{{/コンテンツ/}; そして、Programクラスでmapクラスをインスタンス化しますが、map.mapTerrを使用しているにもかかわらず、UserControlクラス内からmapTerr配列を呼び出すことができません。

さて、私はこれに対するあなたのソリューションコードを見ていませんが、おそらく私はまだそれを手に入れています...それを試してみましょう:P基本的にあなたはProgramクラスのMapクラスをインスタンス化しています、次のようなものです:

Map myMap = new Map();

次に、UserControlクラスのインスタンスで「myMap」参照に直接アクセスしようとしますか?この場合、これを単純に行うことはできません。myMap参照は、呼び出し元のProgramクラスメソッド内のスコープ内にのみ存在するため、 UserControlクラス内から参照しようとすると、myMap参照はまったく認識されず、スコープ外になります。代わりに、次のようにUserControlクラスに参照を渡す必要があります。

Map myMap = new Map();

UserControl newControl = new UserControl(myMap);

そして、クラス内から、コンストラクターは次のようになります。

    public UserControl(Map map)
    {
        map.MapTerr... etc
    }

おそらく私はあなたが言ったことを誤解しました、しかしそれがあなたが意味したものであるならば、上記の解決策はそれを正しく修正するはずです:)

于 2012-11-22T20:29:22.480 に答える
-1

主な問題は、mapTerrのデフォルトの保護レベルがMap専用であるということです。次に、公開されている場合でも、インスタンス化されたMapのインスタンスを使用するか、静的にすることで、さらに修飾する必要があります。

static class Map
{
    public static readonly string[,] mapTerr = new string[10,10 {...}
}

参照するには、プロパティを完全に修飾する必要があります。

class UserControl
{
    public UserControl()
    {
        ...
        if (Map.mapTerr[x,y] == "F")
        { 
            ...
        }
    }
}

また、1)プロパティの背後にあるパブリックフィールドを非表示にし、2)文字列をcharに変更することも検討する必要があります。

于 2012-11-22T10:41:01.843 に答える