C# 实现pin键盘,简化代码?

C# 实现pin键盘,简化代码?,c#,unity3d,C#,Unity3d,我正在游戏中创建一个键盘。我创建的游戏对象有10个按钮:0-9。玩家必须输入4位代码才能开门。一旦播放机输入第一个数字,它就会显示在键盘屏幕上 我有所有的基本代码工作,但我相信我做了一个非常低效的方式。现在,我已将以下功能附加到我的一个键上,实际上是数字1键: public void Key1() { if (digit1entered == false) { digit1 = 1; displaycode.text = digit1.ToSt

我正在游戏中创建一个键盘。我创建的游戏对象有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个函数,除了它们输入的值之外,它们都是相似的。这是糟糕的编程,那么如何避免呢?哦,如果上面的编程一开始就很糟糕,那么欢迎提供所有提示-

我会像这样把它清理干净

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");
}
public void UserClickedButtonNumbered(int digitNumber)
    {
    Debug.Log("that button name is " +digitNumber);
    }
根据代码的性质以及我所看到的情况,无论如何它都不应该碰到多个if条件。如果您正确设置了真/假条件,那么只有适当的If语句才会被计算

编辑:解决方案二

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

将调用方法的OnClick事件附加到每个按钮。然后,该方法将调用连接到主游戏对象的集中式管理器。调用时,如果需要,您将传递按下的值和关联的图像


我会像这样把它清理干净

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");
}
public void UserClickedButtonNumbered(int digitNumber)
    {
    Debug.Log("that button name is " +digitNumber);
    }
根据代码的性质以及我所看到的情况,无论如何它都不应该碰到多个if条件。如果您正确设置了真/假条件,那么只有适当的If语句才会被计算

编辑:解决方案二

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

将调用方法的OnClick事件附加到每个按钮。然后,该方法将调用连接到主游戏对象的集中式管理器。调用时,如果需要,您将传递按下的值和关联的图像


使用当前数字指针而不是布尔标志,并在数组中存储数字。 应使用适当的键值作为参数,从每个按键处理程序调用Function 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;
    }

使用当前数字指针而不是布尔标志,并在数组中存储数字。 应使用适当的键值作为参数,从每个按键处理程序调用Function 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;
    }

要做好这件事非常困难。你选择了一个真正的挑战

您的第一个问题是,您必须集中进来的信息流。让我们这样做吧。 有这样一个功能

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");
}
public void UserClickedButtonNumbered(int digitNumber)
    {
    Debug.Log("that button name is " +digitNumber);
    }
在脚本Complex.cs中对某个对象说

给我你的十个钮扣。在“检查器”中,拖动以连接

请注意,您实际上可以键入一个数字-我键入了3

实际上,你可以在十个按钮上设置值0到9

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

你真的联系上了

所有按钮都指向相同的脚本和功能。 一旦你有工作,让我们知道,我们会找出下一部分

接下来需要一个函数,该函数不允许字符串超过四个字符。如果你在最后加一个,它会把第一个砍掉

重要提示:实际上,您可以通过一个扩展来实现这一点,它是Unity编程的绝对核心。但是一下子解释太多了。当你有时间工作的时候

大致上你的函数是

   private string FourOnly(string s)
    {
    while (s.Length > 4 ) s = s.Substring(1);
    return s;
    }
所以现在你可以这样做了

[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!");
    }
你真的完成了

整个过程只需要大约四行代码。呸。 终于!您只需要在四个LED显示屏上显示信息

最后,只需更新LED显示屏。 你真的需要用UnityEvent来做这件事,这使它变得非常简单。但是一下子就太多了,所以只需要做一个非常简单的函数,像这样

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();
 }
容易极了。因此,只要在用户每次触摸任何东西时调用

以下是最终的完整代码:
你完了。去喝酒。

要做好这件事非常困难。你选择了一个真正的挑战

您的第一个问题是,您必须集中进来的信息流。让我们这样做吧。 有这样一个功能

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");
}
public void UserClickedButtonNumbered(int digitNumber)
    {
    Debug.Log("that button name is " +digitNumber);
    }
