I'm coding a simple maze game in java. The program reads in a text "map" from an input file for the layout of the maze. The rules are simple: navigate the maze (represented by a 2D array) through user input and avoid the cave-ins (represented by Xs), and get to the 'P' (player) the the spot marked 'T'. Right now, I've got most of the code written, it's just a matter of getting it to work properly. I've set up most of the game to run with a while loop, with the boolean "got treasure" set to false. Once this rings true, it should end the game.
However, I haven't coded the circumstance in which the player actually gets the treasure though, so I'm wondering why my code simply spits out "Congratulations! You've found the treasure!" and nothing else. If anyone could shed some light on this, I'd be very grateful. My code is somewhat of a mess of loops, as our teacher has just gotten to methods, constructors, and creating our own classes. Here is the code I have so far:
import java.util.*;
import java.io.File;
public class MazeGame {
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(new File("maze.txt"));
Scanner user = new Scanner(System.in);
int rows = scan.nextInt();
int columns = scan.nextInt();
int px = 0;
int py = 0;
String [][] maze = new String[rows][columns];
String junk = scan.nextLine();
for (int i = 0; i < rows; i++){
String temp = scan.nextLine();
String[] arrayPasser = temp.split("");
for (int j = 0; j < columns; j++){
maze[i][j] = arrayPasser[i];
}
}
boolean gotTreasure = false;
while (gotTreasure = false){
for (int i = 0; i < rows; i++){
for (int j = 0; j < columns; j++){
System.out.print(maze[i][j]);
System.out.print(" ");
}
System.out.print("\n");
}
System.out.printf("\n");
System.out.println("You may:");
System.out.println("1) Move up");
System.out.println("2) Move down");
System.out.println("3) Move left");
System.out.println("4) Move right");
System.out.println("0) Quit");
int choice = user.nextInt();
int i = 0;
if (choice == 1 && i >= 0 && i < columns){
for (int k = 0; k < rows; k++){
for (int l = 0; l < columns; l++){
if (maze[k][l].equals(maze[px][py]) && maze[px][py-1].equals("X") == false){
maze[px][py] = ".";
maze[k][l-1] = "P";
maze[px][py] = maze[k][l-1];
}else if (maze[px][py-1] == "X"){
System.out.println("Cannot move into a cave-in! Try something else.");
}else {
continue;}
}
}
}
else if (choice == 2 && i >= 0 && i < columns){
for (int k = 0; k < rows; k++){
for (int l = 0; l < columns; l++){
if (maze[k][l].equals(maze[px][py]) && maze[px][py+1].equals("X") == false){
maze[px][py] = ".";
maze[k][l+1] = "P";
maze[px][py] = maze[k][l+1];
}else if (maze[px][py+1] == "X"){
System.out.println("Cannot move into a cave-in! Try something else.");
}else {
continue;}
}
}
}
else if (choice == 3 && i >= 0 && i < columns){
for (int k = 0; k < rows; k++){
for (int l = 0; l < columns; l++){
if (maze[k][l].equals(maze[px][py]) && maze[px-1][py].equals("X") == false){
maze[px][py] = ".";
maze[k-1][l] = "P";
maze[px][py] = maze[k-1][l];
}else if (maze[px-1][py] == "X"){
System.out.println("Cannot move into a cave-in! Try something else.");
}else {
continue;}
}
}
}
else if (choice == 4 && i >= 0 && i < columns){
for (int k = 0; k < rows; k++){
for (int l = 0; l < columns; l++){
if (maze[k][l].equals(maze[px][py]) && maze[px+1][py].equals("X") == false){
maze[px][py] = ".";
maze[k+1][l] = "P";
maze[px][py] = maze[k+1][l];
}else if (maze[px+1][py] == "X"){
System.out.println("Cannot move into a cave-in! Try something else.");
}else {
continue;}
}
}
}
else if (choice == 0){
System.exit(0);
}
}
System.out.println("Congratulations, you found the treasure!");
scan.close();
user.close();
}
}
And here is the sample input file:
5 5
P.XX.
.X...
...X.
XXT..
..X..
(sigh) one equals sign instead of two. You have "while (gotTreasure = false)", which assigns the value false to gotTreasure and does not enter the loop. Change it to "while (gotTreasure == false) and it enters the loop.
For future questions: please attempt to figure out on your own what is happening, and let others know what you have tried and what specific questions you have about it. It is arguable I should just have let this go, since it is essentially a request to debug your code for you. Learn to debug yourself. If trace statements aren't getting executed, it's most likely the code at that point isn't getting executed. If a loop isn't getting entered, it is almost certainly because the conditions for entering the loop don't exist.
Learn to use a debugger - eclipse (and, I am sure, lots of other development tools) has an excellent one. Find out what a breakpoint is, how to set it and examine variables when it is hit, and figure out from there what has gone wrong.
If this is a typo ignore this, if it isnt
while (gotTreasure = false) is wrong.
you are not checking if gotTreasure is false, you are assigning it false.
to check if gotTreasure is false use == operator
while(gotTreasure==false)
lemme know if this is a type, i ll delete the answer. :)
You have a simple mistake in your while loop condition,
Instead of,
while (gotTreasure = false)
You should use,
while (gotTreasure == false)
In the first case, you are assigning false to gotTreasure and in the second you are evaluating if gotTreasure is false.
I refeactored your code, because there are a lot of bad programming-styles. Now the game should run as intended.
I used a Construktor and a lot of methods, to divide your big method in small parts. -> easier to understand.
I declared attributes (known in the whole class), so that the different methods can use this variables.
You often checked for a condition like if(variable == false). Try to use if(!variable), the exclamation mark negates the value of the variable.
Your update-Methode had a lot of redundandancies.
By adding the following switch-case-Part, I could seperate the different directions:
General code for setting directions by a userinput:
switch (choice){
case 0: System.exit(0);
case 1: xdir = 0; ydir = -1; break;
case 2: xdir = 0; ydir =1; break;
case 3: xdir = -1; ydir = 0; break;
case 4: xdir = 1; ydir = 0; break;
}
Afterwards I could calculate the new position by adding xdir to x and ydir to y. This comes handy, if you try to check if the new position is in the bounds of the array.
//1. Check if the new position is in the array.
if (x+xdir >= 0 && x+xdir <columns && y+ydir >=0 && y+ydir < rows){
Here follows the whole class:
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class MazeGame2 {
Scanner scan;
Scanner user;
int rows;
int columns;
String [][] maze;
int x; //Player x-Position
int y; //Player y-Position
boolean gotTreasure;
/**
* Konstruktor for the class.
*/
public MazeGame2(){
init();
game();
scan.close();
user.close();
}
/**
* Initialisation of the maze and all attributes.
*/
public void init(){
user = new Scanner(System.in); //Scanner for Userinput
/********************************
* Scanning the maze from a file.
*/
//1. Open the file. Has to be in a try-catch-Bracket, because the file might not be there.
try{
scan = new Scanner(new File("maze.txt"));
}catch(FileNotFoundException e){
e.printStackTrace();
}
//2. Scan the dimensions of the maze.
rows = scan.nextInt();
columns = scan.nextInt();
scan.nextLine(); // So that the next Line can be scanned.
maze = new String[rows][columns];//Create the maze-Array with the right dimensions.
for (int i = 0; i < rows; i++){
String temp = scan.nextLine(); //Scan one line.
for (int j = 0; j < columns; j++){
maze[i][j] = temp.substring(j, j+1);//Put every character in the maze
if (maze[i][j].equals("P")){ //Look out for the Player-Position
x = j;
y = i;
}
}
}
gotTreasure = false;
}
/**
* Prints the Input of the maze-Array. But only if the spots are visible by the player.
*/
public void printMaze(){
for (int i = 0; i < rows; i++){
for (int j = 0; j < columns; j++){
System.out.print(maze[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
/**
* Prints the possebilities to move by the player.
*/
public void printUserPossebilities(){
System.out.println();
System.out.println("You may:");
System.out.println("1) Move up");
System.out.println("2) Move down");
System.out.println("3) Move left");
System.out.println("4) Move right");
System.out.println("0) Quit");
}
/**
*
*/
public void update(int choice){
int xdir=0;
int ydir=0;
// Update the direction based on the userChoice
switch (choice){
case 0: System.exit(0);
case 1: xdir = 0; ydir = -1; break;
case 2: xdir = 0; ydir =1; break;
case 3: xdir = -1; ydir = 0; break;
case 4: xdir = 1; ydir = 0; break;
}
/**
* Update the situation based on the current direction and step.
*/
//1. Check if the new position is in the array.
if (x+xdir >= 0 && x+xdir <columns && y+ydir >=0 && y+ydir < rows){
//2. Check if a step is possible
if (maze[y+ydir][x+xdir].equals("X")){
System.out.println("Cannot move into a cave-in! Try something else.");
}else{
//3. clear the P from the old Position
maze[y][x] =".";
//4. Check if the Player is over the treasure
if (maze[y+ydir][x+xdir].equals("T")){
gotTreasure = true;
}
x = x+xdir;
y = y + ydir;
maze[y][x] = "P"; //Show the new position of the player.
}
}else{
System.out.println("That's not a possible Move.");
}
}
/**
* The game-Methode that includes the game-loop and
*/
public void game(){
while (!gotTreasure){
//System.out.print('\u000C');
printMaze();
printUserPossebilities();
int userInput = user.nextInt(); //Wait for userinput
update(userInput);
}
//System.out.print('\u000C');
printMaze();
System.out.println("Congratulations, you found the treasure!");
}
public static void main(String[] args){
MazeGame2 m = new MazeGame2();
}
}
Related
I am relatively new to coding and Java and for my CS-173 class, I was tasked with creating a Tic Tac Toe game. However, when it came to creating the method for determining a winner, whenever I achieved a "win", the code never ran saying I won. I do have the code to check each way to win however, I pulled it from the code in order to do some personal troubleshooting. Also, my apologies for the bad code.
public static void playGame(char[][] board, int size){
Scanner input = new Scanner(System.in);
int turn = 0;
int spaces = board.length * board.length;
boolean valid = false;
boolean winner = false;
for (int i = 0; i<spaces; i++){
int startchecker = 3;
int xcord = 0;
int ycord = 0;
do{
do{
System.out.println("Player 1 please type your coordinates with a space");
xcord = input.nextInt();
ycord = input.nextInt();
valid = isValid (board, xcord, ycord);
if(i >= spaces){
}
}while(!valid);
board[xcord][ycord] = 'X';
printBoard(board);
winner = isWinner(board);
do{
System.out.println("Player 2 please type your coordinates with a space");
xcord = input.nextInt();
ycord = input.nextInt();
valid = isValid (board, xcord, ycord);
winner = isWinner(board);
}while(!valid);
board[xcord][ycord] = 'O';
printBoard(board);
if(i >= spaces){
winner = true;
System.out.println("It is a tie!");
}
}while(!winner);
}
}
public static boolean isWinner (char[][] board){
boolean determiner = false;
int XCounter = 0;
int OCounter = 0;
int size = board.length-1;
int winner = 3;
//Check Horizontal
for(int j = 0; j > size; j++){
for(int i = 0; i > size; i++){
if(board[i][j]=='X'){
XCounter++;
}
else if(board[i][j]=='O'){
OCounter++;
}
if(XCounter == winner){
determiner = true;
System.out.println("Player 1 Wins!");
}
else if(OCounter == winner){
System.out.println("Player 2 Wins!");
determiner = true;
}
}
}
return determiner;
}
Your isWinner method does not check for all the ways to win.
I would recommend using 2 for-loops (one for horizontal lines and the other for vertical) for clarity, and 2 if-statements (outside of the loops) to check for diagonals.
For example,
for(int i=0; i<size; i++){
boolean flag = true; // Assume this line is a winning line
for(int j=0; j<size; j++){ // Check each tile to see if it has a tile
// Set the flag to false when it is not the tile you're looking for
}
}
I'm having trouble randomizing and adding a 2x2 ship into the game board. I need it to look like the following:
currently I can only seem to get a 1x1 ship and don't quite understand the logic for adding the 2x2 and randomizing it so that they're all connected.
also when the user inputs a '2' at the main menu I need to show the solution, meaning where the ships are. Which I also could use some help on.
Not nearly finished but please be critical when it comes to judging my code, everything helps!
Thanks in advance.
import java.util.Scanner;
public class Battleship
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int [][] board = new int [5][5];
int [][] ship = new int [4][2];
int [] shot = new int[2];
boolean done = false;
resetboard(board);
while(!done)
{
displayBoard(board);
displayMenu();
for(int ships=0 ; ships < 4 ; ships++)
{
ship[ships][0]=(int) Math.random() * 5 + 1;
ship[ships][1]=(int) Math.random() * 5 + 1;
}
int choice = getMenuInput(input);
if(choice == 1)
{
getRow(shot);
getColumn(shot);
if(fireShot(shot,ship) == true)
{
board[shot[0]][shot[1]]= 1;
}
else
{
board[shot[0]][shot[1]]= 0;
}
}
else if(choice == 2)
{
for (int x = 0; x < 5; x++)
{
for(int y = 0; y < 5; y++)
{
for(int z = 0; z < 3; z++)
{
if(board[x][y] == ship[z][0] && board[x][y] == ship[z][1] )
{
board[ship[z][0]][ship[z][1]]= 1;
}
}
}
}
displayBoard(board);
}
else if (choice == 3)
{
done = true;
System.out.println("Thanks For Playing");
}
}
}
public static void displayBoard(int [][] board)
{
System.out.println(" A B C D E");
for(int r =0; r < 5; r++)
{
System.out.print((r + 1) + "");
for(int c = 0; c < 5; c++)
{
if(board[r][c] == -1)
{
System.out.print(" -");
}
else if(board[r][c] == 0)
{
System.out.print(" X");
}
else if(board[r][c] == 1)
{
System.out.print(" *");
}
}
System.out.println("");
}
}
public static void resetboard(int[][] a)
{
for(int row=0 ; row < 5 ; row++ )
{
for(int column=0 ; column < 5 ; column++ )
{
a[row][column]=-1;
}
}
}
public static void displayMenu()
{
System.out.println("\nMenu:");
System.out.println("1. Fire Shot");
System.out.println("2. Show Solution");
System.out.println("3. Quit");
}
public static int getMenuInput(Scanner input)
{
int in = 0;
if(input.hasNextInt())
{
in = input.nextInt();
if(in>0 && in<4)
{
in = in;
}
else
{
System.out.println("Invalid Entry, Please Try Again.\n");
}
}
else
{
System.out.println("Invalid Entry, Please Try Again.\n");
input.nextInt();
}
return in;
}
public static void getRow(int [] shot)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter a Row Number: ");
shot[0] = shotValid(input);
shot[0]--;
}
public static void getColumn(int [] shot)
{
Scanner input = new Scanner(System.in);
int numb = 0;
System.out.println("Enter a Column Letter: ");
String choice = input.next();
if (choice.equals("A"))
{
numb = 0;
}
else if(choice.equals("B"))
{
numb = 1;
}
else if( choice.equals("C"))
{
numb = 2;
}
else if(choice.equals("D"))
{
numb = 3;
}
else if(choice.equals("E"))
{
numb = 4;
}
else
{
System.out.println("2Invalid Entry, Please Try Again.\n");
input.nextLine();
}
shot[1] = numb;
}
public static boolean fireShot(int [] shot, int [][]ship)
{
boolean result = false;
for(int shipHit=0 ; shipHit<ship.length ; shipHit++)
{
if( shot[0]==ship[shipHit][0] && shot[1]==ship[shipHit][1])
{
result = true;
}else
{
result = false;
}
}
return result;
}
public static int shotValid(Scanner quantity)
{
int shot = 0;
boolean done = false;
while(!done)
{
if(quantity.hasNextInt())
{
shot = quantity.nextInt();
if(shot>0 && shot<6)
{
shot = shot;
done = true;
}
else
{
System.out.println("1Invalid Entry, Please Try Again.\n");
}
}
else
{
System.out.println("2Invalid Entry, Please Try Again.\n");
quantity.next();
}
}
return shot;
}
}
You want to place a single ship of size 2×2 on the board and do this:
for(int ships=0 ; ships < 4 ; ships++)
{
ship[ships][0]=(int) Math.random() * 5 + 1;
ship[ships][1]=(int) Math.random() * 5 + 1;
}
There are several errors here:
The random variables will always be 1, because the (int) conversion affects only the result of Math.random(), which is a pseudo-random floating-point number between 0 and 1 exclusively. Conversion to int truncates this to 0. Use (int) (Math.Random() * 5), which will yield a random number from 0 to 4.
You shouldn't add 1. Internally, your game uses the zero-base indices that Java uses, which is good. ()These are known to the outside as rows 1 to 5 ande columns A to E, but you take care of that in your getRow and getColumn functions.)
You place up to four independent ships of size 1×1. (This is up to four, because you might end up wit one ship in an already occupied place.)
To place a single 2×2 ship, just determine the top left corner randomply and make the other ship coordinates dependent on that:
int x = (Math.random() * 4);
int y = (Math.random() * 4);
ship[0][0] = x;
ship[0][1] = y;
ship[1][0] = x + 1;
ship[1][1] = y;
ship[2][0] = x;
ship[2][1] = y + 1;
ship[3][0] = x + 1;
ship[3][1] = y + 1;
You now have two separate data structures: The board, which is all minus ones initially, and the list of ships. Your display routine suggests that you want three different values for a cell in the board: −1 is water; 1 is an unarmed part of a ship and 0 is where a shot has been fired.
But you never set these values. You set the position of the ship before displaying, but you should probably set them straight away. You should also set the locations of shots, so that you never fire at the same cell.
You need two modes for displaying the board: The in-play mode, where the unharmed ships are displayed as water and the solution mode, which shows everything as it is. You could so this by passing a flag to the routine.
Now if you think about it, you don't really need the ship array. Just use the information in the board:
int x = (Math.random() * 4);
int y = (Math.random() * 4);
board[x][y] = 1;
board[x + 1][y] = 1;
board[x][y + 1] = 1;
board[x + 1][y + 1] = 1;
Keep a count of ships, initially 4. When you fire at water, mark the cell with 0. When you fire at a ship, mark the cell as 0 and decrement the count of ships. If the count of ships is zero, the player has won. Otherwise, redisplay the boatrd and shoot again.
I have a map class, which is an Array of 100 Strings
public class map{
[...]
public void movePlayer(String entrada){
if (entrada.equalsIgnoreCase("w")){
move = -10;
}
else if (entrada.equalsIgnoreCase("s")){
move = 10;
}
else if (entrada.equalsIgnoreCase("d")){
move = 1;
}
else if (entrada.equalsIgnoreCase("a")){
move = -1;
}
for(int i = 0; i < mapa.length; i++){
if (mapa[i].equals("P")){
int moved = i+move;
mapa[moved] = "P";
}
}
}
The main looks a little like this
String[] mapa = map.getMap();
mapa[0] = "T";
mapa[99] = "P";
for (int j = 0; j<10; j++){
for(int i = 0; i < map.length; i++){
if (i == 9 || i == 19 || i == 29 || i == 39 || i == 49 || i == 59 || i == 69 || i == 79 || i == 89 || i == 99){
System.out.println(mapa[i]);
}
else{
System.out.print(mapa[i]);
}
}
System.out.print("\n");
System.out.print("Entre o movimento:");
map.movePlayer(read.nextLine());
mapa = map.getMap();
}
It runs like this: A map with random chars are printed, some are normal floors some are traps
EXAMPLE
T##_______
^__#__*^#_
##^^#_#___
_*^^^#^^#^
^^_#_^____
^#_^#___##
*#^_^_____
^###_^__^#
#_#^##^#**
##^^_##_#P
Enter movement:w
T##_______
^__#__*^#_
##^^#_#___
_*^^^#^^#^
^^_#_^____
^#_^#___##
*#^_^_____
^###_^__^#
#_#^##^#*P
##^^_##_#P
Enter movement: w
T##_______
^__#__*^#_
##^^#_#___
_*^^^#^^#^
^^_#_^____
^#_^#___##
*#^_^_____
^###_^__^P
#_#^##^#*P
##^^_##_#P
How can I make the program to print the place where the Player originally was with the previous char it had, in this case a blank space in position [99] and a "*" in position [89]? Thanks for the patience!
Instead of tracking the player inside the map, you can leave the map unchanged and just track the player's position.
int playerpos = 99;
for (int j = 0; j<10; j++){
for(int i = 0; i < map.length; i++){
if (playerpos == i)
System.out.print("P");
else
System.out.print(mapa[i]);
if (i %10 == 9){
System.out.println();
}
}
Then your movePlayer method just changes the playerpos variable.
before player's movement you need to store data from the target cell, like this
int moved = i+move;
previousChar = mapa[moved]; // store replaced symbol
mapa[moved] = "P";
so, during next move you need to restore original char in old position, it could look like this:
int moved = i+move;
mapa[i] = previousChar; // restore original symbol at current player's location
previousChar = mapa[moved]; // preserve symbol at new player's location
mapa[moved] = "P"; // move player to new location
don't forget to init previousChar before very first move
As Lashane is saying, use a variable to store the overriden char for later assignment:
public class map{
[...]
this.init(function() {
last_squarechar = INIT_SQUARECHAR
[...]
});
public void movePlayer(String entrada) {
if (entrada.equalsIgnoreCase("w")){
move = -10;
}
else if (entrada.equalsIgnoreCase("s")){
move = 10;
}
else if (entrada.equalsIgnoreCase("d")){
move = 1;
}
else if (entrada.equalsIgnoreCase("a")){
move = -1;
}
}
for(int i = 0; i < mapa.length; i++){
if (mapa[i].equals("P")){
int moved = i+move;
mapa[i] = last_squarechar
last_squarechar = mapa[moved]
mapa[moved] = "P";
}
}
}
I am a beginner java student writing a gui tic-tac-toe program for my class. (No players, just computer generated).
Everything in my program works as expected, except for one thing; it seems that the placement of my method call for checkWinner is not place correctly, because the assignment for the X's and O's always finish. Why won't the loop end as soon as there is a winner?
It will return the correct winner based on the method call, but the for-loop will continue to iterate and fill in the rest (so sometimes it looks like both the x and o win or one wins twice). I've been going crazy, thinking it might be the placement of my checkWinner method call and if statement. When I set the winner = true; shouldn't that cancel the loop? I have tried putting it between, inside and outside each for-loop with no luck :(
I have marked the area I think is the problem //What is wrong here?// off to the right of that part the code. Thank you for any input!! :)
public void actionPerformed(ActionEvent e)
{
int total = 0, i = 0;
boolean winner = false;
//stop current game if a winner is found
do{
// Generate random # 0-1 for the labels and assign
// X for a 0 value and O for a 1 value
for (int row = 0; row < gameboard.length; row++) //rows
{
for (int col = 0; col < gameboard[row].length; col++) //columns
{
//Generate random number
gameboard[row][col] = (int)(Math.random() * 2);
//Assign proper values
if(gameboard[row][col] == 0)
{
labels[i].setText("X");
gameboard[row][col] = 10; //this will help check for the winner
}
else if(gameboard[row][col] == 1)
{
labels[i].setText("O");
gameboard[row][col] = 100; //this will help check for winner
}
/**Send the array a the method to find a winner
The x's are counted as 10s
The 0s are counted as 100s
if any row, column or diag = 30, X wins
if any row, column or diag = 300, Y wins
else it will be a tie
*/
total = checkWinner(gameboard); **//Is this okay here??//**
if(total == 30 || total == 300) //
winner = true; //Shouldn't this cancel the do-while?
i++; //next label
}
}//end for
}while(!winner);//end while
//DISPLAY WINNER
if(total == 30)
JOptionPane.showMessageDialog(null, "X is the Winner!");
else if(total == 300)
JOptionPane.showMessageDialog(null, "0 is the Winner!");
else
JOptionPane.showMessageDialog(null, "It was a tie!");
}
The easiest way would be to break all loops at once. (Even if some people dont like this)
outerwhile: while(true){
// Generate random # 0-1 for the labels and assign
// X for a 0 value and O for a 1 value
for (int row = 0; row < gameboard.length; row++) //rows
{
for (int col = 0; col < gameboard[row].length; col++) //columns
{
total = checkWinner(gameboard);
if(total == 30 || total == 300)
break outerwhile; //leave outer while, implicit canceling all inner fors.
i++; //next label
}
}//end for
}//end while
This However would not allow for the "tie" option, because the while will basically restart a game, if no winner has been found. To allow tie, you dont need the outer while at all, and can leave both fors at once, when a winner is found:
Boolean winner = false;
outerfor: for (int row = 0; row < gameboard.length; row++) //rows
{
for (int col = 0; col < gameboard[row].length; col++) //columns
{
total = checkWinner(gameboard);
if(total == 30 || total == 300){
winner = true;
break outerfor; //leave outer for, implicit canceling inner for.
}
i++; //next label
}
}//end for
if (winner){
//winner
}else{
//tie.
}
First of all, your code iterates through a board and generates random marks of X and O. This leads to some very odd board states, being always filled row-by-row, and possibly with unbalanced number of X and O marks.
IMHO you should organize your code in opposite manner to fill a board similary to a true game. I mean a series of 9 marks 'XOXOXOXOX' spreaded over the board.
Let Labels labels be a nine-character array, initialized to 9 spaces.
public int doGame( Labels labels)
{
labels = " ";
int itisXmove = true; // player X or O turn
for( int movesLeft = 9; movesLeft > 0; movesLeft --)
{
int position = // 0 .. movesLeft-1
(int) Math.floor(Math.random() * movesLeft);
for( int pos = 0; pos < 9; pos ++) // find position
if( labels[ pos] == " ") // unused pos?
if( position-- == 0) // countdown
{
if( itisXmove) // use the pos
labels[ pos] = "X"; // for current player
else
labels[ pos] = "O";
break;
}
int result = checkWinner( labels); // who wins (non-zero)?
if( result != 0)
return result;
itisXmove = ! itisXmove; // next turn
}
return 0; // a tie
}
then
public void actionPerformed(ActionEvent e)
{
Labels labels;
int result = doGame( labels);
if( result == valueForX)
JOptionPane.showMessageDialog(null, "X is the Winner!");
else if( result == valueForO)
JOptionPane.showMessageDialog(null, "O is the Winner!");
else
JOptionPane.showMessageDialog(null, "It's a tie!");
for( int rowpos = 0; rowpos < 9; rowpos += 3)
{
for( int colpos = 0; colpos < 3; colpos ++)
/* output (char)label[ rowpos + colpos] */;
/* output (char)newline */;
}
}
I think you should change your loop condition and add one more bool.
You have a "tie" condition but currently you only check for winner. The only explanation without the checkWinner code is that you are encountering a tie every time.
So...
boolean tie;
boolean winner;
do {
//your stuff
}
while(!(tie || winner))
Edit: I didn't realize you put the while loop outside your for loop, you will need to break out of your for loops in order for the while condition to be checked.
//stop current game if a winner is found
do{
for (int row = 0; row < gameboard.length; row++) //rows
{
for (int col = 0; col < gameboard[row].length; col++) //columns
{
if(winner || tie)
break;
}//end for
if(winner || tie)
break;
}//end for
}while(!(winner || tie));//end while
//the rest of your stuff here
You're not checking the value of winner until both for loops complete. Add a break right after you set winner = true, and add an
if (winner)
{
break;
}
to the beginning or end of your outer for loop.
Your issue is that your do/while statement is wrapped around the for statements. So the for statements end up running their entire cycle before it ever reaches the while statement. A solution to get around this is checking for a winner in the for statements and breaking:
//stop current game if a winner is found
do {
for (int row = 0; row < gameboard.length; row++) //rows
{
for (int col = 0; col < gameboard[row].length; col++) //columns
{
// ... your other code ...
total = checkWinner(gameboard);
if(total == 30 || total == 300) {
winner = true;
break; // end current for-loop
}
i++; //next label
}
if (winner) break; // we have a winner so we want to kill the for-loop
} //end for
} while(!winner); //end while
So you should be able to just loop through the two for-statements and break upon a winner. Your code also does not seem to handle a tied case, but I am guessing you already know that.
My brother offered me a challege to help my studies by making a game that only runs in the main method instead of using other classes to make sure I still remember my old stuff. Bases off that I went with a cat and mouse game where the player is the mouse looking for the cheese while avoiding all the cats. When you enter an empty "room" (cell) the game is supposed to give you a clue at how far you are from the cheese. Now the game runs but my clues just keep going higher and higher to the point where it over the amount of rooms in the maze. I am stumpped on where the problem is.
Here's the code
import java.util.Scanner;
import java.util.Random;
public class CatAndMouse
{
public static final int MAX = 10;
public static void main(String args[ ])
{
Scanner mouse = new Scanner(System.in);
Random placement = new Random();
boolean check = true, gameOver = false, win = false, lose = false;
final int row = MAX;
final int col = MAX;
final int page = MAX;
int cheeseX, cheeseY, cheeseZ;
int cheese = 1;
int catX, catY, catZ;
int cat = 2;
int mouseRow;
int mouseCol;
int mousePage;
int mouseMove;
int empty = 0;
int clue = 0;
int clueCount = 0;
int winQuotes;
int loseQuotes;
int [][][]maze = new int [row][col][page];
for(int i = 0; i < MAX; i++)
{
for(int j = 0; j < MAX; j++)
{
for(int k = 0; k < MAX; k++)
{
maze[i][j][k] = empty;
}//page
}//col
}//row
cheeseX = placement.nextInt(row);
cheeseY = placement.nextInt(col);
cheeseZ = placement.nextInt(page);
maze[cheeseX][cheeseY][cheeseZ] = cheese;
for (int i = 0; i < 500; i++)
{
catX = placement.nextInt(row);
catY = placement.nextInt(col);
catZ = placement.nextInt(page);
maze[catX][catY][catZ] = cat;
if ((maze[catX][catY][catZ]) == (maze[cheeseX][cheeseY][cheeseZ]))
{
catX = placement.nextInt(row);
catY = placement.nextInt(col);
catZ = placement.nextInt(page);
maze[catX][catY][catZ] = cat;
}//if place with cheese
}//cat placement loop
System.out.println("Hello there, my name is Q, do you like it? it's short for Q. So you're probably asking yourself \"why am I now a mouse?\"");
System.out.println("The answer is simple, I was bored and you humans are so much fun to play with, but don't worry I can change you back.");
System.out.println("All you have to do is win my little game and you'll be back to your old self again, loose and...well just don't lose.");
System.out.println("In this maze there is a piece of cheese, find it and you win. But be careful now, I added a \'few\' cats to hunt you.");
System.out.println("Can't make this too easy now can we? But don't worry, you'll be given clues if you're close to the cheese or not");
System.out.println("The maze itself is 10*10*10 and to move through it enter an integer between 0-9.");
System.out.println("Now then, let the game begin.");
System.out.println();
do
{
System.out.print("Enter row: ");
mouseRow = mouse.nextInt();
if((mouseRow < 0) || (mouseRow > 9))
{
while (check == true)
{
System.out.print("I said, it needs to be an integer between 0-9. Try again: ");
mouseRow = mouse.nextInt();
if((mouseRow >= 0) && (mouseRow <= 9))
check = false;
}//while closer
}//row check
check = true;
System.out.print("Enter column: ");
mouseCol = mouse.nextInt();
if((mouseCol < 0) || (mouseCol > 9))
{
while (check == true)
{
System.out.print("I said, it needs to be an integer between 0-9. Try again: ");
mouseCol = mouse.nextInt();
if((mouseCol >= 0) && (mouseCol <= 9))
check = false;
}//while closer
}//column check
check = true;
System.out.print("Enter page: ");
mousePage = mouse.nextInt();
if((mousePage < 0) || (mousePage > 9))
{
while (check == true)
{
System.out.print("I said, it needs to be an integer between 0-9. Try again: ");
mousePage = mouse.nextInt();
if((mousePage >= 0) && (mousePage <= 9))
check = false;
}//while closer
}//page check
check = true;
mouseMove = maze[mouseRow][mouseCol][mousePage];
System.out.println();
/*================[Win/Lose]===============*/
if (mouseMove == 2)
{
gameOver = true;
lose = true;
}//loser
if (mouseMove == 1)
{
gameOver = true;
win = true;
}//winner
/*===============[Win/Lose]===============*/
/*=================[Clue]=================*/
if(mouseRow == cheeseX)
{
System.out.println("In same row as cheese!");
}//if same row
else if (mouseRow > cheeseX)
{
for(int i = cheeseX; i <= mouseRow; i++)
{
clueCount++;
}//for loop closer
}//if mouse is larger
else
{
for(int i = mouseRow; i <= cheeseX; i++)
{
clueCount++;
}//for loop closer
}//else cheese is larger
clue = clue + clueCount;
if(mouseCol == cheeseY)
{
System.out.println("In same column as cheese!");
}//if same colum
if (mouseCol > cheeseY)
{
for(int i = cheeseY; i <= mouseCol; i++)
{
clueCount++;
}//for loop closer
}//if mouse is larger
else
{
for(int i = mouseCol; i <= cheeseY; i++)
{
clueCount++;
}//for loop closer
}//else cheese is larger
clue = clue + clueCount;
if(mousePage == cheeseZ)
{
System.out.println("In same page as cheese!");
}//if same page
if (mousePage > cheeseZ)
{
for(int i = cheeseZ; i <= mousePage; i++)
{
clueCount++;
}//for loop closer
}//if mouse is larger
else
{
for(int i = mousePage; i <= cheeseZ; i++)
{
clueCount++;
}//for loop closer
}//else cheese is larger
clue = clue + clueCount;
System.out.println("You are " + clue + " cells away from the cheese.");
System.out.println();
/*=================[Clue]=================*/
}while (gameOver == false);
if (win == true)
{
winQuotes = (int)(3 * Math.random()) + 1;
switch (winQuotes)
{
case 1:
System.out.println("You found the cheese! Now it's time to send you back, but don't worry. I'm sure we'll meet again soon.");
break;
case 2:
System.out.println("An excellent job, maybe you were meant to be a mouse all long. What, change you back? Oh fine.");
break;
default:
System.out.println("Congradulation, I don't think Captian Picard couldn't have done it better. Maybe I should pay him a visit.");
break;
}//win switch
}//if you won
if (lose == true)
{
loseQuotes = (int)(3 * Math.random()) + 1;
switch(loseQuotes)
{
case 1:
System.out.println("Well at least you fed a hungry cat right? Star Fleet would be so proud to have you on one of their ships.");
break;
case 2:
System.out.println("Oh come on, don't tell me you wore a red shirt before I brought you here.");
break;
default:
System.out.println("Maybe I should have brought Captian Janeway here instead, I still owe her for that punch to my face.");
break;
}//lose switch
}//if you lose
}//main closer
} //class closer
You never reinitialize your clue variable to 0 in your do/while loop. So, everytime you run through the loop, instead of setting clue to the current clue value, you keep adding to it (clue = clue + clueCount).
You aren't resetting clue to zero in the big do-while loop
So it's seems logical to me that the clues can't do anything but go higher, because it keep adding the new count to itself (clue = clue + clueCount)