实现pin键盘,简化代码?

时间:2016-06-30 17:33:28

标签: c# unity3d

我正在游戏中创建一个键盘。我创建的游戏对象有10个按钮:0-9。玩家必须输入4位数代码才能打开门。一旦玩家输入第一个数字,它就会显示在键盘的屏幕上。

我已经完成了所有基本代码,但我确信我已经以非常低效的方式完成了这项工作。现在,我已将以下功能附加到我的一个键上,实际上是数字1键:

    public void Key1() {

    if (digit1entered == false) {

        digit1 = 1;
        displaycode.text = digit1.ToString () + digit2.ToString () + digit3.ToString () + digit4.ToString ();
        print ("First digit entered");
        digit1entered = true;
    } else {
        if (digit1entered == true && digit2entered == false) {

            digit2 = 1;
            digit2entered = true;
            displaycode.text = digit1.ToString () + digit2.ToString () + digit3.ToString () + digit4.ToString ();
            print ("2nd digit entered");
        } else {
            if (digit2entered == true && digit3entered == false) {
                digit3 = 1;
                digit3entered = true;
                displaycode.text = digit1.ToString () + digit2.ToString () + digit3.ToString () + digit4.ToString ();
                print ("3rd digit entered");
            } else {
                if (digit3entered == true && digit4entered == false) {

                    digit4 = 1;
                    digit4entered = true;
                    displaycode.text = digit1.ToString () + digit2.ToString () + digit3.ToString () + digit4.ToString ();
                    print ("4th digit entered");

                }
            }

        }
    }
}

为了使整个键盘工作,我需要创建9个以上的功能,每个功能都有2-0的更新值。这意味着我最终会得到10个相似的函数,除了它们输入的值。这是糟糕的编程,所以我该如何避免呢?哦,如果上面已经开始编程不好了,欢迎提示所有提示; - )

4 个答案:

答案 0 :(得分:5)

很难做到这一点非常困难。你选择了一个真正的挑战。

您的第一个问题是,您必须集中信息流。让我们这样做。

有这样的功能

Complex.cs

在你的脚本 private string FourOnly(string s) { while (s.Length > 4 ) s = s.Substring(1); return s; } 中说某个对象

有十个按钮。在Inspector中,拖动以连接...

enter image description here

请注意,您实际上可以输入一个数字 - 我输入" 3"。

所以你实际上设置了值" 0"至" 9"在你的十个按钮上。

{脚注。你不会在真实的"中做到这一点。项目,因为它是正交的,会导致设计人员麻烦。我会根据键盘位置或其他东西神奇地查找数字。但这是一个很好的开始!}

所以你实际连接

相同脚本和功能的所有按钮。

一旦你有了这个工作,请告诉我们,我们会找出下一部分!

接下来,您需要一个永远不会让字符串超过四个字符的函数。如果您在最后添加一个,它会删除第一个

(重要提示:您实际上是通过扩展程序来实现这一点,这是Unity编程的绝对核心。但它太过于一次解释所有内容。当你有时间处理this

大致你的功能是..

[System.NonSerialized] public string pin = "";

public void UserClickedButtonNumbered(int digitNumber)
    {
    Debug.Log("that button name is " +digitNumber);
    pin = pin + digitNumber.ToString();
    pin = FourOnly(pin);
    Debug.Log("So far, the user entered: " +pin);
    if ( pin == "1313" ) Debug.Log("code unlocked!");
    }

所以现在你可以这样做......

public Text led1;  // Text, or whatever your digits are
public Text led2;
public Text led3;
public Text led4;

private void FixLEDs()
 {
 string show = pin + "       "; // just add many spaces on the end
 led1.text = show[0].ToString(); // "show[n]" is a char, not a string
 led2.text = show[1].ToString();
 led3.text = show[2].ToString();
 led4.text = show[3].ToString();
 }

所以你实际上完成了

整个过程只需要四行代码。呼。

最后!您只想在四个" LED显示屏中显示信息"

最后,只需更新LED显示屏。

你真的需要用 UnityEvent 来做这件事,这让它非常容易。 (Tutorial here.)但是它一下子太多了,所以只需制作一个非常简单的函数......

public void UserClickedButtonNumbered(int digitNumber)
    {
    pin = FourOnly( pin + digitNumber );
    FixLEDs();
    if ( pin == "1313" ) Debug.Log("code unlocked!");
    }

很容易就像馅饼一样。所以每次用户触摸任何东西时都要调用它,

这是最终的完整代码:

fs.readdir

你已经完成了。去喝酒。

答案 1 :(得分:1)

我不会在这里发布实际代码,但更多的是为您分配。你应该真正研究多态和状态机。这是我最喜欢的多态性视频Google IO Talk之一。这是关于如何从代码中删除if语句和case语句的一些很好的指针。我没有状态机的视频,但基本上对于你的例子,你可能想要一个有7种状态:Start,Key1,Key2,Key3,Key4,Error,Success。现在您可以使用一些代码来收集输入并将其传递给状态机StateMachine.NextState(输入)。然后,您的状态机可以根据输入跳转到下一个状态。您可以让每个“状态”成为视频解释的对象,并且状态将负责执行它自己的逻辑。您应该能够使用no if语句或case语句重写您的问题。请发布您的解决方案。我很乐意看到它。

请注意,如果您使用此功能,将更改您的状态以接受6位数代码或10位数代码或字母数字代码。这就是多态性如此之大的原因。

答案 2 :(得分:0)

我会像这样清理它

if (digit1Entered == false) {
    digit1 = 1;
    displaycode.text = 
    print("First digit entered");
    digit1entered = true;
}
else if (digit2Entered == false) {
    digit2 = 1;
    digit2entered = true;
    displaycode.text = dispString;
    print("2nd digit entered");
}
else if (digit3Entered == false) {
    digit3 = 1;
    digit3entered = true;
    displaycode.text = dispString;
    print("3rd digit entered");
}
else if (digit4Entered == false) {
    digit4 = 1;
    digit4entered = true;
    displaycode.text = dispString;
    print("4th digit entered");
}

根据您的代码的性质以及我所看到的,如果条件无论如何都不应该达到多重。如果您正确设置了真/假条件(),则仅评估相应的if语句

编辑:解决方案二

这个想法需要一些重构,但它将是一个更“可扩展”的解决方案

将每个按钮附加一个调用方法的OnClick事件。然后,该方法将调用附加到主游戏对象的集中管理器。当您拨打电话时,您将传递按下的值和相关图像(,如果需要

GameManagerThingy {
    public int ReqEntries {get;set;}
    private string curSelectedString = "";
    private image[] selectedImages;

    public void AddNumber(string numVal, image img) {
        //Insert image and display it on keypad
        //curSelectedString += numVal

        if (ReqEntries == curSelectedString.length-1) 
            //This means enough buttons have been pressed and whatever
            //Evaluation logic you have for entering correct #'s is here
        else
            //The game would continue
    }
}

ButtonClickScript {
     public image buttonImage {get;set;}
     public string buttonValue {get;set;}

     //Tie an onclick event to your game object for when it is clicked
     public void OnClickFunction() {
         GameObject.FindWithTag("manager").GetComponent<SomeScript>().AddNumber(buttonValue, buttonImage);

     }
}

答案 3 :(得分:0)

使用当前数字指针代替布尔标志并在数组中存储数字 应该从每个按键处理程序调用函数KeyPressed,并使用适当的键值作为参数。

    int currentDigit = 0;
    char[] digits = new char[4];

    public void KeyPressed(char keyDigit)
    {
        if (currentDigit==digits.Length-1)
        {
            return; // all digits entered
        }

        digits[currentDigit] = keyDigit;

        displaycode.text = string.Empty;
        for (int i = 0; i < digits.Length; ++i)
        {
            displaycode.text += digits[i];
        }

        switch(currentDigit)
        {
            case 0:
                print("First digit entered");
                break;
            case 1:
                print("2nd digit entered");
                break;
            // etc
        }

        ++currentDigit;
    }