在脚本Complex.cs中对某个对象说

给我你的十个钮扣。在“检查器”中,拖动以连接

请注意,您实际上可以键入一个数字-我键入了3

实际上,你可以在十个按钮上设置值0到9

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

你真的联系上了

所有按钮都指向相同的脚本和功能。 一旦你有工作,让我们知道,我们会找出下一部分

接下来需要一个函数,该函数不允许字符串超过四个字符。如果你在最后加一个,它会把第一个砍掉

重要提示:实际上,您可以通过一个扩展来实现这一点,它是Unity编程的绝对核心。但是一下子解释太多了。当你有时间工作的时候

大致上你的函数是

   private string FourOnly(string s)
    {
    while (s.Length > 4 ) s = s.Substring(1);
    return s;
    }
所以现在你可以这样做了

[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!");
    }
你真的完成了

整个过程只需要大约四行代码。呸。 终于!您只需要在四个LED显示屏上显示信息

最后,只需更新LED显示屏。 你真的需要用UnityEvent来做这件事,这使它变得非常简单。但是一下子就太多了,所以只需要做一个非常简单的函数,像这样

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();
 }
容易极了。因此,只要在用户每次触摸任何东西时调用

以下是最终的完整代码:
你完了。去喝酒。

我不会在这里发布实际的代码,但更多的是给你的作业。您应该真正研究多态性和状态机。这是我最喜欢的关于多态性的视频之一。在本文中,有一些关于如何从代码中删除if语句和case语句的很好的提示。我没有状态机的视频,但基本上对于您的示例,您可能需要一个具有7种状态的视频:开始、按键1、按键2、按键3、按键4、错误、成功。现在您可以有一些代码来收集输入并将其传递给状态机StateMachine.NextStateinput。然后,您的状态机可以跳转到下一个状态应该基于输入的内容。你可以让每一个状态都像视频中解释的那样是一个对象,并且该状态将负责执行它自己的逻辑。您应该能够使用no-if语句或case语句重写问题。请发布您的解决方案。我很想看看


请注意,如果你能做到这一点,那么改变你的状态以接受6位代码、10位代码或字母数字代码是多么容易。这就是多态性如此伟大的原因

我不会在这里发布实际代码,但更多的是为您分配的任务。您应该真正研究多态性和状态机。这是我最喜欢的关于多态性的视频之一。在本文中,有一些关于如何从代码中删除if语句和case语句的很好的提示。我没有状态机的视频,但基本上对于您的示例,您可能需要一个具有7种状态的视频:开始、按键1、按键2、按键3、按键4、错误、成功。现在您可以有一些代码来收集输入并将其传递给状态机StateMachine.NextStateinput。然后,您的状态机可以跳转到下一个状态应该基于输入的内容。你可以让每一个状态都像视频中解释的那样是一个对象,并且该状态将负责执行它自己的逻辑。您应该能够使用no-if语句或case语句重写问题。请发布您的解决方案。我很想看看


请注意,如果你能做到这一点,那么改变你的状态以接受6位代码、10位代码或字母数字代码是多么容易。这就是多态性如此伟大的原因

您正在使用.UI,对吗?要做到这一点非常困难。我会给你一些提示。我认为最好是让玩家键入一个组合,然后检查计数是否正确,然后在该点检查组合。就像Joe Blow对实际按钮按下所做的那样使用一些功能。Gun——正如ManO所解释的,基本上你只是把它输入到一个状态机中。从概念上讲,这就是这里的总体答案。带FIFO的字符串可以完美地执行这个角色,以满足如此琐碎的需求。您使用的是.UI,对吗?要做到这一点非常困难。我会给你一些提示。我认为最好是让玩家键入一个组合,然后检查计数是否正确,然后在该点检查组合。就像Joe Blow对实际按钮按下所做的那样使用一些功能。Gun——正如ManO所解释的,基本上你只是把它输入到一个状态机中。从概念上讲,这就是这里的总体答案。带FIFO的字符串可以完美地执行这个角色,以满足这样一个琐碎的需求。如果需要,请不要使用其他字符串。而且,你真的做的和这完全不同。你从来没有用过else if吗?这可以被设计成一个切换语句,但我认为这是有效的。@JoeBlow想详细说明一下为什么你如此坚决地反对else if?这很了不起,我解释了一行代码解决方案,人们仍然在研究多行和多行解决方案:-我没有看到你的解决方案,但是我的第二个和你的非常相似。我试图保持OP最初在我的回答中所表达的精神。你还没有解释你对其他假设的蔑视?我有点好奇为什么他们这么可怕。谢谢切勿使用其他if-ev

