2013-04-27 88 views
0

游戏类:Java的文本框无限循环

import java.util.Random; 

public class Game { 
public static void main(String args[]){ 

    //----------Sets up GUI---------- 

    GUI gameGUI = new GUI(); 
    gameGUI.setVisible(true); 
    Player.setGUI(gameGUI); 


    //----------Sets initial number of marbles, computer player and human player---------- 

    Random random = new Random(); 
    int initialNum; 
    //loop makes sure initialNum of marbles is between 10 and 100 
    do{         
     initialNum = random.nextInt(100); 
    }while(initialNum < 10); 
    //*****gameGUI.manageMarbles(initialNum, true); 
    //end loop 

    Pile pile = new Pile(initialNum); 
    gameGUI.setPile(pile); 

    int compChoice = random.nextInt(2) + 1; //number index (1 or 2) representing SIMPLE_COMPUTER or SMART_COMPUTER 
    Player computer = new Player(Player.Type.values()[compChoice]); 
    Player humanPlayer = new Player(Player.Type.HUMAN); 


    //----------Game loop---------- 

    //Randomly determine first player 
    Player currentPlayer; 
    int playerIndex = random.nextInt(2); //will be used to determine next player in the loop 
    if(playerIndex == 0){ currentPlayer = computer; } 
    else { currentPlayer = humanPlayer; } 

    //Loop 
    while(pile.getNumMarbles() != 0){ 
     System.out.printf("%d marbles left.\n", pile.getNumMarbles()); 
     int removed = currentPlayer.playTurn(pile.getNumMarbles()); 
     pile.removeMarbles(removed); 

     //Determine next player 
     playerIndex = Math.abs(playerIndex - 1); //if playerIndex = 0, it becomes 1, and vice-versa 
     if(playerIndex == 0){ currentPlayer = computer; } 
     else { currentPlayer = humanPlayer; } 

    } 

    System.out.println(currentPlayer + " won"); 



} 
} 

Player类:

import java.util.Scanner; 
import java.util.Random; 
public class Player { 

    public enum Type{HUMAN, SIMPLE_COMPUTER, SMART_COMPUTER} 
    private Type type; 
    static private GUI gui; 

    public Player(Player.Type type){ 
     this.type = type; 
    } 

    public Player.Type getType(){ 
     return type; 
    } 

    public int playTurn(int pileSize){ 
      Random random = new Random(); 
      if(type == Type.HUMAN){ 

       int marbles; 
      do{ 
      marbles = gui.getMarblesToRemove(); 
      }while(marbles < 0); 
       return marbles; 

      } 

      else if(type == Type.SIMPLE_COMPUTER){ 
      if(pileSize == 1){ 
       return 1; 
       } 
      else{ 
      int remove = random.nextInt(pileSize/2) + 1; 
       if(remove == (pileSize/2) + 1){ remove -= 1; } 
       return remove; 
       } 
      } 

      else if(type == Type.SMART_COMPUTER){ 
       if(pileSize == 1){ 
       return 1; 
      } 
       else if(pileSize == 3 || pileSize == 7 || pileSize == 15 || pileSize== 31 || pileSize== 63 || pileSize <= 3){ 
       int remove = random.nextInt(pileSize/2) + 1; 
       if(remove == (pileSize/2) + 1){ remove -= 1; } 
       return remove; 
      } 
      else{ 
       for(int i=1; i<=pileSize/2; i++){ 
        int size = pileSize - i; 
       if(size == 3 || size == 7 || size == 15 || size == 31 || size == 63){ 
        return i; 
       } 
      } 
     } 
    } 
    return 0; 

    } 


public String toString(){ 
    return ""+type; 
} 

public static void setGUI(GUI guii){ 
    gui = guii; 
} 


} 

GUI类:

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JButton; 
import javax.swing.JLabel; 
import javax.swing.JTextField; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 

public class GUI extends JFrame { 

    private JPanel panel; 
    private JButton removeButton; //button to remove marbles 
    private JTextField marblesAmount; //amount of marbles to remove 
    private static final int FIELD_WIDTH = 2; 
    private JLabel marblesLabel; 
    private JLabel errorLabel; 
    private Pile pile; 
    private int marblesToRemove; 
    private ClickListener listener; 
    static final private int WIDTH = 700, HEIGHT = 600; 

