2016-12-30 71 views
1

所以我正在寫一個基本的MasterMind遊戲,它大多是功能性的。然而,它的表現奇怪的行爲,我不確定爲什麼。爲什麼我的類變量在一個不相關的方法運行後重寫自己?

這個想法是什麼定義了一個代碼,它的行爲是一個文件,遊戲是另一個文件,Main創建一個新遊戲並開始播放。當我初始化遊戲時,計算機按預期創建一個新的隨機字符串4(「密碼」);但是一旦我得到了用戶猜測的輸入,它似乎就會將密碼重寫爲我輸入的內容。此外,我的評估匹配方法根本不起作用,但考慮到密碼不斷變化意味着它沒有被設置爲開頭,我不確定原因。

以下全部三個類。爲什麼我的遊戲中的類變量沒有正確設置並且無法通過其他方法訪問?

Main.java

class Main { 
    public static void main(String[] args) { 
    Game newGame = new Game(); 
    newGame.play(); 
    } 
} 

Code.java

import java.util.Random; 
import java.util.HashMap; 
import java.util.Collection; 
import java.util.ArrayList; 
import java.util.Set; 

import java.lang.Math; 
import java.lang.StringBuilder; 

class Code { 
    private static HashMap<String,String> PEGS; 
    private static ArrayList<String> pegStrings; 
    protected static String secretCodeString; 


    public static void main(String[] args) { 

    } 

    public Code(String input){ 
    this.secretCodeString = input; 
    } 

    public Code(){ 
    randomize(); 
    } 


    //literally just creates the peghash 
    public static void setPegs(){ 
    PEGS = new HashMap<String,String>(); 

    PEGS.put("C","c"); 
    PEGS.put("Y","y"); 
    PEGS.put("R","r"); 
    PEGS.put("P","p"); 
    PEGS.put("O","o"); 
    PEGS.put("G","g"); 
    } 

    //turns the pegs ito something randomize can use 
public static ArrayList<String> makePegArray(){ 
    setPegs(); 

    pegStrings = new ArrayList<String>(); 

    Collection<String> pegValues = PEGS.values(); 
    Object[] pegObjects = pegValues.toArray(); 

     for (int i = 0; i < pegObjects.length; i++){ 
     pegStrings.add(pegObjects[i].toString()); 
     } 

    return pegStrings; 
    } 

    // sets Class Variable secretCode to a four letter combination 
    public static Code randomize(){ 
    secretCodeString = new String(); 

    Random rand = new Random(); 
    int randIndex = rand.nextInt(makePegArray().size()); 

    for (int i = 0; i < 4; i++){ 
     randIndex = rand.nextInt(makePegArray().size()); 
     secretCodeString = secretCodeString.concat(makePegArray().get(randIndex)); 
    } 

     Code secretCode = parse(secretCodeString); 
     return secretCode; 
    } 

    public static Code parse(String input) { 
    setPegs(); 
    makePegArray(); 

    String[] letters = input.split(""); 
    StringBuilder sb = new StringBuilder(); 

    for (String letter : letters) { 
     if (pegStrings.contains(letter)) { 
     sb.append(letter); 
     } else { 
     System.out.println(letter); 
     throw new RuntimeException(); 

     } 
    } 

    String pegListString = sb.toString(); 
    Code parsedCode = new Code(pegListString); 
    //System.out.println(parsedCode); 
    return parsedCode; 

    } 

    public int countExactMatches(Code guess){ 
    String guessString = guess.secretCodeString; 

    int exactMatches = 0; 

    String[] guessArray = guessString.split(""); 

    String[] winningCodeArray = (this.secretCodeString).split(""); 

    for(int i = 0; i < 4; i++){ 

     if(guessArray[i] == winningCodeArray[i]){ 
     exactMatches++; 
     } 
    } 
    return exactMatches; 
    } 