呃。而且,你真的做的和这完全不同。你从来没有用过else if吗?这可以被设计成一个切换语句,但我认为这是有效的。@JoeBlow想详细说明一下为什么你如此坚决地反对else if?这很了不起,我解释了一行代码解决方案,人们仍然在研究多行和多行解决方案:-我没有看到你的解决方案,但是我的第二个和你的非常相似。我试图保持OP最初在我的回答中所表达的精神。你还没有解释你对其他假设的蔑视?我有点好奇为什么他们这么可怕。谢谢你在正确的轨道上,但它必须比这更模块化。我只是展示了一个想法,它可能会帮助你完成你的任务。我很感激-但n unity特别容易做到这一点你在正确的轨道上,但它必须比这更模块化。我只是展示了一个想法,它可能会帮助你完成你的任务。我很感激-但特别是n unity,它非常容易做到我输入了3:P Hanks Joe!我会告诉你事情的进展。事实上,我正在尝试使用一个处理所有数字的函数。我正在努力实施你的上述建议。我正在将每个按钮的int值传递给函数,这使事情变得更容易…工作起来很有魅力!在键盘上显示3d文本,但我自己解决了这个问题。谢谢你,乔!在我的游戏中,我会把你的照片贴在键盘旁边的墙上!我输入了3:p汉克斯乔!我会告诉你事情的进展。事实上,我正在尝试使用一个处理所有数字的函数。我正在努力实施你的上述建议。我正在将每个按钮的int值传递给函数,这使事情变得更容易…工作起来很有魅力!在键盘上显示3d文本,但我自己解决了这个问题。谢谢你,乔!在我的游戏中,我会把你的照片贴在键盘旁边的墙上!对于中级程序员来说,查看状态机是一件好事。然而,请注意,这是一个统一的问题,特别是一个绝对的初学者。作为一个ECS系统,Unity为您做了大量的工作。你不会用Mathematica写乘法函数。事实上,在Unity中使用固有的值传递UI函数,只需一行代码——这就是OP在这里需要学习的内容。很烦人的是,统一问题没有标记得更清楚。是的,我没有注意到标签。我的过滤器设置为C。我不知道unity免费提供了什么,但不管怎样,一堆if语句和case语句都可以通过多态性消除。很好,很好。事实上,你会看到我的答案,正是你所推荐的。以非常经济的方式实施:投票支持你的答案。我在这里的回答实际上是对OP的最后一句话的回应,所有的提示都是受欢迎的:事实上,我投票支持这个答案,因为它是长期来看最好的,它有利于中级程序员查看状态机。然而,请注意,这是一个统一的问题,特别是一个绝对的初学者。作为一个ECS系统,Unity为您做了大量的工作。你不会用Mathematica写乘法函数。事实上,在Unity中使用固有的值传递UI函数,只需一行代码——这就是OP在这里需要学习的内容。很烦人的是,统一问题没有标记得更清楚。是的,我没有注意到标签。我的过滤器设置为C。我不知道unity免费提供了什么,但不管怎样,一堆if语句和case语句都可以通过多态性消除。很好,很好。事实上,你会看到我的答案,正是你所推荐的。以非常经济的方式实施:投票支持你的答案。我在这里的回答实际上是对OP的最后一句话的回应,所有的建议都是受欢迎的:事实上,我投票支持这个答案,因为从长远来看它是最好的