How to fix Tic Tac Toe winner determination - java

Every time I run my Tic Tac Toe program I can create the board and do my first turn.
After the first turn, the game just ends as: "IT'S A DRAW", which is one of the three ending possibilities. This just happens before the computer can even make his own turn.
Another problem in my program is that the scanner user input limit(er) is not working (at the end of the code). If user inputs i.e a letter instead of int, the program crashes.
package newtictactoe;
import java.util.Scanner;
import java.util.Random;
public class NewTicTacToe {
public static final int DRAW = 0;
public static final int COMPUTER = 1;
public static final int PLAYER = 2;
public static int size;
public static char[][] board;
public static int score = 0;
public static Scanner scan = new Scanner(System.in);
/**
* Creates base for the game.
*
* #param args the command line parameters. Not used.
*/
public static void main(String[] args) {
System.out.println("Select board size");
System.out.print("[int]: ");
size = Integer.parseInt(scan.nextLine());
board = new char[size][size];
setupBoard();
int i = 1;
loop:
while (true) {
if (i % 2 == 1) {
displayBoard();
getMove();
} else {
computerTurn();
}
switch (isGameFinished()) {
case PLAYER:
System.err.println("YOU WIN!");
break loop;
case COMPUTER:
System.err.println("Computer WINS!\nYOU LOOSE!!");
break loop;
case DRAW:
System.err.println("IT'S A DRAW");
break loop;
}
i++;
}
}
private static int isGameFinished() {
if (isDraw()) {
return DRAW;
} else if (computerHasWon()) {
return COMPUTER;
} else if (playerHasWon()) {
return PLAYER;
}
return 0;
}
/**
* Checks for computer's win.
*
* #return if this game is won by computer.
*/
public static boolean playerHasWon() {
boolean hasWon = false;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
// check if 5 in a line
}
}
return hasWon;
}
/**
* Checks for player's win.
*
* #return if this game is won by computer.
*/
public static boolean computerHasWon() {
boolean hasWon = false;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
// check if 5 in a line
}
}
return hasWon;
}
/**
* Checks for draws.
*
* #return if this game is a draw
*/
public static boolean isDraw() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (board[i][j] == ' ') {
return false;
}
}
}
return true;
}
/**
* Displays the board.
*
*
*/
public static void displayBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.printf("[%s]", board[i][j]);
}
System.out.println();
}
}
/**
* Displays the board.
*
*
*/
public static void setupBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = ' ';
}
}
}
/*
* Checks if the move is allowed.
*
*
*/
public static void getMove() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.printf("ROW: [0-%d]: ", size - 1);
int x = Integer.parseInt(sc.nextLine());
System.out.printf("COL: [0-%d]: ", size - 1);
int y = Integer.parseInt(sc.nextLine());
if (isValidPlay(x, y)) {
board[x][y] = 'X';
break;
}
}
}
/*
* Randomizes computer's turn - where it inputs the mark 'O'.
*
*
*/
public static void computerTurn() {
Random rgen = new Random(); // Random number generator
while (true) {
int x = (int) (Math.random() * size);
int y = (int) (Math.random() * size);
if (isValidPlay(x, y)) {
board[x][y] = 'O';
break;
}
}
}
/**
* Checks if the move is possible.
*
* #param inX
* #param inY
* #return
*/
public static boolean isValidPlay(int inX, int inY) {
// Play is out of bounds and thus not valid.
if ((inX >= size) || (inY >= size)) {
return false;
}
// Checks if a play have already been made at the location,
// and the location is thus invalid.
return (board[inX][inY] == ' ');
}
These last two methods in the code check if the scanner input is valid but they don't work and I don't know why.
/**
* Checks if user input is valid
*
* #param scan
* #param prompt
* #return
*/
public static String getInput(Scanner scan, String prompt) {
System.out.print(prompt); // Tell user what to input
String text = "Enter one integer value i.e 5.";
while (true) { // Keeps on looping until valid input
text = scan.nextLine();
if (isInteger(text)) // Checks input is int
{
break; // Exit loop
}
System.out.print("Try again, " + prompt); // If invalid
}
return text; // Return valid user input
}
/**
* Checks if input string is int.
*
* #param str
* #return
*/
public static boolean isInteger(String str) {
try {
Integer.parseInt(str); // If this succeeds the input is int
return true;
} catch (NumberFormatException e) {
return false; // If not int
}
}
}

