Below is a homework assignment I've just completed. I am curious as to how, with only a basic understanding of Java, I could make this code more robust, organized, efficient, etc. I intend to turn this in the way it is right now (so I won't be "taking credit for work that isn't mine"), but I want to see if there are ways in which I can improve. Thanks.


Code:
/********************
*  NimGame.java
*  Roger Tschida
********************/

import java.util.Scanner;

public class NimGame {

   
   public static void main(String[] args) {
      int stones = 0, turn, reduceStones = 0, wins = 0, total = 0, temp;
      Scanner stdIn = new Scanner(System.in);
      boolean invalidResponse;
      String inputStr = " ";
      System.out.println("T H E   G A M E   O F   N I M");
      do {
         total++;
         do {
            System.out.print("\nEnter number of starting stones: ");
            inputStr = stdIn.next();
            try {
               stones = Integer.parseInt(inputStr);
            } catch (NumberFormatException nfe) {
               System.out.println("Error: Invalid number");
            }
         } while (stones == 0);
         turn = 0;
         do {
            System.out.print("Would you like to go first? (y/n): ");
            inputStr = stdIn.next();
            if (inputStr.equalsIgnoreCase("y") || inputStr.equalsIgnoreCase("yes")) {
               turn = 2;
            } else if (inputStr.equalsIgnoreCase("n") || inputStr.equalsIgnoreCase("no")) {
               turn = 1;
            } else {
               System.out.println("Invalid Response");
            }
         } while (turn == 0);
         System.out.print("\n");
         while (stones > 0) {
            if (turn == 1) {
               if (stones % 3 == 0) {
                  System.out.println("The computer removes 2 stones.");
                  stones -= 2;
               }
               else {
                  System.out.println("The computer removes 1 stone.");
                  stones--;
               }
               turn++;
               System.out.println("The number of stones left is " + stones + ".");
            }
            if (turn == 2 && stones > 0) {
               do {
                  invalidResponse = false;
                  System.out.print("How many would you like to remove (1 or 2)? ");
                  inputStr = stdIn.next();
                  try {
                     reduceStones = Integer.parseInt(inputStr);
                     if (reduceStones != 1 && reduceStones != 2) {
                        throw new NumberFormatException();
                     }
                     if (reduceStones < 0 || stones - reduceStones < 0) {
                        throw new Exception();
                     }
                  } catch (NumberFormatException nfe) {
                     System.out.println("Error: Invalid response!");
                     invalidResponse = true;
                  } catch (Exception e) {
                     System.out.println("Error: Negative stones are invalid!");
                     invalidResponse = true;
                  }
               } while (invalidResponse);
               stones -= reduceStones;
               turn--;
               System.out.println("The number of stones left is " + stones + ".");
            }
         }
         if (turn == 2) {
            System.out.println("You win!");
            wins++;
         } else if (turn == 1) {
            System.out.println("The computer wins!");
         }
         temp = 1;
         while (temp == 1) {
            System.out.print("\nDo you want to play again? (y/n): ");
            inputStr = stdIn.next();
            if (inputStr.equalsIgnoreCase("y") || inputStr.equalsIgnoreCase("yes") || inputStr.equalsIgnoreCase("n") || inputStr.equalsIgnoreCase("no")) {
               temp = 0;
            }
         }
      } while (inputStr.equals("y") || inputStr.equals("yes"));
      System.out.println("\nResults:");
      System.out.println("Computer Wins: " + (total - wins));
      System.out.println("Player Wins: " + wins);
      System.out.println("Total Games: " + total);
      if (2 * wins == total) {
         System.out.println("It is a DRAW!");
      } else if (2 * wins < total) {
         System.out.println("The Computer Wins Overall!");
      } else {
         System.out.println("You Win Overall!");
      }
      System.out.println("\nThank you, good bye!");
   }
}
Hi.

I though you were allowed to take 1, 2 or 3 stones per move in 1 pile nim?
Hugh, the homework assignment says only 1 or 2 stones may be removed per turn.

