我正在使用C#在命令行中制作拼字游戏。玩家必须输入一些单词,如下面的列表:
| Word | Points |
| ------ | ------ |
| some | 6 |
| first | 8 |
| potsie | 8 |
| day | 7 |
| could | 8 |
| postie | 8 |
| from | 9 |
| have | 10 |
| back | 12 |
| this | 7 |
玩家得到的字母是:
sopitez
此值为字符串。我会检查字母中是否包含字母。为此,我尝试了这段代码:
String highst = (from word
in words
where word.Contains(letters)
orderby points descending
select word).First();
但它不起作用我会怎么做。此代码不会选择任何单词。我知道原因,因为sopitez
不包含任何单词。
现在我的问题是有一种方法可以检查字符串letters
中包含的字符是否包含在字符上的字母whitout循环中。
注意:解决方案中每个字母最多只能使用一次。
如果我计算结果,则必须为potsie
或postie
。 (我必须为此编写逻辑)
P.S。:我正在玩这个游戏:www.codingame.com/ide/puzzle/scrabble
答案 0 :(得分:3)
这根本不具备高性能,但至少它会起作用。请注意,我只是为了简单而使用了字典(我也不明白为什么你会重复像“potie”这样的词,我从未玩过拼字游戏)。你可以像如果您遵循此代码,请使用元组列表
编辑:我根据OP的新评论
更改了此内容using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var letters = new HashSet<char>("sopitez");
var wordsMap = new Dictionary<string, int>()
{
{"some", 6}, {"first", 8}, {"potsie", 8}, {"postie", 8}, {"day", 7},
{"could", 8}, {"from", 9}, {"have", 10}, {"back", 12},
{"this", 7}
};
var highest = wordsMap
.Select(kvp => {
var word = kvp.Key;
var points = kvp.Value;
var matchCount = kvp.Key.Sum(c => letters.Contains(c) ? 1 : 0);
return new {
Word = word,
Points = points,
MatchCount = matchCount,
FullMatch = matchCount == word.Length,
EstimatedScore = points * matchCount /(double) word.Length // This can vary... it's just my guess for an "Estiamted score"
};
})
.OrderByDescending(x => x.FullMatch)
.ThenByDescending(x => x.EstimatedScore);
foreach (var anon in highest)
{
Console.WriteLine("{0}", anon);
}
}
}
答案 1 :(得分:1)
这里的问题是Contains
检查一个字符串是否包含另一个字符串;它不会检查它是否包含所有这些字符。 您需要使用 HashSet<char>
替换字典中的每个字符串,并执行IsSubset
或IsSuperset
等集合比较,以确定字母是否匹配。
以下是您正在做的事情:
string a= "Hello";
string b= "elHlo";
bool doesContain = b.Contains(a); //This returns false
以下是您需要做的事情:
var setA = new HashSet<char>(a);
var setB = new HashSet<char>(b);
bool isSubset = a.IsSubsetOf(b); //This returns true
击> <击>的更新强>
实际上,这是错误的,因为sets删除了重复的元素。但基本上你是在滥用Contains
。你需要一些更复杂的序列比较,可以允许重复的字母。
<强> UPDATE2 强> 你需要这个用于单词/字母比较:
//Compares counts of each letter in word and tiles
bool WordCanBeMadeFromLetters(string word, string tileLetters) {
var tileLetterCounts = GetLetterCounts(tileLetters);
var wordLetterCounts = GetLetterCounts(word);
return wordLetterCounts.All(letter =>
tileLetterCounts.ContainsKey(letter.Key)
&& tileLetterCounts[letter.Key] >= letter.Value);
}
//Gets dictionary of letter/# of letter in word
Dictionary<char, int> GetLetterCounts(string word){
return word
.GroupBy(c => c)
.ToDictionary(
grp => grp.Key,
grp => grp.Count());
}
所以你原来的例子看起来像这样:
String highst = (from word
in words
where WordCanBeMadeFromLetters(word, letters)
orderby points descending
select word).First();
答案 2 :(得分:1)
由于字母可以重复,我认为你需要这样的东西(当然这不是很有效,但纯粹的LINQ):
var letters = "sopitezwss";
var words = new Dictionary<string, int>() {
{"some", 6}, {"first", 8}, {"potsie", 8}, {"day", 7},
{"could", 8}, {"from", 9}, {"have", 10}, {"back", 12},
{"this", 7}, {"postie", 8}, {"swiss", 15}
};
var highest = (from word
in words
where word.Key.GroupBy(c => c).All(c => letters.Count(l => l == c.Key) >= c.Count())
orderby word.Value descending
select word);