    public int countNearMatches(Code guess) { 

    String guessString= guess.secretCodeString; 

    HashMap<String,Integer> guessCount = new HashMap<String,Integer>(); 
    HashMap<String,Integer> secretCodeCount = new HashMap<String,Integer>(); 

    Set<String> codeKeys = guessCount.keySet(); 

    int matches = 0; 
    int keys = guessCount.keySet().size(); 


    String[] keyArray = new String[keys]; 



    for(int i = 0; i < guessString.length(); i++) { 
     //removes character from string 
     String codeCharacter = String.valueOf(guessString.charAt(i)); 
     String guessShort = guessString.replace(codeCharacter,""); 

     //counts instances of said character 
     int count = guessString.length() - guessShort.length(); 

     guessCount.put(codeCharacter, count); 
    } 

    for(int i = 0; i < secretCodeString.length(); i++) { 
     //removes character from string 
     String winningString = this.secretCodeString; 

     String winningCodeCharacter = String.valueOf(winningString.charAt(i)); 
     String winningCodeShort = guessString.replace(winningCodeCharacter,""); 

     //counts instances of said character 
     int count = winningString.length() - winningCodeShort.length(); 

     secretCodeCount.put(winningCodeCharacter, count); 
    } 

    for (int i = 0; i < keys; i++) { 
     codeKeys.toArray(keyArray); 
     String keyString = keyArray[i]; 

     if (secretCodeCount.containsKey(keyString)) { 
     matches += Math.min(secretCodeCount.get(keyString), guessCount.get(keyString)); 
     } 
    } 

    int nearMatches = matches - countExactMatches(guess); 

    return nearMatches; 
    } 
} 

Game.java

import java.util.Scanner; 

class Game { 

    protected static Code winningCode; 

    public static void main(String[] args){ 

    } 

    public Game(){ 
    winningCode = new Code(); 
    } 

    protected static Code getGuess() { 

    Scanner userInput = new Scanner(System.in); 

    int count = 0; 
    int maxTries = 5; 
    while(true){ 
     try { 
     String codeToParse = userInput.next(); 
     Code guess = Code.parse(codeToParse); 
     return guess; 

     } catch(RuntimeException notACode) { 
     System.out.println("That's not a valid peg. You have " + (maxTries - count) + " tries left."); 
     if (++count == maxTries) throw notACode; 
     } 
    } 


    } 

    protected static void displayMatches(Code guess){ 

    int nearMatches = winningCode.countNearMatches(guess); 
    int exactMatches = winningCode.countExactMatches(guess); 

    System.out.println("You have " + exactMatches + " exact matches and " + nearMatches + " near matches."); 
    } 

    protected static void play(){ 
    int turnCount = 0; 
    int maxTurns = 10; 

    System.out.println("Greetings. Pick your code of four from Y,O,G,P,C,R."); 

    while(true){ 
     Code guess = getGuess(); 
     displayMatches(guess); 

     if (guess == winningCode) { 
     System.out.print("You win!!"); 
     break; 
     } else if (++turnCount == maxTurns) { 
     System.out.print("You lose!!"); 
     break; 
     } 
    } 
    } 
} 
+4

爲什麼你聲明一切爲靜態?壞。 http://stackoverflow.com/questions/2671496/java-when-to-use-static-methods – OldProgrammer

+0

我是一個新的程序員,所以我可能做錯了。但是,我的許多方法彈出一個錯誤,說你不能從非靜態的上下文中調用靜態,反之亦然。我改變他們,因爲我需要停止看到錯誤 –

+2

不,不,不,不。你這樣做是因爲Main()被聲明爲靜態的。您需要在Main()中創建類(對象)的實例,然後通過該對象引用方法。在評論中閱讀鏈接。 – OldProgrammer

回答

3

在每一個猜測,你叫Code.parseCode.parse創建一個新的Codenew Code(pegListString);)並且構造函數設置了secretCodeString,因爲這是靜態的,Code的所有實例共享相同的變量。您需要避免可變成員static

另一個提示是要麼有一個方法返回一個值或mutate狀態(其輸入或其自身的實例,this),但避免兩者都做。

+0

我明白你的意思,但我有第二個構造函數,它接受輸入,並且應該將代碼的String值設置爲提供'this.secretCodeString = input'的參數。現在有沒有隨機/無參數構造函數是無效的? –

+0

我明白了,我錯過了這一點,它仍然類似於我的想法,因爲兩個構造函數都改變了共享靜態字段'secretCodeString'。 – weston

1

「爲什麼我的類變量在一個不相關的方法運行後自我重寫?」

因爲,實際上它並不無關係。將變量和方法聲明爲static所創建的「混亂」會導致代碼不同部分之間出現不必要的耦合。

很難說這裏正確的解決方案是什麼,因爲你的代碼被重寫弄得很困惑,很難辨別原始的「設計意圖」。

我的建議是重新開始。您現在應該對需要哪些功能有更清楚的瞭解。你需要做的是重做對象設計,以便每個班級都有明確的目的。 (MainGame類是有意義的,但Code似乎是一個功能和狀態混搭,沒有一致的目的。)

相關問題