为了一次假面试,我决定给Hangman写信。我要问的第一个问题是,当在面试中检查某人的代码时,写一些简短的、能完成任务的东西,还是用依赖注入和小的OOP模块来写东西,会更重要吗?
附件是我想出的一个小例子,花了30分钟左右。如果您正在检查这段代码,您会认为这是可以接受的,还是希望在一小时内,有人能生产出更多的技能呢?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Hangman
{
public static class Program
{
private const string WordToGuess = "HANGMAN";
private static readonly HashSet<char> LettersToGuess = new(WordToGuess.ToCharArray());
private const int MaxLives = 5;
private static readonly HashSet<char> _guessedLetters = new();
private static void Main(string[] _)
{
while (!WonGame && LivesRemaining > 0)
{
var displayStringBuilder = new StringBuilder();
displayStringBuilder
.AppendLine(WordDisplay)
.Append("Letters Guessed: ").AppendLine(GuessedLettersDisplay)
.Append("Lives Remaining: ").Append(LivesRemaining)
.AppendLine().AppendLine()
.Append("Enter a guess: ");
Console.Clear();
Console.Write(displayStringBuilder.ToString());
var guess = Console.ReadLine();
if (!ValidGuess(guess)) continue;
_guessedLetters.Add(char.ToUpper(guess[0]));
}
var endingStringBuilder = new StringBuilder();
endingStringBuilder
.Append("The word was: ").AppendLine(WordToGuess)
.AppendLine(WonGame ? "You Won!" : "You Lost!");
Console.Clear();
Console.WriteLine(endingStringBuilder.ToString());
}
private static int LivesRemaining => MaxLives - _guessedLetters.Except(LettersToGuess).Count();
private static bool WonGame => !LettersToGuess.Except(_guessedLetters).Any();
private static string WordDisplay => string.Join(' ', WordToGuess.ToCharArray().Select(x => _guessedLetters.Contains(x) ? x : '_'));
private static string GuessedLettersDisplay => string.Join(',', _guessedLetters);
private static bool ValidGuess(string guess)
{
if (guess.Length != 1) return false;
return char.IsLetter(guess[0]);
}
}
}发布于 2021-09-16 10:11:41
以下是我的观察结果
ValidGuessValidateGuess或IsGuessValidprivate static bool IsGuessValid(string guess) => guess.Length == 1 ? char.IsLetter(guess[0]) : false;LettersToGuessHashSet不是不变的。您不能替换整个集合,但可以替换集合的任何成员。System.Collections.Immutable命名空间提供了几种非常有用的结构和扩展方法:private static readonly ImmutableArray<char> WordToGuess = "HANGMAN".ToImmutableArray();
private static readonly ImmutableHashSet<char> LettersToGuess = WordToGuess.ToImmutableHashSet();WordToGuessconst WordDisplay中,您正在一次又一次地将string转换为char[]endingStringBuilder中,您可以简单地将ImmutableArray<char>转换为string,如下所示:.Append("The word was: ").AppendLine(new string(WordToGuess.AsSpan()))displayStringBuilder,endingStringBuilderStringBuildergameStatusInformationBuilder或者仅仅是statusInformationBuildergameSummaryInformationBuilder或者仅仅是summaryInformationBuilderMainMain方法可以编写以几种不同的方式args,那么只需去掉参数即可。static void Main()
{
...
}MaxLives,LivesRemainingMaxLives和RemainingLivesif (!IsGuessValid(guess)) continue;continue,可能会帮助玩家修复他/她以前的问题。发布于 2021-09-16 21:23:31
..。才能创造出更多的技能?
要求+设计+代码=艺术。事情就是这样。
不执行汉曼游戏。只有一个硬编码的单词--通过设计--只有一种使用丢弃的东西,而不是游戏。
手动替换猜测词需要每次重写程序。“不,只需更改WordToGuess值”。我要对版本控制软件说这句话;您从来没有必要以交付和维护工作软件为生,是吗?任何更改,无论多么琐碎,都需要回顾、测试、集成、部署、客户需求等等。因此,从“刽子手”改为"EXEMPLOYEE“绝不能像”重写“代码那么重要。
依赖注入本身并不是设计目标。这是经过深思熟虑的模块化设计的结果,如果不是明确的面向对象的话。模块本身并不是一个设计目标。总体目标是程序功能的分离/独立。我们称这为单一责任原则..。
Hangman算法没有直接输出显示的功能。即使在Hangman游戏中,对于细微的功能责任也可能有不同的看法,但这不是这样的。提取控制台显示代码将产生大量有目的的"DI“和”小模块“。不要强行把热门词宾果BS写进代码中。可能会增加复杂性,却没有任何合理的好处。
我不明白为什么static类。Program是Hangman类,为什么要将它命名为Program并使其成为静态类?包装在Hangman命名空间中的坏类名仍然是错误的类名。阅读这个线程:为什么类程序被声明为静态的?。在所选的答案中引用:
Program的S职责是为应用程序提供一个入口点,所以它不应该再做任何事情
这是一个小程序,但有抽象概念和代码,封装细节等的空间。
如果我做了任何错误的假设或代码误读,我可以把它放在编码器上。结构、有意义的名称、抽象、封装、实心、成语、判断等使即使是“简单”的程序也不平凡。
提取一种方法 -对主游戏循环来说太详细了
var displayStringBuilder = new StringBuilder();
displayStringBuilder
.AppendLine(WordDisplay)
.Append("Letters Guessed: ").AppendLine(GuessedLettersDisplay)
.Append("Lives Remaining: ").Append(LivesRemaining)
.AppendLine().AppendLine()
.Append("Enter a guess: ");
Console.Clear();
Console.Write(displayStringBuilder.ToString());"CorrectGuess“是正确的。“有效”在用户交互中具有更广泛的含义。字母表中的字母是有效的输入,但只有猜字的字母是正确的.
private static bool ValidGuess(string guess)对无效输入的保护太弱了
private static bool ValidGuess(string guess)
{
if (guess.Length != 1) return false;
return char.IsLetter(guess[0]);
}
// suggestions:
private static bool ValidGuess(string guess)
{
if (string.IsNullOrWhitespace(guess)) return false;
if (guess.Length != 1) return false;
// IsLetter can throw NullArgumentException, but the
// above guards for that.
return char.IsLetter(guess[0]);
}ValidGuess只是这样做的,而不是寻找一个正确的WordToGuess字母。单一责任的极好例子。
所以线程:isNullOrWhitespace
我开始欣赏矮个子ifs时的单线和没有支撑。但是,无论多长时间,始终在控制块(而不仅仅是"if")上方和下面留空格。一个大爆炸的巴克可读性提示!
过度工程?我不明白HashSet的必要性。另外,string是一个char数组。换句话说,您可以直接forEach(letter in myString)
private static readonly HashSet<char> LettersToGuess = new(WordToGuess.ToCharArray());游戏主回路应读为“高水平”,并准确地表达游戏条件。
while (!WonGame && LivesRemaining > 0)。
表达“我还活着吗?”,而不是“生命是否还在零?”。我不在乎有多少人,如果有的话。代码越早从低水平的DNA比特中抽象出来,就越好。
while (!WonGame && StillAlive)
protected bool StillAlive { get {return LivesRemaining > 0; }}。
!WonGame在这里的意思是我们猜错了这个词。
while ( WrongGuess && StillAlive )
protected bool WrongGuess { get { ... }}现在我们明白了继续比赛的条件。而不需要读取底层代码。
。
Hangman宇宙中的总体“坚持”概念是什么?
while (NotHung) { ... }
protected bool NotHung { get { return WrongGuess && StillAlive; }}我们可以争论一整天的财产的负面名称。这是我们要找的主意。
https://codereview.stackexchange.com/questions/268028
复制相似问题