我正在学习Java,并计划很快参加OCA SE8考试。我制作了一个相当原始的Hangman游戏来帮助学习。如果可能的话,我希望能得到一些反馈。如果没有达到所需的标准(命名约定、某些方法的速度等),我很想知道。
我不满意的两件事是:
package hangman2;
import java.util.Arrays;
import java.util.Scanner;
public class Hangman2 {
static int guessesRemaining;
static String stringWord;
static char[] charWord;
public static void playHangman() {
System.out.print("Welcome to Hangman! ");
System.out.println("Player 1: Enter a word");
Scanner scan = new Scanner(System.in);
stringWord = scan.nextLine();
//Loop to get user to enter in letters only
while (stringWord.matches(".*[^a-z].*")) {
System.out.println("Please enter letters only, try again:");
stringWord = scan.nextLine();
}
System.out.println("The length of the word is " + stringWord.length()); //Print out length of word.
stringWord = stringWord.toLowerCase();
int lettersRemaining = stringWord.length(); //Letters to be gussed is equal to the word length.
//Create a new char array equal to the word length, add * to each index.
charWord = new char[stringWord.length()];
for (int i = 0; i < stringWord.length(); i++) {
charWord[i] = ('\u002A');
}
int livesRemaining = 7; // 7 lives remaining!
MainLoop:
/*
Main loop, gets user input using Scanner, ensures it is only a letter (not a number or special character)
Converts string to char, uses the guess method which compares the secret word to the character entered and
returns true if it found it, false if it didn't.
If found, letters remaining - 1, if the char array contains any asterisks, envoke the gameWon() method.
If not found, lives remaining - 1, if no more lives, envoke the gameLost() method.
*/
while (livesRemaining > 0) {
System.out.println("Player 2: Guess a Letter:!");
char guessLetter;
String b = scan.next();
while (b.matches(".*[^a-z].*")) {
System.out.println("Please enter letters only, try again:");
b = scan.next();
}
guessLetter = b.toLowerCase().charAt(0);
String a = new Hangman2().print(guessLetter);
if (guess(guessLetter, stringWord)) {
lettersRemaining--;
if (!a.contains("*")) {
gameWon();
break;
}
System.out.println("Well done, you guessed correctly! You have " + lettersRemaining + " letters remaining");
} else {
livesRemaining--;
if (livesRemaining == 0) {
gameLost();
}
System.out.println("Too bad, you guessed incorrectly, you have " + livesRemaining + " lives remaining");
}
}
}
public String print(char c) {
//Prints asterisks and replaces characters that have been guessed.
String misses;
char[] guess = stringWord.toCharArray();
for (int i = 0; i < charWord.length; i++) {
if (guess[i] == c) {
charWord[i] = c;
}
}
misses = Arrays.toString(charWord);
System.out.print(misses + " ");
return misses;
}
public static boolean guess(char c, String s) {
//Evaluates the chracter entered and compares it to the word, returns a boolean (correct or incorrect).
boolean result = false;
char[] a = s.toCharArray();
for (int i = 0; i < s.length(); i++) {
if (a[i] == c) {
result = true;
}
}
return result;
}
public static void gameWon() {
char yesno;
boolean enter;
System.out.print("Congratulations, you won!");
Scanner input = new Scanner(System.in);
System.out.println(" Would you like to play again? Y / N");
do {
yesno = input.next().toUpperCase().charAt(0);
switch (yesno) {
case 'Y':
playHangman();
case 'N':
System.exit(0);
default:
System.out.println("Please enter Y / N");
enter = false;
break;
}
} while (!enter);
}
public static void gameLost() {
char yesno;
boolean enter;
System.out.print("Too bad, you lost...");
Scanner input = new Scanner(System.in);
System.out.println(" Would you like to play again? Y / N");
do {
yesno = input.next().toUpperCase().charAt(0);
switch (yesno) {
case 'Y':
playHangman();
case 'N':
System.exit(0);
default:
System.out.println("Please enter Y / N");
enter = false;
break;
}
} while (!enter);
}
public static void main(String[] args) {
playHangman();
}
}发布于 2018-02-19 01:41:47
对象
静态int guessesRemaining;静态字符串stringWord;静态char[] charWord;
你要把整个类变成一个假的对象。
private String stringWord;
private char[] charWord;这就是真实对象字段的外观。
除非您有特定的原因(例如,您希望某个字段出于某种特定原因在外部可见),否则您应该将对象字段声明为private可见性。避免默认(包私有),除非您有一些理由使用它。而不是一个“我可能想.在未来”的理由。这是在代码中实际实现的原因。在这种情况下,整个程序是一个类。任何可见性都可以,但在大多数情况下,private是首选。
同样,我并不是说除了对对象字段(存储在对象中的数据)使用private以外,没有理由使用可见性。我是说你在这里没有这样的理由。我还说,可能总是让字段private和修复罕见的异常比在一开始就尝试寻找其他任何东西的原因要容易一些。如果这一政策开始令人恼火,那就重新考虑一下。但在早期阶段,它很少会超出设置者和获取者的范围。
您不想使用类作为假对象的原因是,它阻止您创建类的多个实例。你不能这样一次玩两个汉曼游戏。
你需要一个构造函数。
Hangman2(String word) {
stringWord = word;
charWord = new char[word.length()];
Arrays.fill(charWord, '*');
}这也消除了用星号手动填充字符数组的需要。相反,我们使用内置的Arrays.fill。
虽然有些方法不需要是static,但main需要。所以重写它就像
public static void main(String[] args) {
do {
Hangman2 game = new Hangman2(inputWordToGuess());
game.play();
} while (isReplayDesired());
}注意,getWordToGuess和isReplayDesired都是static方法。与此同时,play不是。
static当使用static确实有意义时,您在任何地方都使用相同的东西。例如,有一个static Scanner是有意义的。
public static Scanner input = new Scanner(System.in);这也可以是public,所以其他类不必自己制作扫描器。
在您的原始版本中,您将在任何碰巧需要获取用户输入的方法中构建一个扫描器对象。这样,您就可以为整个程序构建一个持久的程序。
您的gameWon和gameLost方法几乎是相同的。所以我用
public static boolean isReplayDesired() {
while (true) {
System.out.println(" Would you like to play again? Y / N");
switch (input.next().toUpperCase().charAt(0)) {
case 'Y':
return true;
case 'N':
return false;
default:
System.out.println("Please enter Y / N");
}
}
}这就去掉了enter布尔值。所以代码更少了。
您可以使用中间的yesno变量,但这是不必要的。
通过返回布尔值,我们可以简化这里和调用方中的代码。
可以使用原始代码使用递归调用来溢出堆栈(尽管有些困难)。现在不是了,没有递归调用。
当break语句是switch语句中的最后一个子句时,我从不将它放入默认子句中。这没必要。我总是在我可以的时候把它放在最后,这几乎一直都是。我确实把它放在最后一个非缺省子句中,尽管它仍然是不必要的。
您的原始playHangman方法尝试做几件事。我听说了这个词。现在我们有两种更简单的方法。这使得事情变得更加灵活。与从用户输入中获取单词不同,我完全可以切换到从文件中读取单词,而无需更改play方法。我只是停止使用inputWordToGuess。
如果我更改名称,我可以将inputWordToGuess重用到其他地方。
发布于 2018-02-19 03:30:05
public class Hangman2 {HangMan2是个坏名字。不要将数字作为类名添加。如果不打算覆盖类,则向类添加final修饰符。
static int guessesRemaining;
static String stringWord;
static char[] charWord;您可以用纯面向对象的方式编写代码,因此您不需要statics。此外,您还可以添加一个private修饰符。
public static void playHangman() {不需要static。
//Loop to get user to enter in letters only
while (stringWord.matches(".*[^a-z].*")) {
System.out.println("Please enter letters only, try again:");
stringWord = scan.nextLine();
}这可能是另一种方法。Regex可以声明为字符串常量。你可能不想要无限的尝试。
stringWord = stringWord.toLowerCase();为什么不叫它word呢?
while (livesRemaining > 0) {显然需要有自己的方法。
while (b.matches(".*[^a-z].*")) {回到我的常量点。如果string是null,你是否确保它不会导致NPE?
String a = new Hangman2().print(guessLetter);print方法应该是void,否则更改名称。a是个坏名字。
if (!a.contains("*")) {难道不能用letterRemaining == 0来代替吗?
System.out.print(misses + " ");假设你可以一次打印一个字符串?
char[] a = s.toCharArray();你可以选择String.charAt(i)。
https://codereview.stackexchange.com/questions/187820
复制相似问题