Your isGameFinished() method returns 0 by default (when the game is not over), but your DRAW constant is also 0. Try to change it to return (for example) -1 when the game is not over.
A nicer solution would be to have one method isGameFinished() that would return boolean to indicate if the game is over, and another method getWinner() which would return the winner (DRAW or COMPUTER or PLAYER), and will only be called if isGameFinished() returns true.
Your getMove method should catch NumberFormatException, which can be thrown by Integer.parseInt.

Related

How do I check which player moves in my connect four game?

I am trying to create a method/ while loop which checks to see which player moves. For now I check to see which play moves in a for loop. I am trying to make my code a bit more clear and concise. Here is the main method:
public static void main(String[] args) {
try (Scanner input = new Scanner(System.in)) {
int height = 6, width = 8, moves = height * width;
ConnectFour board = new ConnectFour(width, height);
System.out.println("Use 0-" + (width - 1) + " to choose a column.");
System.out.println(board);
for (int player = 0; moves-- > 0; player = 1 - player) { // Here is where i check to see who plays
char symbol = players[player];
board.chooseAndDrop(symbol, input);
System.out.println(board);
if (board.isWinningPlay()) {
System.out.println("Player " + symbol + " wins!");
return;
}
}
System.out.println("Game over, no winner.");
}
}
I was thinking more along the lines of:
int playerNb = 0;
while (thegamestarted)
{
if (playerNb == 0)
// Get user input
else
// Get second player input
// Process the input
// Change playerNb to 1 or 0
}
Below is the full code:
import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ConnectFour {
private static final char[] players = new char[] { 'X', 'O' };
private final int width, height;
private final char[][] grid;
private int lastCol = -1, lastTop = -1;
public ConnectFour(int width, int height) {
this.width = width;
this.height = height;
this.grid = new char[height][];
for (int h = 0; h < height; h++) {
Arrays.fill(this.grid[h] = new char[width], '.');
}
}
public String toString() {
return IntStream.range(0, this.width)
.mapToObj(Integer::toString)
.collect(Collectors.joining()) + "\n" +
Arrays.stream(this.grid)
.map(String::new)
.collect(Collectors.joining("\n"));
}
/**
* Prompts the user for a column, repeating until a valid
* choice is made.
*/
public void chooseAndDrop(char symbol, Scanner input) {
do {
System.out.print("\nPlayer " + symbol + " turn: ");
int col = input.nextInt();
if (! (0 <= col && col < this.width)) {
System.out.println("Column must be between 0 and " +
(this.width - 1));
continue;
}
for (int h = this.height - 1; h >= 0; h--) {
if (this.grid[h][col] == '.') {
this.grid[this.lastTop=h][this.lastCol=col] = symbol;
return;
}
}
System.out.println("Column " + col + " is full.");
} while (true);
}
/**
* Detects whether the last chip played was a winning move.
*/
public boolean isWinningPlay() {
if (this.lastCol == -1) {
throw new IllegalStateException("No move has been made yet");
}
char sym = this.grid[this.lastTop][this.lastCol];
String streak = String.format("%c%c%c%c", sym, sym, sym, sym);
return contains(this.horizontal(), streak) ||
contains(this.vertical(), streak) ||
contains(this.slashDiagonal(), streak) ||
contains(this.backslashDiagonal(), streak);
}
/**
* The contents of the row containing the last played chip.
*/
private String horizontal() {
return new String(this.grid[this.lastTop]);
}
/**
* The contents of the column containing the last played chip.
*/
private String vertical() {
StringBuilder sb = new StringBuilder(this.height);
for (int h = 0; h < this.height; h++) {
sb.append(this.grid[h][this.lastCol]);
}
return sb.toString();
}
/**
* The contents of the "/" diagonal containing the last played chip
* (coordinates have a constant sum).
*/
private String slashDiagonal() {
StringBuilder sb = new StringBuilder(this.height);
for (int h = 0; h < this.height; h++) {
int w = this.lastCol + this.lastTop - h;
if (0 <= w && w < this.width) {
sb.append(this.grid[h][w]);
}
}
return sb.toString();
}
/**
* The contents of the "\" diagonal containing the last played chip
* (coordinates have a constant difference).
*/
private String backslashDiagonal() {
StringBuilder sb = new StringBuilder(this.height);
for (int h = 0; h < this.height; h++) {
int w = this.lastCol - this.lastTop + h;
if (0 <= w && w < this.width) {
sb.append(this.grid[h][w]);
}
}
return sb.toString();
}
private static boolean contains(String haystack, String needle) {
return haystack.indexOf(needle) >= 0;
}
public static void main(String[] args) {
try (Scanner input = new Scanner(System.in)) {
int height = 6, width = 8, moves = height * width;
ConnectFour board = new ConnectFour(width, height);
System.out.println("Use 0-" + (width - 1) + " to choose a column.");
System.out.println(board);
for (int player = 0; moves-- > 0; player = 1 - player) {
char symbol = players[player];
board.chooseAndDrop(symbol, input);
System.out.println(board);
if (board.isWinningPlay()) {
System.out.println("Player " + symbol + " wins!");
return;
}
}
System.out.println("Game over, no winner.");
}
}
}
Its a bit difficult to tell what you want from your code, but the absolute simplest way to keep track of what player it is, is to keep track of the turn number, and check if it is even or odd with the modulus function
This is just a brief bit of psuedocode to show you how you can tell what the turn is with simple math. You will have to adapt it to your own needs. You can see that it will only be "Player 2"'s turn on an even turn number where the turn number divided by 2 has no remainder. Just remember to increment the turn after every move.
There's no "good" answer. You're the one writing the code, you can decide whose turn it is, you just have to keep track of it.
int turn = 1;
for ( ) {
if (turn % 2 == 0) {
System.out.println("Player 2");
} else {
System.out.println("Player 1");
}
turn++;
}

Printing out a triangle in java [duplicate]

This question already has an answer here:
java print a triangle
(1 answer)
Closed 6 years ago.
I have to write a program to print out a triangle using "*" via methods. I have to design it to ask the user for a number to represent the number of *'s at the base of the triangle. Then print out the triangle by passing that number to your printUpTriangle() method. The only thing I have an idea about is the actual code to make the triangle which is:
public class Triangle {
public static void triangle(int levels) {
if(levels == 0)
return;
triangle(levels - 1);
for(int y = 0; y < levels; y++) {
System.out.print("*");
}
System.out.println();
}
I have to write two methods: one to return a String containing n copies of s, concatenated in a row & another one that uses your makeRow() method. It should print a right triangle in which the base of the triangle is made of n copies of s, and the vertex of the triangle has a single copy of s on the right (both methods have an int & String as variables).
public static void main (String[] args) throws java.lang.Exception
{
makeTriangle(5);
// change the above line if you need to input the number (5) from the user
}
public static void makeTriangle(Integer base_size)
{
for(int x = 1; x < base_size + 1; x++)
{
System.out.print(makeRow(x, base_size));
System.out.println();
}
}
public static String makeRow(Integer row_num, Integer base)
{
String row = "";
for(int x = base; x >= 0; x--)
{
if (x < row_num) { row += "*"; }
else row += " ";
}
return row;
}
This makes a triangle with the "vertex of the triangle has a single copy of s on the right"
So it will print out
*
**
***
****
*****
public class Triangle {
public static void main(String[] args) {
printTriangle(10);
}
public static String makeRow(int n) {
return String.format("%1$-" + n + "s", "*").replace(" ", "*");
}
public static void printTriangle(int n) {
IntStream.rangeClosed(1, n).mapToObj(Triangle::makeRow).forEach(System.out::println);
}
}
You don't need two methods, just one toString method.
public class Triangle
{
private int width;
/**
This class describes triangle objects that can be displayed
as shapes like this:
*
**
***
*/
public class Triangle
{
private int width;
/**
Constructs a triangle.
#param aWidth the number of * in the last row of the triangle.
*/
public Triangle(int aWidth)
{
width = aWidth;
}
/**
Computes a string representing the triangle.
#return a string consisting of * and newline characters
*/
public String toString()
{
String r = "";
for (int i = 1; i <= width; i++)
{
// Make triangle row
for (int j = 1; j <= i; j++)
r = r + "*";
r = r + "\n";
}
return r;
}
}
And Tester class:
import java.util.Scanner;
/**
This program prints two triangles.
*/
public class TriangleRunner
{
public static void main(String[] args)
{
System.out.println("Please enter number");
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
Triangle test = new Triangle(i);
System.out.println(test);
}
}
EDIT Realized that the OP needed a RIGHT triangle. I mistakenly made an equilateral triangle. New output is shown below.
If you really have to have another method to print the triangle:
import java.util.Scanner;
public class ICanHasTriangle {
static Scanner input;
static String s = "*";
public static void main(String args[]) {
input = new Scanner(System.in);
System.out.print("How wide will your base be (Enter an integer): ");
int width = input.nextInt();
boolean valid = false;
while (!valid) {
if (width <= 0) {
System.out.println("ERROR. You must enter a positive integer!");
System.out.println();
System.out.print("Try again: ");
valid = false;
width = input.nextInt();
} else {
valid = true;
printUpTriangle(s, width);
}
}
}
public static String printUpTriangle(String s, int width) {
for (int i = 0; i <= width; i++) {
for (int j = 0; j < i + 1; j++) {
System.out.print(s);
}
System.out.println();
}
return s;
}
}
OUTPUT
How wide will your base be (Enter an integer): 0
ERROR. You must enter a positive integer!
Try again: 8
*
**
***
****
*****
******
*******
********
*********

How do I determine a winner in my Tic Tac Toe program

Earlier post: How do I make my tictactoe program scalable
I have tried to make a Tic Tac Toe program (human vs computer) scalable (the board size can be changed). I had major problems earlier but fixed most of them.
The game's rules are basic Tic Tac Toe but one different rule is that no matter how large the board is (when >= 5) the player or computer only need five marks in a row to win.
Now the only gamebreaking problem with my program is determining who wins the game. It is only possible that the game ends a 'draw' at the moment. (Also I have not implemented the ">= 5" yet).
Specific problem explanation is that I need to determine a winner and end screen for something like "computer wins" and/or "player wins".
package tictactoe;
import java.util.Scanner;
import java.util.Random;
public class TicTacToe {
public static int size;
public static char[][] board;
public static int score = 0;
public static Scanner scan = new Scanner(System.in);
/**
* Creates base for the game.
*
* #param args the command line parameters. Not used.
*/
public static void main(String[] args) {
System.out.println("Select board size");
System.out.print("[int]: ");
size = Integer.parseInt(scan.nextLine());
board = new char[size][size];
setupBoard();
int i = 1;
while (true) {
if (i % 2 == 1) {
displayBoard();
getMove();
} else {
computerTurn();
}
// isWon()
if (isDraw()) {
System.err.println("Draw!");
break;
}
i++;
}
}
/**
* Checks for draws.
*
* #return if this game is a draw
*/
public static boolean isDraw() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (board[i][j] == ' ') {
return false;
}
}
}
return true;
}
/**
* Displays the board.
*
*
*/
public static void displayBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.printf("[%s]", board[i][j]);
}
System.out.println();
}
}
/**
* Displays the board.
*
*
*/
public static void setupBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = ' ';
}
}
}
/*
* Checks if the move is allowed.
*
*
*/
public static void getMove() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.printf("ROW: [0-%d]: ", size - 1);
int x = Integer.parseInt(sc.nextLine());
System.out.printf("COL: [0-%d]: ", size - 1);
int y = Integer.parseInt(sc.nextLine());
if (isValidPlay(x, y)) {
board[x][y] = 'X';
break;
}
}
}
/*
* Randomizes computer's turn - where it inputs the mark 'O'.
*
*
*/
public static void computerTurn() {
Random rgen = new Random(); // Random number generator
while (true) {
int x = (int) (Math.random() * size);
int y = (int) (Math.random() * size);
if (isValidPlay(x, y)) {
board[x][y] = 'O';
break;
}
}
}
/**
* Checks if the move is possible.
*
* #param inX
* #param inY
* #return
*/
public static boolean isValidPlay(int inX, int inY) {
// Play is out of bounds and thus not valid.
if ((inX >= size) || (inY >= size)) {
return false;
}
// Checks if a play have already been made at the location,
// and the location is thus invalid.
return (board[inX][inY] == ' ');
}
}
You have already the loop to play, so, in each iteration, in the same way you check if the game isDraw(), check also if some of the players won:
while (true) {
if (i % 2 == 1) {
displayBoard();
getMove();
} else {
computerTurn();
}
// isWon()
if (isDraw()) {
System.err.println("Draw!");
break;
} else if (playerHasWon()){
System.err.println("YOU WIN!");
break;
} else if (computerHasWon()) {
System.err.println("Computer WINS!\nYOU LOOSE!!");
break;
}
i++;
}
After create the needed methods:
public static boolean playerHasWon() {
boolean hasWon = false;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
// check if 5 in a line
}
}
return hasWon ;
}
public static boolean computerHasWon() {
boolean hasWon = false;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
// check if 5 in a line
}
}
return hasWon ;
}
Next question of course is HOW DO I CREATE THIS METHODS?? dunno if you have problems with this, but doing a fast check here here and here you will find some ideas.
ADD ON:
In order to clarify, I would make a function returning an int instead booleans, to check if the game is finished using some constants:
private final int DRAW = 0;
private final int COMPUTER = 1;
private final int PLAYER = 2;
private int isGameFinished() {
if (isDraw()) return DRAW;
else if (computerHasWon()) return COMPUTER;
else if (playerHasWon()) return PLAYER;
}
Then simply check with a switch case (check here how to break the while insite the while)
loop: while (true) {
// other stufff
switch (isGameFinished()) {
case PLAYER:
System.err.println("YOU WIN!");
break loop;
case COMPUTER:
System.err.println("Computer WINS!\nYOU LOOSE!!");
break loop;
case DRW:
System.err.println("IT'S A DRAW");
break loop;
}

Unable to determine win condition in Tic Tac Toe

I have been trying to get my tic tac toe program to work for a while now.
At the moment I'm stuck in the win condition.
The game can now end as a draw but no player (human || computer) can win it.
I need to determine the winning conditions (horizontal, vertical, across) in playerHasWon but have no idea how to implement them.
import java.util.Scanner;
import java.util.Random;
public class NewTicTacToe {
public static final int DRAW = 0;
public static final int COMPUTER = 1;
public static final int PLAYER = 2;
public static final char PLAYER_MARK = 'X';
public static final char COMPUTER_MARK = 'O';
public static int size;
public static String[][] board;
public static int score = 0;
public static Scanner scan = new Scanner(System.in);
/**
* Creates base for the game.
*
* #param args the command line parameters. Not used.
*/
public static void main(String[] args) {
while (true) {
System.out.println("Select board size");
System.out.print("[int]: ");
try {
size = Integer.parseInt(scan.nextLine());
} catch (Exception e) {
System.out.println("You can't do that.");
continue;
}
break;
}
int[] move = {};
board = new String[size][size];
setupBoard();
int i = 1;
loop:
while (true) {
if (i % 2 == 1) {
displayBoard();
move = getMove();
} else {
computerTurn();
}
switch (isGameFinished(move)) {
case PLAYER:
System.err.println("YOU WIN!");
break loop;
case COMPUTER:
System.err.println("Computer WINS!\nYOU LOSE!");
break loop;
case DRAW:
System.err.println("IT'S A DRAW");
break loop;
}
i++;
}
}
private static int isGameFinished(int[] move) {
if (isDraw()) {
return DRAW;
} else if (playerHasWon(board, move, COMPUTER_MARK)) {
return COMPUTER;
} else if (playerHasWon(board, move, PLAYER_MARK)) {
return PLAYER;
}
return -1;
}
/**
* Checks for win.
*
* #param board
* #return if the game is won.
*/
public static boolean playerHasWon(String[][] board, int[] move,
char playerMark) { //playermark x || o
boolean hasWon = false;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
// check if 5 in a line
if (board[i][j].equals(playerMark)) {
score++;
} else {
score = 0;
}
if (score == 5) {
return true;
}
}
}
return hasWon;
}
/**
* Checks for draws.
*
* #return if this game is a draw
*/
public static boolean isDraw() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (board[i][j] == " ") {
return false;
}
}
}
return true;
}
/**
* Displays the board.
*
*
*/
public static void displayBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.printf("[%s]", board[i][j]);
}
System.out.println();
}
}
/**
* Displays the board.
*
*
*/
public static void setupBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = " ";
}
}
}
/*
* Takes in userinput and sends it to isValidPlay.
*
*
*/
public static int[] getMove() {
Scanner sc = new Scanner(System.in);
System.out.println("Your turn:");
while (true) {
try {
System.out.printf("ROW: [0-%d]: ", size - 1);
int x = Integer.parseInt(sc.nextLine());
System.out.printf("COL: [0-%d]: ", size - 1);
int y = Integer.parseInt(sc.nextLine());
if (isValidPlay(x, y)) {
board[x][y] = "" + PLAYER_MARK;
return new int[]{x, y};
}
} catch (Exception e) {
System.out.println("You can't do that.");
}
return null;
}
}
/*
* Randomizes computer's turn - where it inputs the mark 'O'.
*
*
*/
public static void computerTurn() {
Random rgen = new Random(); // Random number generator
while (true) {
int x = (int) (Math.random() * size);
int y = (int) (Math.random() * size);
if (isValidPlay(x, y)) {
board[x][y] = "" + COMPUTER_MARK;
break;
}
}
}
/**
* Checks if the move is possible.
*
* #param inX
* #param inY
* #return
*/
public static boolean isValidPlay(int inX, int inY) {
// Play is out of bounds and thus not valid.
if ((inX >= size) || (inY >= size)) {
return false;
}
// Checks if a play have already been made at the location,
// and the location is thus invalid.
return (board[inX][inY] == " ");
}
}
// End of file
You could use a different approach to check for victories. Maybe split in three parts? Horizontal, vertical, and diagonals?
I made some changes to your code to give an example:
public static boolean playerHasWon(String[][] board, int[] move,
String playerMark) { //playermark x || o
//Horizontal check
for (int i = 0; i < size; i++) {
if (board[i][0].equals(playerMark)) {
int j;
for (j = 1; j < size; j++) {
if (!board[i][j].equals(playerMark)) {
break;
}
}
if (j == size) {
return true;
}
}
}
//Vertical check
for (int i = 0; i < size; i++) {
if (board[0][i].equals(playerMark)) {
int j;
for (j = 1; j < size; j++) {
if (!board[j][i].equals(playerMark)) {
break;
}
}
if (j == size) {
return true;
}
}
}
//Diagonals
int i;
for (i = 0; i < size; i++) {
if (!board[i][i].equals(playerMark)) {
break;
}
}
if (i == size) {
return true;
}
for (i = 0; i < size; i++) {
if (!board[i][(size - 1) - i].equals(playerMark)) {
break;
}
}
if (i == size) {
return true;
}
return false;
}
Note that you have to change the playerMarks from char to String.
Also, I suggest displaying the board just before announcing who won. That way, if the computer wins, you can see its last move

Java Antwalk - 2D Arrays

There is a 2D array with dimensions 9x9. The ant starts in cell (5,5) , or the center. It moves randomly north, south, east, or west. The ant stops walking when it falls off the grid. The space where it falls is marked by an X. In the matrix, it should display the amount of times the ant visited each cell and the number of moves the ant took to fall off.
I'm not sure where to start or how to go about it. Like how to make the north, south, west, east methods.
Here's what I have so far.
public static void main(String [] args)
{
int [][] grid = new int[9][9];
for (int r = 0; r< grid.length; r++)
{
for (int c = 0 ; c<grid[0].length; c++)
{
grid[r][c] = 0;
}
}
boolean test = true;
while(test)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
}
else if (random == 2)
{
}
else if (random == 3)
{
}
else if (random == 4)
{
}
}
}
You've got the right idea, now what you want to do is move in the direction specified by random, and increment the value in your array. Here is how I would do it.
int count = 0;
int x = 4;
int y = 4; // arrays are 0 based
while(true)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
x--; // move left
}
else if (random == 2)
{
x++; // move right
}
else if (random == 3)
{
y--; // move down
}
else if (random == 4)
{
y++; // move up
}
if(x < 0 || y < 0 || x >= grid.length || y >= grid[x].length) break;
count++;
grid[x][y]++;
}
System.out.println(count); // number of moves before it fell
Here is a random walk of an ant on the grid. See comments in the code. The ant walks STEPS on a predefined size grid.
import java.util.Random;
public class Ants {
/** height and width of the grid */
public static final int HEIGHT = 9 ;
public static final int WIDTH = 9 ;
/** NOVAL means "no value" */
public static final int NOVAL = -1;
/** world directions */
public static final int NORTH = 0 ;
public static final int WEST = 1 ;
public static final int SOUTH = 2 ;
public static final int EAST = 3 ;
/** how many steps for ant to walk */
public static final int STEPS = 10;
/** where does the ant start it's walk */
public static final int START_X = 5;
public static final int START_Y = 5;
/** printing related */
public static final String ANT = "ANT";
private static final Random random = new Random();
/** grid for ant to walk on */
static int[] grid;
/** get height of the grid */
static int getHeight() {
return HEIGHT;
}
/** get width of the grid */
static int getWidth() {
return WIDTH;
}
/** size of the grid */
static int getSize() {
return getWidth()*getHeight();
}
/** coordinates are converted to one dimension */
/** #return index from coordinates. */
static int idx(int x, int y) {
return y*getWidth() + x;
}
/** get x coordinate of idx */
static int x(int idx) {
return idx % getWidth();
}
/** get y coordinate of idx */
static int y(int idx) {
return (idx - x(idx)) / getWidth();
}
/** get cell */
static int getCell(int idx) {
return grid[idx];
}
static int getCell(int x, int y) {
return getCell(
idx(x,y));
}
static void setCell(int idx, int value) {
grid[idx] = value;
}
/** init array with some value */
private static void initArr(int[] arr, int value) {
for (int i = 0; i < arr.length; i++) {
arr[i] = value;
}
}
/**
* #return adjancted cells indexes.
*/
public static int[] adjanctedTo(int idx) {
int[] adj = new int[4];
initArr(adj, NOVAL);
int x = x(idx);
int y = y(idx);
/** Is North available? */
if (y - 1 >= 0) {
adj[NORTH] = idx(x,y-1);
}
/** West? */
if (x - 1 >= 0) {
adj[WEST] = idx(x-1, y);
}
/** South? */
if (y + 1 < getHeight()) {
adj[SOUTH] = idx(x,y+1);
}
/** East? */
if (x + 1 < getWidth()) {
adj[EAST] = idx(x+1, y);
}
return adj;
}
/** picks random value from array */
public static int pick(int[] arr) {
int ret = NOVAL;
int idx = random.nextInt(4);
for (int i = idx;; i++) {
if (NOVAL != arr[i]) {
ret = arr[i];
break;
}
if (3 == i) {
/** cycle if not yet found a NOVAL value in array */
i = 0;
}
}
return ret;
}
public static void main(String[] args) {
/** init grid */
grid = new int[getSize()];
int nextStep = NOVAL;
int current = idx(START_X, START_Y);
setVisited(current);
for (int s = 0; s < STEPS; s++) {
System.out.println("STEP "+s);
System.out.println(
"Standing #" + position(current) + ".");
printGrid(current);
nextStep = pick(
adjanctedTo(current));
System.out.println(
"Moving to " + position(nextStep));
setVisited(current);
printGrid(nextStep);
current = nextStep;
}
}
public static void setVisited(int idx) {
setCell(idx, getCell(idx)+1);
}
public static String position(int idx) {
return idx+"("+x(idx) + ";" + y(idx) +")";
}
public static void printGrid(int antPosition) {
for (int x = 0; x < getWidth(); x++) {
for (int y = 0; y < getHeight(); y++) {
if (idx(x,y) == antPosition) {
System.out.print(ANT);
} else {
System.out.format(
"%2d|",
getCell(x,y));
}
}
System.out.println();
}
}
}
public static void main(String[] args) {
String[][] sim = ant(3,3);
for (int i = 0; i < sim.length; i++) {
for (int j = 0; j < sim[i].length; j++) {
System.out.print(sim[i][j] + " ");
}
System.out.println();
}
}
static String[][] ant(int x, int y) {
if(x<0||x>=9||y<0||y>=9){
return null;
}
int[] rn = {-1, 1}; //next ant random direction , you can include 0 if you wanted
String[][] mat = new String[9][9];
for (int i = 0; i < 9; i++) {
Arrays.fill(mat[i], "0");//fill array with 0 to avoid null default value
}
int a = x, b = y; // a and b are the Cartesian coordinates of the ant
while (true) {
mat[a][b] = String.valueOf(Integer.parseInt(mat[a][b]) + 1);
int newx = a + rn[(int) (Math.random() * rn.length)];
int newy = b + rn[(int) (Math.random() * rn.length)];
//these are the ant new coordinates , we have to check them before going to them
if (newx < 0 || newx >= 9 || newy < 0 || newy >= 9) {
mat[a][b] = "X";
return mat;
}
a = newx;
b = newy;
}
}

Categories