문제

나는 지금 이것을 오랫동안 (3 일) 해결하려고 노력했지만 그것을 알아낼 수는 없습니다. 문제가 좀 더 복잡하기 때문에 종합적으로 설명하려고 노력할 것입니다.

내 학교 과제는 C# Visual Studio 2008에서 OOP를 사용하여 간단한 텍스트 게임을 만드는 것입니다 (교사가 제공 한 도서관에 구축해야 함). 콘솔 만 사용해야합니다. PHP와 C ++의 OOP에 대한 적절한 경험이 있지만 여전히 이것을 알아낼 수는 없습니다.

텍스트 게임의 80%가 이미 작동하고 있으므로 이미 작동하고 문제와 관련이없는 수업과 물건으로 당신을 낳지 않을 것입니다. Ok 시작하자 :

게임의 각 명령 (콘솔에 입력하고 Enter hit Enter)은 추상 클래스를 확장하는 단일 클래스와 게임을 구축 해야하는 라이브러리에서 인터페이스를 모두 표시합니다. Bellow는 항목을 사용하기위한 명령을 나타내는 클래스 사용입니다 (예 : 콘솔에 "소드 사용"을 입력하면 게임은 Sword라는 항목을 찾고 사용 방법을 호출합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Game.Commands
{
    class Use : TextGame.Commands.ACommand, TextGame.Commands.ICommand
    {
        private string name;
        public new string Name
        {
            set { this.name = value; }
            get { return this.name; }
        }

        private string description;
        public new string Description
        {
            set { this.description = value; }
            get { return this.description; }
        }

        private string parameters;
        public new string Params
        {
            set { this.parameters = value; }
            get { return this.parameters; }
        }

        public Use(string name, string description) : base(name, description)
        {
            this.name = name;
            this.description = description;
        }

        private TextGame.Core.GameState gameState;
        public TextGame.Core.GameState Execute(TextGame.Core.IGame game)
        {
            // This is just a test because it appears the problem is
            // with the parameters property. There should be a command
            // you have typed in the console but its always null
            // Note that I have not yet coded the body of this method.
            // I will do that once I solve the problem.
            if (this.parameters == null)
            {
                Console.WriteLine("is null");
            }
            else
            {
                Console.WriteLine(this.parameters);
            }
            return this.gameState;
        }
    }
}

사용되는 두 가지 다른 클래스가 있습니다. 파서 클래스와 게임 클래스. 조금 더 길어서 관련 물건의 스 니펫 만 게시 할 것입니다. 파서 클래스 :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections; // ArrayList, Dictionary, Hashtable
using System.Text.RegularExpressions; // regex engine
using Game.Commands;

namespace Game
{
    class Parser
    {
        private ArrayList commands = new ArrayList();

        // All commands that are available in the game so far are
        // initialized here in the constructor (and added to the arraylist)...
        // skip to the other method this is not important
        public Parser()
        {
            this.commands.Add(new North("^north", "Go north"));
            this.commands.Add(new South("^south", "Go south"));
            this.commands.Add(new East("^east", "Go east"));
            this.commands.Add(new West("^west", "Go west"));
            this.commands.Add(new Use("^use\\s\\w+", "Try to use the selected item"));
            this.commands.Add(new Quit("^quit", "Quit the game"));
        }

        // This method takes as an argument a string representing
        // a command you type in the console. It then searches the arraylist
        // via the regex. If the command exists, it returns an the command object
        // from the arraylist
        // This works fine and returns right objects (tested)
        public TextGame.Commands.ACommand GetCommand(string command)
        {
            TextGame.Commands.ACommand ret = null;
            foreach (TextGame.Commands.ACommand c in this.commands)
            {
                Regex exp = new Regex(@c.Name, RegexOptions.IgnoreCase);
                MatchCollection MatchList = exp.Matches(command);
                if (MatchList.Count > 0)
                {
                    ret = c;
                }
            }
            return ret;
        }
    }
}

이제 위의 두 클래스를 모두 사용하는 게임 클래스의 스 니펫 :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TextGame.Core;
using System.Collections;
using Game.Items;
using Game.Commands;

namespace Game
{
    class Game : TextGame.Core.IGame
    {

        public void Play()
        {   
            // Here I read commands from the console in a loop and
            // call the ProcessCommand() method. No problem here.
            while (true)
            {
                string command = Console.ReadLine();
                this.ProcessCommand(command);
            }
        }

        // This is the IMPORTANT method so take a closer look
        private TextGame.Core.GameState gameState;
        public TextGame.Core.GameState ProcessCommand(string command)
        {
            Parser parser = new Parser();
            TextGame.Commands.ACommand c = parser.GetCommand(command);
            if (c != null)
            {
                // HERE I ADD THE COMMAND FROM THE CONSOLE TO THE C OBJECT
                // I ADD IT VIA THE SETTER TO THE PARAMETERS PROPERTY
                // OF THE COMMAND
                c.Params = command;
                // AND I CALL THE COMMAND'S EXECUTE() METHOD - SEE THE FIRST CLASS -
                // USE - WHERE I TEST FOR THE PARAMS PROPERTY BUT IT IS STILL NULL
                this.gameState = ((TextGame.Commands.ICommand)c).Execute(this);
            }
        }
    }
}

문제가 어디에 있는지 설명하기 위해 스 니펫에 의견을 추가했습니다. 나는 그것을 잘 설명했으면 좋겠다.

누구든지 아이디어가 있습니까? 나는이 프로젝트를 약 3 주 동안 작업 해 왔으며 3 일 전에이 문제를 발견했을 때 대부분의 물건은 순조롭게 진행되었으며 그 이후 로이 문제를 해결하려고 노력했습니다.

도움이 되었습니까?

해결책

당신의 문제는 '새로운'키워드에 문제가 있습니다. '사용'수업에서 사용하는 곳입니다.

    private string parameters;
    public new string Params
    {
        set { this.parameters = value; }
        get { return this.parameters; }
    }

상속하는 유형의 속성과 동일한 이름을 갖는 다른 속성을 만들고 있습니다. '새로운'키워드는 컴파일러에게 당신이 그렇게하려는 것을 알려줍니다.

기본적으로 이것은 다음을 수행한다는 것을 의미합니다.

var x = new Use();
x.Params = "abcd";
((ACommand)x).Params = "wxyz";
Console.Writeline("direct: " + x.Params);
Console.Writeline("ACommand: " + ((ACommand)x).Params);

이 출력을 얻을 수 있습니다.

직접 : ABCD

ACOMMAND : WXYZ

아마도 사용에서 'params'의 정의를 완전히 제거하고 Acommand에서 상속받을 것입니다. 아마도 이름과 설명에서도 있지만, 원하든 원하지 않으면 여기에서 알아낼 수 있어야합니다.

다른 팁

Acommand 클래스의 코드를 보지 않고 ... 사용 클래스의 매개 변수 선언에서 "새"연산자를 제거하십시오. 속성을 설정할 때 c.params = 명령; 실제로 기본 클래스의 속성을 설정하고, 실행 메소드에서 vase.params 대신 this.parameters를 확인하는 실행 방법에서.

// 문제가있는 것처럼 보이기 때문에 이것은 단지 테스트입니다.
// 매개 변수 속성이 있습니다. 명령이 있어야합니다
// 콘솔에서 입력했지만 항상 null
// 아직이 방법의 본문을 코딩하지 않았다는 점에 유의하십시오.
// 문제를 해결하면 그렇게하겠습니다.

이것은 귀하가 귀하의 속성에 새롭게 선언함으로써 발생합니다. ACOMMAND의 논리를 변경할 필요가 없다면 이들은 재정의되거나 전혀 포함되지 않아야합니다.

당신이 acommand로 언급 할 때 :

TextGame.Commands.ACommand c = parser.GetCommand(command);            
c.Params = command;

Acommand의 매개 변수 또는 재정의 (정의 된 경우)를 사용합니다.

귀하의 새로운 Params Shadow Acommand의 Params는 귀하의 참조가 USEcommand 인 경우에만 액세스 할 수 있습니다.

귀하의 문제는 여기에 있습니다.

private string parameters;
public new string Params
{
    set { this.parameters = value; }
    get { return this.parameters; }
}

코드에서 :

c.Params = command;

당신은 유형을 참조하고 있습니다 TextGame.Commands.ACommand. 서브 클래스에 Param 속성을 숨기고 있으므로 비 폴리 흉부 기준을 유발합니다. 위의 정의를 제거하고 Param의 기본 클래스 정의에 의존하면 괜찮을 것입니다.

이 문제를 해결 한 지 오래되었지만 반사기로 열면 사용을 숨기고 있음을 알게 될 것입니다. 타이피스트가 지적했다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top