I trying to create the game nim. I made it so the computer can randomly take 1-3 cards from a random row. Right not the computer will do it, but when there is only one or three cards left it will go in an infinite loop.
Main file. Does not need touched
package nimgame;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
* @author Angela
*/
public class NimApp extends JFrame implements ActionListener {
private static final int ROWS = 3;
private JTextField[] gameFields; // Where sticks for each row shown
private JTextField rowField; // Where player enters row to select
private JTextField sticksField; // Where player enters sticks to take
private JButton playButton; // Pressed to take sticks
private JButton AIButton; // Pressed to make AI's move
private NimGame nim;
public NimApp() {
// Build the fields for the game play
rowField = new JTextField(5);
sticksField = new JTextField(5);
playButton = new JButton("PLAYER");
AIButton = new JButton("COMPUTER");
playButton.addActionListener(this);
AIButton.addActionListener(this);
AIButton.setEnabled(false);
// Create the layout
JPanel mainPanel = new JPanel(new BorderLayout());
getContentPane().add(mainPanel);
JPanel sticksPanel = new JPanel(new GridLayout(3, 1));
mainPanel.add(sticksPanel, BorderLayout.EAST);
JPanel playPanel = new JPanel(new GridLayout(3, 2));
mainPanel.add(playPanel, BorderLayout.CENTER);
// Add the fields to the play panel
playPanel.add(new JLabel("Row: ", JLabel.RIGHT));
playPanel.add(rowField);
playPanel.add(new JLabel("Sticks: ", JLabel.RIGHT));
playPanel.add(sticksField);
playPanel.add(playButton);
playPanel.add(AIButton);
// Build the array of textfields to display the sticks
gameFields = new JTextField[ROWS];
for (int i = 0; i < ROWS; i++) {
gameFields[i] = new JTextField(10);
gameFields[i].setEditable(false);
sticksPanel.add(gameFields[i]);
}
setSize(350, 150);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
nim = new NimGame(new int[]{3, 5, 7});
draw();
}
// Utility function to redraw game
private void draw() {
for (int row = 0; row < ROWS; row++) {
String sticks = "";
for (int j = 0; j < nim.getRow(row); j++) {
sticks += "| ";
}
gameFields[row].setText(sticks);
}
rowField.setText("");
sticksField.setText("");
}
public void actionPerformed(ActionEvent e) {
// Player move
if (e.getSource() == playButton) {
// Get the row and number of sticks to take
int row = Integer.parseInt(rowField.getText())-1;
int sticks = Integer.parseInt(sticksField.getText());
// Play that move
nim.play(row, sticks);
// Redisplay the board and enable the AI button
draw();
playButton.setEnabled(false);
AIButton.setEnabled(true);
// Determine whether the game is over
if (nim.isOver()) {
JOptionPane.showMessageDialog(null, "You win!");
playButton.setEnabled(false);
}
}
// Computer move
if (e.getSource() == AIButton) {
// Determine computer move
nim.AIMove();
// Redraw board
draw();
AIButton.setEnabled(false);
playButton.setEnabled(true);
// Is the game over?
if (nim.isOver()) {
JOptionPane.showMessageDialog(null, "You win!");
playButton.setEnabled(false);
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
NimApp a = new NimApp();
}
}
This is the support class for the main file
package nimgame;
import java.util.Random;
/**
*
* @author Angela
*/
public class NimGame {
int[] Sticks; //creating an array of sticks
int totalSticks=0;
public NimGame(int[] initialSticks){
Sticks = initialSticks;}
public int getRow(int r){
return Sticks[r];}
public void play(int r, int s){
Sticks[r]=Sticks[r]-s;}
This is supposed to count up all the sticks left on the board. It should return true if 1 stick is left and false if there is more than one stick on the board. I am having trouble with the for loop and making it correctly count the sticks.
public boolean isOver(){
int theTotal = 0;
for (int i =1; i<Sticks.length; i++){
theTotal = totalSticks + Sticks[i];
System.out.println(totalSticks);}
totalSticks = theTotal;
System.out.println(totalSticks);
if (totalSticks<=1){
return true;
}
return false;
This method is supposed to randomly generate a row and an amount of sticks to discard for the computer. This is where i am getting my infinite loop.
public void AIMove(){
Random randomInt = new Random ();
int RandomRow = randomInt.nextInt(3);
int RandomDiscard = randomInt.nextInt(3-0)+1;
int randomize=0;
while (RandomDiscard >Sticks[RandomRow] && totalSticks>1){
RandomRow = randomInt.nextInt(3);
RandomDiscard = randomInt.nextInt(3-0)+1;
Sticks[RandomRow]=Sticks[RandomRow]-RandomDiscard;
randomize = 1;}
if (randomize==0)
Sticks[RandomRow]=Sticks[RandomRow]-RandomDiscard;
if (totalSticks <= 1){
Sticks[RandomRow]=Sticks[RandomRow]-1;}
isOver();
}
}
The condition to terminate the while
loop is when you have RandomDiscard > Sticks[RandomRow]
or totalSticks>1
on the body of the loop the value of Sticks[RandomRow]
gets smaller at least by one, maintaining the condition.
To break the loop either on the body you need to increment Sticks[RandomRow]
or decrease the totalSticks
or change the condition to RandomDiscard < Sticks[RandomRow] || totalSticks>1
RandomDiscard < Sticks[RandomRow] || totalSticks>1
Edit(10:18PM): Looking at the problem and the solution, I got a better way to solve the problem here is what I have done:
public void AIMove(){
Random randomInt = new Random ();
boolean tryRemove = true;
while(tryRemove && totalSticks > 1){
int RandomRow = randomInt.nextInt(3);
if(Sticks[RandomRow] <= 0)//the computer can't remove from this row
continue;
//the max number to remove from row
int size = 3;
if( Sticks[RandomRow] < 3)//this row have lest that 3 cards
size = Sticks[RandomROw];//make the max number to remove from the row be the number of cards on the row
int RandomDiscard = randomInt.nextInt(size) + 1;
Sticks[RandomRow] = Sticks[RandomRow] - RandomDiscard;
//I don't know if this is needed, but since we remove a RandomDiscard amount lest decrease the totalSticks
totalSticks = totalSticks - RandomDiscard;
//exit loop
tryRemove = false;
}
if(totalSticks <= 1){
Sticks[RandomRow]=Sticks[RandomRow]-1;
isOver();
}
}
What I have done was combine the random loop and the if statements in one loop.
theTotal = totalSticks + Sticks[i];
should be
theTotal = theTotal + Sticks[i];
Also, the for loop probably should start with the index 0 instead of 1:
for (int i =1; i<Sticks.length; i++){
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.