    public GUI(){ 
    super.setTitle("test"); 
    super.setSize(WIDTH, HEIGHT); 
    super.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    panel = new JPanel(); 
    marblesLabel = new JLabel("How many marbles to remove?"); 
    errorLabel = new JLabel(""); 
    removeButton = new JButton("Remove"); 
    listener = new ClickListener(); 
    removeButton.addActionListener(listener); 
    marblesAmount = new JTextField(FIELD_WIDTH); 
    panel.add(removeButton); 
    panel.add(marblesLabel); 
    panel.add(marblesAmount); 
    panel.add(errorLabel); 
    super.add(panel); 
    marblesToRemove = 0; 
    } 

    public void setPile(Pile pile){ 
    this.pile = pile; 
    } 



    private class ClickListener implements ActionListener{ 

    public void actionPerformed(ActionEvent event){ 
     marblesToRemove = Integer.parseInt(marblesAmount.getText()); 

    } 
    } 

    public int getMarblesToRemove(){ 
    return marblesToRemove; 
    } 


} 

桩类:

公共类桩{

private int initialNum; 
private int currentNum; 

public Pile(int initialNum){ 
    setNumMarbles(initialNum); 
    currentNum = initialNum; 
} 

public int getNumMarbles(){ 
    return currentNum; 
} 

public void removeMarbles(int numToRemove){ 
    currentNum = currentNum - numToRemove; 
} 

public void setNumMarbles(int amount){ 
    initialNum = amount; 
} 

public String toString(){ 
    return "Number of marbles: " + currentNum; 
} 

} 

我想要做的是在Player类中的函数playTurn(int pileSize)返回变量弹珠(在if(type == Type.HUMAN)块内部)仅当它不是零。通过调用函数getMarblesToRemove()将gui类中的变量marblesToRemove分配给弹子。

marblesToRemove最初在gui类的默认构造函数中设置为0,并导致functionplayTurn(int pileSize)进入无限循环。但当按下一个按钮(removeButton)时,marblesToRemove将更改为在JTextFieldmarblesAmount)中输入的另一个值。但是do while循环仍然是一个无限循环,并且函数不会返回任何内容,为什么?有人可以帮忙吗?谢谢。

+0

getMarblesToRemove()方法在哪里? – Apurv 2013-04-27 19:35:57

+0

听起来像是要么阻止EDT,要么扼杀过程的线程。在什么情况下执行“playTurn”? – MadProgrammer 2013-04-27 19:36:39

+0

getMarblesToRemove()位于gui类的第二个代码块的底部 – 2013-04-27 19:41:30

回答

2

这可能是因为我至少可以看到两个问题。首先,你正在修改一个线程中的变量,并在另一个线程中读取它。这应该使用同步或某种其他锁定机制(Lock或AtomicInteger等)完成。

第二个问题是你的阅读线程应该而不是正在做一个'紧密'循环。这是发送一个CPU到100%使用率的不良做法。应该使用某种形式的通知来完成。同样想到同步。

在解决这两个问题之前,您总是会得到不可靠的结果。

对于什么是值得的,在你的特定情况下,如果我进行一个有根据的猜测,我会猜想有两个重要的副本marblesAmount(并且还有多个副本)。有一个副本在L1中,一个CPU的寄存器正在进行紧密的循环,等待该寄存器发生变化,另一个在CPU的另一个核心中将其设置为新的值。除非你使用了一些同步或者java.util.concurrent。*库中的某些东西,否则你无法告诉该变量的一个副本刷新另一个。

+0

也是我的猜测。只是为了再次指出这一事实:尽量避免像这样运行循环。如果你需要做这样的事情,你应该更好地重新思考,如果你的问题的另一个解决方案会更好。 – user2248673 2013-04-27 19:55:32

0

我终于开始工作了。我刚刚添加了一行代码“System.out.print(”“);”在Player类的do-while循环中。

所以现在看起来

do{ 
     marbles = gui.getMarblesToRemove(); 
     System.out.print(""); 
     }while(marbles < 0); 

我不知道为什么这样的作品,但它确实笑。现在该函数实际上返回我在JTextField中设置的值,如果它不是零。

+0

你的代码仍然可以正常工作而不使用'System.out.print(“”);'。使它工作的唯一变化是'while(大理石<0)'在你的情况下。但是我也检查了'while(marbles == 0)'的代码。它在我的最后工作得很好。我建议你将'marblesToRemove'声明为'private volatile int marblesToRemove''。 'Votalite'关键字将确保'marblesToRemove'的更新值将被EDT和'playTurn'方法所看到。 – 2013-04-27 21:53:22