当前位置:  开发笔记 > 编程语言 > 正文

C#中的Konami代码

如何解决《C#中的Konami代码》经验,为你挑选了3个好方法。

我希望有一个C#应用程序实现Konami代码来显示复活节彩蛋. http://en.wikipedia.org/wiki/Konami_Code

做这个的最好方式是什么?

这是一个标准的C#windows窗体应用程序.



1> Sam Meldrum..:

在Windows窗体中,我将有一个类知道序列是什么,并保持序列中的位置状态.这样的事情应该做到这一点.

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsFormsApplication3 {
    public class KonamiSequence {

        List Keys = new List{System.Windows.Forms.Keys.Up, System.Windows.Forms.Keys.Up, 
                                       System.Windows.Forms.Keys.Down, System.Windows.Forms.Keys.Down, 
                                       System.Windows.Forms.Keys.Left, System.Windows.Forms.Keys.Right, 
                                       System.Windows.Forms.Keys.Left, System.Windows.Forms.Keys.Right, 
                                       System.Windows.Forms.Keys.B, System.Windows.Forms.Keys.A};
        private int mPosition = -1;

        public int Position {
            get { return mPosition; }
            private set { mPosition = value; }
        }

        public bool IsCompletedBy(Keys key) {

            if (Keys[Position + 1] == key) {
                // move to next
                Position++;
            }
            else if (Position == 1 && key == System.Windows.Forms.Keys.Up) {
                // stay where we are
            }
            else if (Keys[0] == key) {
                // restart at 1st
                Position = 0;
            }
            else {
                // no match in sequence
                Position = -1;
            }

            if (Position == Keys.Count - 1) {
                Position = -1;
                return true;
            }

            return false;
        }
    }
}

要使用它,您需要在表单的代码中响应密钥事件.这样的事情应该这样做:

    private KonamiSequence sequence = new KonamiSequence();

    private void Form1_KeyUp(object sender, KeyEventArgs e) {
        if (sequence.IsCompletedBy(e.KeyCode)) {
            MessageBox.Show("KONAMI!!!");
        }
    }

希望这足以满足您的需求.对于WPF,您需要的细微差别非常相似(请参阅编辑历史记录#1).

编辑:更新为winforms而不是wpf.


@James,这不是生产就绪代码 - 这不是SO的用途 - 我认为这是一个很好的起点.我不认为代码特别混乱 - 很清楚它所呈现的逻辑是做什么的.就个人而言,我觉得你很难理解.目标并不总是"整洁",但可维护性和易于理解应该是最重要的.
使用特殊情况来修复状态机似乎不是解决此问题的正确方法.每次更改"密码"时,您都需要调整硬编码的"修复".作为这个问题的答案,我提供了一种更简单,更轻量级的新解决方案.

2> James..:

正确的顺序,就像Konami本身实现它一样:

得到输入

如果输入等于代码数组索引处的字节,则增加索引

否则,明确指数

如果index大于代码长度,则代码是正确的

这是不怎么做:

累积按键缓冲区,然后进行逐字节字符串比较.充其量只是效率低下.您正在为表单上的每个按键调用字符串解析例程,并且这些例程与可以采取相同的确切效果的一些简单步骤相比是缓慢而笨重的.

一个有限状态机,如果在代码中重复序列,每次都会中断.

具有"特殊情况"硬编码的有限状态机.现在,您无法在一个地方进行修改.您必须更改代码字符串并添加新代码以处理不适当实现的状态机.

实例化一个List对象以保存简单的字符列表.

参与String对象.

那么,这是如何做到的:

using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public class KonamiSequence
    {
        readonly Keys[] _code = { Keys.Up, Keys.Up, Keys.Down, Keys.Down, Keys.Left, Keys.Right, Keys.Left, Keys.Right, Keys.B, Keys.A };

        private int _offset;
        private readonly int _length, _target;

        public KonamiSequence()
        {
            _length = _code.Length - 1;
            _target = _code.Length;
        }

        public bool IsCompletedBy(Keys key)
        {
            _offset %= _target;

            if (key == _code[_offset]) _offset++;
            else if (key == _code[0])  _offset = 2;  // repeat index

            return _offset > _length;
        }
    }
}

现在,它很快,不会打扰字符串或实例化任何bulker而不是数组,并且对代码的更改就像修改数组一样简单.

构造函数中的字段初始化取代了与所需值等效的硬编码常量.如果我们使用常量,我们可以将代码缩短6个左右的"行".这有点浪费,但允许类尽可能轻松地适应新代码 - 您只需要更改数组列表.另外,所有"批量"都是在实例化时处理的,因此它不会影响我们的目标方法的效率.

乍一看,这段代码可以更简单.只要您在正确的代码输入上重置值,就不需要模数.

核心逻辑实际上可以组成一行代码:

_sequenceIndex =  (_code[_sequenceIndex] == key) ? ++_sequenceIndex : 0;



3> user54650..:

在正常处理它们之前,将按键捕获到13(或代码的任何子集,因为您可能不想包含START键) - 字符列表/数组/字符串/等等.每次添加一个键时,如果(并且仅当)它是该系列中的最后一个键,则将缓冲区与正确的konami代码匹配.

我的建议是,如果他们按箭头键,将其映射到合理的字母......然后映射B和A,只需清除任何其他按键的缓冲区.

然后,将缓冲区设为字符串,将其与"UUDDLRLRBABA"进行比较

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有