Upon receiving a less-than-satisfactory grade on my previous homework, I would be grateful if anyone could look over my revised code (below) and point out either any problems that I may have missed or ways to make the code more easily readable (since that's where I lost a lot of my points).


Code:

/********************
*  NimGame.java
*  Roger Tschida
********************/

import java.util.Scanner;

public class NimGame {

   
   public static void main(String[] args) {
      
      int remainingStones = 0;
      int turn;
      int reduceStones = 0;
      int wins = 0;
      int total = 0;
      Scanner stdIn = new Scanner(System.in);
      boolean invalidResponse;
      boolean tempBoolean;
      String inputStr = "";
      
      System.out.println("T H E   G A M E   O F   N I M");
      
      do {      //This do-while loop is the entire game, minus the reporting of the results
         
         total++;
         
         do {
            
            System.out.print("\nEnter number of starting stones: ");
            inputStr = stdIn.next();
            
            try {
               
               remainingStones = Integer.parseInt(inputStr);
               
               if (remainingStones <= 0) {
                  
                  remainingStones = 0;
                  throw new Exception();
                  
               }
               
            } catch (NumberFormatException nfe) {
               
               System.out.println("Error: Invalid number");
               
            } catch (Exception e) {
               
               System.out.println("Error: Value must be greater than 0");
               
            }  //end Try-Catch
            
         } while (remainingStones == 0);
         
         turn = 0;
         
         do {          //do-while loop guarantees valid input and determines who starts
            
            System.out.print("Would you like to go first? (y/n): ");
            inputStr = stdIn.next();
            
            if (inputStr.equalsIgnoreCase("y") || inputStr.equalsIgnoreCase("yes")) {
               
               turn = 2;
               
            } else if (inputStr.equalsIgnoreCase("n") || inputStr.equalsIgnoreCase("no")) {
               
               turn = 1;
               
            } else {
               
               System.out.println("Error: Invalid Response");
               
            }  //end If
            
         } while (turn == 0);
         
         System.out.print("\n");      //Extra line to provide space shown in sample output
         
         while (remainingStones > 0) {   //Loop follows mandated computer strategy
            
            if (turn == 1) {
               
               if (remainingStones % 3 == 0) {
                  
                  System.out.println("The computer removes 2 stones.");
                  remainingStones -= 2;
                  
               }
               
               else {
                  
                  System.out.println("The computer removes 1 stone.");
                  remainingStones--;
                  
               }  //end If
               
               turn++; //Switches turns
               System.out.println("The number of stones left is " + remainingStones + ".");
               
            }  //end If: Computer's entire turn
            
            if (turn == 2 && remainingStones > 0) {   
               
               //Second check against positive value of remainingStones enables both the
               //computer and the player turns to reside in the same while loop without
               //the player being stuck when the computer removes the last stone
               
               do {
                  
                  invalidResponse = false;
                  System.out.print("How many would you like to remove (1 or 2)? ");
                  inputStr = stdIn.next();
                  
                  try {
                     
                     reduceStones = Integer.parseInt(inputStr);
                     
                     if (reduceStones != 1 && reduceStones != 2) {
                        
                        throw new NumberFormatException();
                        
                     }  //end If
                     
                     if (reduceStones < 0 || remainingStones - reduceStones < 0) {
                        
                        throw new Exception();
                        
                     }  //end If
                     
                  } catch (NumberFormatException nfe) {
                     
                     System.out.println("Error: Invalid response");
                     invalidResponse = true;
                     
                  } catch (Exception e) {
                     
                     System.out.println("Error: Negative stones are invalid");
                     invalidResponse = true;
                     
                  }  //end Try-Catch
                  
               } while (invalidResponse);  //end Do-While
               
               remainingStones -= reduceStones;
               turn--; //Switches turns
               System.out.println("The number of stones left is " + remainingStones + ".");
               
            }  //end If: Player's entire turn
            
         }  //end While: Entire game minus total results report
         
         if (turn == 2) { //If computer went last, turn = 2 from turn++
            
            System.out.println("You win!");
            wins++;
            
         } else if (turn == 1) { //If player went last, turn = 1 from turn--
            
            System.out.println("The computer wins!");
            
         }
         
         do {
            
            System.out.print("\nDo you want to play again? (y/n): ");
            inputStr = stdIn.next();
            tempBoolean = inputStr.equalsIgnoreCase("y") || inputStr.equalsIgnoreCase("yes")
                  || inputStr.equalsIgnoreCase("n") || inputStr.equalsIgnoreCase("no");
            
            if (!tempBoolean) {
               
               System.out.println("Error: Invalid response");
               
            } //A temporary variable seems cleaner than having the same string equality checks run multiple times
            
         }   while (!tempBoolean);  //end Do-While: Play again option
         
      } while (inputStr.equalsIgnoreCase("y") || inputStr.equalsIgnoreCase("yes"));
               //Checks against the "play again" input and controls
               //repetition of the most-external do-while loop
      
      System.out.println("\nResults:");
      System.out.println("Computer Wins: " + (total - wins));
      System.out.println("Player Wins: " + wins);
      System.out.println("Total Games: " + total);
      
      if (2 * wins == total) {
         
         System.out.println("It is a DRAW!");
         
      } else if (2 * wins < total) {
         
         System.out.println("The Computer Wins Overall!");
         
      } else {
         
         System.out.println("You Win Overall!");
         
      } //end If: Selecting overall winner
      
      System.out.println("\nThank you, good bye!");
      
   }  //end Main
   
}  //end Class
Sorry, yes looks like you can play with 1 or 2 per turn.

There's nothing really wrong with your code, after all it does work! I would say that they're probably looking for you to factor out various functions as method calls rather than in one large loop, making the main loop smaller and easier to read.

The only other thing, and this is a matter of personal preference, is that you validity test the player response, throw an exception when it isnt valid and catch to handle it. Although there's nothing really wrong with this, you're making something you already test for into an exception instead of reserving exceptions for those situations that are, in fact, exeptional.

except that you're probably expected to show the use of exceptions in your code anyhow Smile
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement