【问题标题】:Check exact word in scrabble words list检查拼字游戏单词列表中的确切单词
【发布时间】:2019-12-14 17:28:18
【问题描述】:

我有一个带有验证工具的拼字游戏时钟。 如果我检查的单词在列表中,则验证单词空间会显示为绿色或红色。

问题是,如果我用sbuffer.toString().contains,写一个像ABA这样的词,虽然ABA不在列表中,但ABACABACA在列表中,单词空间看起来是绿色的列表。

我想知道如何在我的代码中实现一个条件来检查确切的完整单词。

我研究了正则表达式、边界和匹配项,但在我的代码中找不到对应的行代码。

这是我到目前为止的代码。

public class MainActivity extends AppCompatActivity {

    TextView textView;
    TextView textInV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.texto_1);
        textView.setMovementMethod(new ScrollingMovementMethod());
        textInV = findViewById(R.id.textIn);

        String data = "";
        StringBuffer sbuffer = new StringBuffer();

        InputStream is = this.getResources().openRawResource(R.raw.fruits);

        BufferedReader reader = new BufferedReader((new InputStreamReader(is)));

        if (is != null)
        {
            try
            {
                while((data =reader.readLine())!=null)
                {
                    sbuffer.append((data + "\n"));
                }

                is.close();

            }
            catch (Exception e){ e.printStackTrace();}
        }

        textView.setText(sbuffer);
    }
}

【问题讨论】:

    标签: java android


    【解决方案1】:

    字符串上的contains 方法测试目标是否包含在作为子字符串;如果ABAC 作为子字符串包含,那么ABA 也是如此,因为ABAABAC 的子字符串,因此它也是ABAC 是其子字符串的任何字符串的子字符串。因此,String.contains 方法在逻辑上不可能为 ABAC 返回 true 和为 ABA 返回 false

    您想测试目标是否是字符串集合的元素之一,因此您应该在字符串集合上使用contains,而不是在字符串上。最佳选择是HashSet,因为它平均在 O(1) 时间内执行成员资格测试。

    > import java.util.*;
    > Set<String> allowed = new HashSet<>();
    > allowed.add("ABAC");
    > allowed.add("ABACA");
    > allowed.contains("ABA")
    false
    > allowed.contains("ABAC")
    true
    

    【讨论】:

    • 英语中有大约 171,000 个单词,因此虽然使用具有 O(1) 访问权限的数据结构绝对是一个好主意,但这并不是绝对必要的。
    • 这取决于您要检查多少字。如果您正在编写一个拼字游戏 AI,它试图通过尝试许多可能的选项来最大化其分数,那么 O(n) 成员资格测试可能还不够好。但不管时间复杂度如何,关键是子字符串包含在逻辑上是错误的检查。
    • 扮演魔鬼的拥护者,如果您希望在搜索时获得最佳性能(就像 AI 可能做的那样),使用树形结构会更有意义,其中每个分支都是单词中的下一个字母.
    • 是的,在拼字游戏检查单词中,有数千个单词。那么...如何在哈希集中输入 .txt 来检查单词...?
    • 您打开文件,读取单词,然后将每个单词插入 HashSet,而不是将它们写入 StringBuffer。即使你有 200,000 字,它仍然只需要几兆字节的内存。
    【解决方案2】:

    正如@Ashutosh KS 已经提到的,String.contains 在这种情况下并不是您真正需要的:您想检查两个字符串是否相同,而不是一个包含另一个。

    Java String 类包含一些方法,您可以使用这些方法比较两个字符串的内容,您可以选择相应的方法来匹配您的确切用例:

    1. contentEquals(CharSequence cs)contentEquals(StringBuffer sb) 都检查传递的字符串表示的内容是否与当前的匹配。
    2. equals(Object str)contentEquals 相似之处在于它会在两个字符串之间进行精确比较,但它也会检查以确保传递的对象实际上是一个字符串。
    3. equalsIgnoreCase(String anotherString),顾名思义,会在忽略字符串大小写的情况下进行检查。

    这些是比较原生 API 公开的两个字符串的“正确”方法,因此虽然绝对可以使用其他方法,但最好坚持使用这些方法。

    【讨论】:

      【解决方案3】:

      StringBuffercontains() 检查给定字符串是否是sbuffer 中文本的子字符串。这意味着,它将输出true,用于在“ABC”、“ABCBC”、“ZABC”中搜索“ABC”, "ZABCBC"...

      如果您想在sbuffer 中搜索完整的单词,那么您可以查找"\n" + "ABC" + "\n",因为您在向sbuffer 添加单词时添加了“\n”:sbuffer.append((data + "\n"));。但是,您还必须使用“\n”初始化sbufferStringBuffer sbuffer = new StringBuffer("\n");

      sbuffer.toString().contains("\n" + "ABC" + "\n"); // this will do the trick
      

      测试代码:

      class Main {
        public static void main(String[] args) {
          StringBuffer sbuffer = new StringBuffer("\n");
          StringBuffer sbuffer2 = new StringBuffer("\n");
      
          sbuffer.append("ABC" + "\n");
          sbuffer.append("ABCBC" + "\n");
          sbuffer.append("ZABC" + "\n");
          sbuffer.append("ZABCBC" + "\n");
      
          System.out.println("Is ABC in sbuffer = " + sbuffer.toString().contains("\n" + "ABC" + "\n"));
      
          sbuffer2.append("ABCBC" + "\n");
          sbuffer2.append("ZABC" + "\n");
          sbuffer2.append("ZABCBC" + "\n");
      
          System.out.println("Is ABC in sbuffer2 = " + sbuffer2.toString().contains("\n" + "ABC" + "\n"));
        }
      }
      

      测试输出:

      Is ABC in sbuffer = true
      Is ABC in sbuffer2 = false
      

      【讨论】:

      • 这种方式可行,但仅适用于列表的第一个单词。
      • @ddaudiosolutions 它适用于每个单词——如果它是第一个单词、中间单词或列表中的最后一个单词。你是否正确地遵循我的例子?也就是说,在初始化时将“\n”添加到 StringBuffer,在每次插入时添加“\n”,并检查“\n”+ WORD +“\n”。我刚刚测试过:repl.it/repls/FluidCraftyCells
      【解决方案4】:

      现在我有了这个,并且可以使用,但是我有一个包含单词的文件,我想将这些文件添加到字典中。

      但我不知道如何读取文件。我尝试过bufferread,但我需要try/catch,但不起作用....

      其他一些解决方案....

      谢谢

      boton2.setOnClickListener(new View.OnClickListener()
              {
      
                 String content;
                 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                 @Override
                  public void onClick(View view)
                  {
                      HashSet<String> diccionario = new HashSet<String>();
                      //Adding elements to HashSet
                      diccionario.add("CASA");
                      diccionario.add("ABAC");
      
                      if(diccionario.contains(textIn.getText().toString().toUpperCase()))
                      {
                          textIn.setBackgroundColor(Color.GREEN);
                      }
                      else
                      {
                          textIn.setBackgroundColor(Color.RED);
                      }
      
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多