need some help with a maze solving program in java.
The program has to read a maze from a file, store it into an array, solve it, and display the solution in a drawing panel. I'm struggling storing it into an array, and I'm really unsure of how to move into solving it and displaying it. But if i could get some help on the array part to get into a groove, I'd really appreciate it.
Here is an example of an input file. I want it to work for any maze of this structure, (with +, -, S, E, and |). The first two numbers, (8, 10) represent the height and width, the # of rows and # of columns.
8 10
+-+-+-+-+-+-+-+-+-+
| |
+ +-+-+-+ +-+-+-+ +
| | | |
+ + +-+-+-+-+-+ + +
| | | | | |
+ + + +-+-+-+ + + +-+
| | | | | | | S|
+ + + + +-+ + + + +-+
| | | |E| | | |
+ + + +-+ +-+ + + +
| | | | | |
+ + +-+-+-+-+-+ + +
| | | |
+ +-+-+-+-+-+-+-+ +
| |
+-+-+-+-+-+-+-+-+-+
Here is my code so far:
import java.util.Arrays;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class MazeSolver {
// The name of the file describing the maze
static String mazefile;
static int width;
static int height;
public static void main(String[] args) throws FileNotFoundException {
if (handleArguments(args)) {
readMazeFile(mazefile);
DrawMaze.draw();
if (solveMaze())
System.out.println("Solved!");
else
System.out.println("Maze has no solution.");
}
else {
System.out.println("The arguments are invalid.");
}
}
// Handle the input arguments
static boolean handleArguments(String[] args) {
if (args.length > 4 || args.length < 1) {
System.out.println("There are too many or too few command line arguments");
return false;
}
if (args.length == 1) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
return true;
}
if (args.length == 2) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
int cellsize = Integer.parseInt(args[1]);
if (cellsize < 10) {
return false;
}
return true;
}
if (args.length == 3) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
int cellsize = Integer.parseInt(args[1]);
int borderwidth = Integer.parseInt(args[2]);
if (borderwidth < 5) {
return false;
}
return true;
}
if (args.length == 4) {
String mazefile = args[0];
File file = new File(mazefile);
if (!file.canRead()) {
return false;
}
int cellsize = Integer.parseInt(args[1]);
int borderwidth = Integer.parseInt(args[2]);
int sleeptime = Integer.parseInt(args[3]);
if (sleeptime < 0 || sleeptime > 10000) {
return false;
}
return true;
}
return false;
}
// Read the file describing the maze.
static char[][] readMazeFile(String mazefile) throws FileNotFoundException {
Scanner scanner = new Scanner(new File(mazefile));
height = scanner.nextInt();
width = scanner.nextInt();
int arrayHeight = 2 * height + 1;
int arrayWidth = 2 * width + 1;
char[][] mazeArrays = new char[arrayHeight][arrayWidth];
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
for (int row = 0; row < arrayHeight; row++) {
for (int col = 0; col < arrayWidth; col++) {
mazeArrays[row][col] = line.charAt(col);
}
}
}
return mazeArrays;
}
// Solve the maze.
static boolean solveMaze() {
return true;
}
}
I think I have the handling of command line arguments down. The readMazeFile method is where I'm currently struggling. I just can't wrap my head around storing the maze in an array and solving it.
Thanks!
The first thing to do is to work out a data structure for you to store the maze in. I suggest using a structure that makes the solving as easy as possible, even if printing is more complicated. Here is a simple example:
class Node {
private final int row;
private final int col;
private final List<Node> paths;
}
class Maze {
private final int rowCount;
private final int colCount;
private final List<Node> nodes;
private Node start;
private Node end;
}
This, in my view, is going to be more useful than something like an array. An array would make it easy to print the maze but that's not the most difficult part of the operation. A path finding algorithm needs to be able to easily get the paths from any position which this data structure allows.
You asked for some help on reading the maze. I suggest making the reading method a static 'builder' method inside Maze. In general the structure will be something like:
class Maze {
public static Maze buildMaze(String mazeFile) {
// read row & col size from file
Maze maze = new Maze(rows, cols);
// skip first line (invariant)
for (int row = 0; row < rows; row++) {
// get next 2 lines (for horizontal & vertical paths)
for (int col = 0; col < cols; col++) {
// get corresponding horizontal wall or space
if (isHorizontalPath) {
maze.getNode(row,col).addHorizontalPath();
}
if (hasVerticalPath) {
maze.getNode(row, col).addVerticalPath();
}
// check for S and E
if (isStart) {
maze.setStart(row, col);
} else if (isEnd) {
maze.setEnd(row, col);
}
}
}
return maze;
}
}
Related
ListTopVisitedSites(sites, 5) is supposed to return the following output:
www.google.com | 4
www.aol.com | 3
www.microsoft.com | 3
www.amazon.com | 3
www.facebook.com | 3
I am trying to print the top 5 elements. If multiple elements have the same quantity, they should be ordered by recency - (recently added). Also, I need to print an empty array of type string for no value.
Which part am I missing, or have coded incorrectly? All the methods and their parameters should remain the same, as I am supposed to keep the time complexity as N2 and space complexity as 1.
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
class SiteStats {
private String url;
private int numVisits;
public SiteStats(String url, int numVisits) {
this.url = url;
this.numVisits = numVisits;
}
public int getNumVisits() {
return this.numVisits;
}
public String getUrl() {
return this.url;
}
public void setNumVisits(int updatedNumVisits) {
this.numVisits = updatedNumVisits;
}
public String toString() {
return this.url + " | " + this.numVisits;
}
}
public class PartBSolution {
private static Queue<SiteStats> sites = new LinkedList<SiteStats>();
public static void listTopVisitedSites(Queue<SiteStats> sites, int n) {
sortQueue(sites);
while(sites.isEmpty()== false)
{
System.out.println(sites.peek() + " ");
sites.poll();
}
}
public static void insertMaxToRear(Queue<SiteStats> sites,
int max_index)
{
SiteStats max_value = null;
int s = sites.size();
for (int i = 0; i < s; i++)
{
SiteStats current = sites.peek();
sites.poll();
if (i != max_index)
sites.add(current);
else
max_value = current;
}
sites.add(max_value);
}
public static void sortQueue(Queue<SiteStats> sites)
{
for(int i = 1; i <= sites.size(); i++)
{
int max_index = maxIndex(sites,sites.size() - i);
insertMaxToRear(sites, max_index);
}
}
public static int maxIndex(Queue<SiteStats> sites,
int sortIndex)
{
int max_index = -1;
int max_value = 0;
int s = sites.size();
for (int i = 0; i < s; i++)
{
SiteStats current = sites.peek();
sites.poll();
if (current.getNumVisits() >= max_value && i <= sortIndex)
{
max_index = i;
max_value = current.getNumVisits();
}
sites.add(current);
}
return max_index;
}
public static void updateCount(String url) {
boolean flag=false;
int size2=sites.size();
for(int i = 0; i < size2 ; i++)
{
SiteStats temp=sites.peek();
sites.poll();
if(temp.getUrl().equals(url))
{
temp.setNumVisits(temp.getNumVisits()+1);
flag=true;
sites.add(temp);
break;
}
sites.add(temp);
}
if(!flag)
sites.add(new SiteStats(url,1));
}
public static void main(String[] args) {
String[] visitedSites = { "www.google.com", "www.google.com", "www.facebook.com", "www.aol.com", "www.google.com", "www.youtube.com",
"www.facebook.com", "www.aol.com", "www.facebook.com", "www.google.com", "www.microsoft.com", "www.9gag.com", "www.netflix.com",
"www.netflix.com", "www.9gag.com", "www.microsoft.com", "www.amazon.com", "www.amazon.com", "www.uber.com", "www.amazon.com",
"www.microsoft.com", "www.aol.com" };
for (String url : visitedSites) {
updateCount(url);
}
listTopVisitedSites(sites, 5);
}
}
/**
www.google.com | 4
www.aol.com | 3
www.microsoft.com | 3
www.amazon.com | 3
www.facebook.com | 3
*/
The parameter n that you pass into listTopVisitedSites(sites, 5); is never used again, so you can not expect it to only list the 5
You did not write the logic for parameter n of listTopVisitedSites. Please find the updated one.
public static void listTopVisitedSites(Queue<SiteStats> sites, int n) {
sortQueue(sites);
int iterate = 1;
while (sites.isEmpty() == false && iterate <= n) {
System.out.println(sites.peek() + " ");
sites.poll();
iterate++;
}
}
I have a scenario, in which every timeslot has a profit and muliple jobs to choose from. I need to select the jobs at each time slot such that overall maximum profit is obtained. I require the maximum profit obtained and the schedule.
The only thing I can think of is to try for every comibnation using bruteforce. How can I solve this problem effectively.Is there any way I can do it better by using specific algorithm or data structure?
In the below example , any of the jobs J1,J2,J4 can be selected for timeslot1. Similarly for other time slots any one or none of the jobs can be selected. Only one job can be selected for a particular timeslot. If a job is done in one time slot, it cannot be done again.
Eg. If j1 is done in TS1, it cannot be picked again in TS2
+----------+--------+----------------------+
| TimeSlot | Profit | Possible Job |
+----------+--------+----------------------+
| 1 | 50 | J1 or J2 or J4 |
| 2 | 100 | J1 |
| 3 | 20 | J2 |
| 4 | 60 | J5 or J4 |
| 5 | 15 | J1 or J2 or J3 or J6 |
+----------+--------+----------------------+
This can be solved optimally by weighted maximum matching in bipartite graph.
In here, your graph is G=(U,V,E), where:
U = {1, 2, ...., n} // time slots
V = {J1, J2, ..., J_m} // jobs
E = { (i,J) | if job J can be done in time i }
w(i,J) = profit(i)
A maxmum matching in the above graph is translated directly to an optimal solution, by performing task J in timeslot i iff the maximum matching matched node J with node i.
public class JobProfitMaximizer {
private int numberOfJobs;
private Job[] jobs;
private int maxProfit;
public class JobComparator implements Comparator<Job> {
#Override
public int compare(Job arg0, Job arg1) {
if (arg0.end <= arg1.end)
return -1;
else
return 1;
}
}
public JobProfitMaximizer() {
numberOfJobs = 0;
maxProfit = 0;
}
private void printJobProfiles() {
for (Job j : jobs) {
System.out.println(j.start + " " + j.end + " " + j.profit);
}
}
private void createJobProfiles() {
jobs = new Job[numberOfJobs];
File inputFile = new File("***Filepath***********");
Scanner sc = null;
int jobCounter = 0;
try {
sc = new Scanner(inputFile);
while (sc.hasNextLine()) {
String s = sc.nextLine();
String[] profileOfJob = s.split(" ");
int start = Integer.parseInt(profileOfJob[1]);
int end = Integer.parseInt(profileOfJob[2]);
int profit = Integer.parseInt(profileOfJob[3]);
jobs[jobCounter] = new Job(start, end, profit);
jobCounter = jobCounter + 1;
}
} catch (FileNotFoundException e) {
System.out.println("The file is not present");
} finally {
try {
if (sc != null)
sc.close();
} catch (Exception f) {
System.out.println(f.getMessage());
}
}
}
private void setNumberOfJobs() {
File inputFile = new File("***Filepath***********");
Scanner sc = null;
int countOfJobs = 0;
try {
sc = new Scanner(inputFile);
while (sc.hasNextLine()) {
countOfJobs = countOfJobs + 1;
sc.nextLine();
}
numberOfJobs = countOfJobs;
System.out.println(numberOfJobs);
} catch (FileNotFoundException e) {
System.out.println("The file is not present");
} finally {
try {
if (sc != null)
sc.close();
} catch (Exception f) {
System.out.println(f.getMessage());
}
}
}
private void sortJobsOnFinishTimes() {
JobComparator jc = new JobComparator();
Arrays.sort(jobs, jc);
}
private void calculateMaximumProfit() {
int[] T = new int[numberOfJobs];
T[0] = jobs[0].profit;
for (int i = 1; i < numberOfJobs; i++) {
T[i] = Math.max(T[i - 1], jobs[i].profit);
for (int j = i - 1; j >= 0; j--) {
if (jobs[j].end <= jobs[i].start) {
T[i] = Math.max(T[i], T[j] + jobs[i].profit);
break;
}
}
}
int currentMaxProfitValue = T[0];
for (int m : T) {
if (m > currentMaxProfitValue) {
currentMaxProfitValue = m;
}
}
maxProfit = currentMaxProfitValue;
}
public static void main(String args[]) {
JobProfitMaximizer j = new JobProfitMaximizer();
j.setNumberOfJobs();
j.createJobProfiles();
j.sortJobsOnFinishTimes();
j.calculateMaximumProfit();
System.out.println("The maximum profit is " + j.maxProfit);
}
}
Is there a way to "extract" individual strings from an ArrayList?
I have stored strings in an ArrayList and want to print them to the console.
I know that I can use a for-loop but it isn't quite that simple. I'm trying to create a column based print and I use a method (Created by "CandiedOrange" here on stack overflow) that takes strings separated by commas as input.
What it basically does is; It creates column spacing based on the length of strings in each column. (All credit to "CandiedOrange")
List<List<String>> lines = new ArrayList<>();
List<Integer> maxLengths = new ArrayList<>();
int numColumns = -1;
public Columns addLine(String... line) {
if (numColumns == -1){
numColumns = line.length;
for(int i = 0; i < numColumns; i++) {
maxLengths.add(0);
}
}
if (numColumns != line.length) {
throw new IllegalArgumentException();
}
for(int i = 0; i < numColumns; i++) {
maxLengths.set( i, Math.max( maxLengths.get(i), line[i].length() ) );
}
lines.add( Arrays.asList(line) );
return this;
}
The number of columns I want to print is unknown during compile time because the user enters the number of columns 1-5 during run time. So I figured I could use ArrayLists for the rows and use the addLine() method with each of the arraylists for the rows.
If there Is a better way of solving this, I'd be more than happy to know.
EDIT:
From the start:
I'm creating a Yahtzee game with 1-5 players. Each Player is defined by instances of the class "Player"
public class Player {
private String name;
private int ones;
private int twos;
private int threes;
private int fours;
private int fives;
private int sixes;
private int threeofakind;
private int fourofakind;
private int fullhouse;
private int smallstraight;
private int largestraight;
private int chance;
private int yahtzee;
private int totalscore;
public int getOnes() {
return ones;
}
public void setOnes(int ones) {
this.ones = ones;
}
public int getTwos() {
return twos;
}
public void setTwos(int twos) {
this.twos = twos;
}
public int getThrees() {
return threes;
}
public void setThrees(int threes) {
this.threes = threes;
}
public int getFours() {
return fours;
}
public void setFours(int fours) {
this.fours = fours;
}
public int getFives() {
return fives;
}
public void setFives(int fives) {
this.fives = fives;
}
public int getSixes() {
return sixes;
}
public void setSixes(int sixes) {
this.sixes = sixes;
}
public int getThreeofakind() {
return threeofakind;
}
public void setThreeofakind(int threeofakind) {
this.threeofakind = threeofakind;
}
public int getFourofakind() {
return fourofakind;
}
public void setFourofakind(int fourofakind) {
this.fourofakind = fourofakind;
}
public int getFullhouse() {
return fullhouse;
}
public void setFullhouse(int fullhouse) {
this.fullhouse = fullhouse;
}
public int getSmallstraight() {
return smallstraight;
}
public void setSmallstraight(int smallstraight) {
this.smallstraight = smallstraight;
}
public int getLargestraight() {
return largestraight;
}
public void setLargestraight(int largestraight) {
this.largestraight = largestraight;
}
public int getChance() {
return chance;
}
public void setChance(int chance) {
this.chance = chance;
}
public int getYahtzee() {
return yahtzee;
}
public void setYahtzee(int yahtzee) {
this.yahtzee = yahtzee;
}
public int getTotalscore() {
return totalscore;
}
public void setTotalscore(int totalscore) {
this.totalscore = totalscore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I'm implementing MVC structure (to the best of my ability) which means that I have a View class with a method to display the main console column scoreboard. (Method unfinished)
public void displayMainScoreBoard(ArrayList<Player> playerList) {
Columns col = new Columns(); //Instance of column class.
ArrayList<String> Name = new ArrayList<>();
ArrayList<Integer> Ones = new ArrayList<>();
ArrayList<Integer> Twos = new ArrayList<>();
ArrayList<Integer> Threes = new ArrayList<>();
ArrayList<Integer> Fours = new ArrayList<>();
ArrayList<Integer> Fives = new ArrayList<>();
ArrayList<Integer> Sixes = new ArrayList<>();
ArrayList<Integer> Threeofakind = new ArrayList<>();
ArrayList<Integer> Fourofakind = new ArrayList<>();
ArrayList<Integer> Fullhouse = new ArrayList<>();
ArrayList<Integer> Smallstraight = new ArrayList<>();
ArrayList<Integer> Largestraight = new ArrayList<>();
ArrayList<Integer> Chance = new ArrayList<>();
ArrayList<Integer> Yahtzee = new ArrayList<>();
ArrayList<Integer> Totalscore = new ArrayList<>();
for (Player p : playerList) { //For every player, append their category data.
Name.add(p.getName());
Ones.add(p.getOnes());
Twos.add(p.getTwos());
Threes.add(p.getThrees());
Fours.add(p.getFours());
Fives.add(p.getFives());
Sixes.add(p.getSixes());
Threeofakind.add(p.getThreeofakind());
Fourofakind.add(p.getFourofakind());
Fullhouse.add(p.getFullhouse());
Smallstraight.add(p.getSmallstraight());
Largestraight.add(p.getLargestraight());
Chance.add(p.getChance());
Yahtzee.add(p.getYahtzee());
Totalscore.add(p.getTotalscore());
}
}
And heres CandiedOrange's full Column class. (Again, I claim no rights to his code.)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Columns {
List<List<String>> lines = new ArrayList<>();
List<Integer> maxLengths = new ArrayList<>();
int numColumns = -1;
public Columns addLine(String... line) {
if (numColumns == -1){
numColumns = line.length;
for(int i = 0; i < numColumns; i++) {
maxLengths.add(0);
}
}
if (numColumns != line.length) {
throw new IllegalArgumentException();
}
for(int i = 0; i < numColumns; i++) {
maxLengths.set( i, Math.max( maxLengths.get(i), line[i].length() ) );
}
lines.add( Arrays.asList(line) );
return this;
}
public void print(){
System.out.println( toString() );
}
public String toString(){
String result = "";
for(List<String> line : lines) {
for(int i = 0; i < numColumns; i++) {
result += pad( line.get(i), maxLengths.get(i) + 1 );
}
result += System.lineSeparator();
}
return result;
}
private String pad(String word, int newLength){
while (word.length() < newLength) {
word += " ";
}
return word;
}
}
How can I pass the Strings of my ArrayLists in my view to the addLine() Method?
I believe you should not be using that Columns class at all.
Most of your lists are numbers rather than strings. Numbers are best displayed right-justified. And the only string you have in each of the rows you want to display is the player name.
So instead of copying all the data to various lists, and assuming that for most of the numbers you have a reasonable width that they will not pass (4 digits? 6 digits?), then your task becomes:
Find the longest name in the list
Display each player such that the name is padded to accomodate the longest name found.
You could add these as methods to the Player class, so finding the maximal name length of a given list of players:
public static int maxNameLength( List<? extends Player> players ) {
int maxLength = 0;
for ( Player player : players ) {
int currLength = player.getName().length();
if ( currLength > maxLength ) {
maxLength = currLength;
}
}
return maxLength;
}
Now, displaying the current player in a properly padded way can be done using String.format, which uses a Formatter.
For the sake of brevity, suppose I just want to display the name, Yahtzee and total score. You'll have a method like this in Player:
public String getScoreLine( int maxLength ) {
String format = "%-" + maxLength + "s %6d %6d";
return String.format( format, getName(), getYahtzee(), getTotalscore() );
}
What the first part does is create a left-justified field for the string. So if maxLength is, say, 20, the format will be %-20s %6d %6d. The numbers will be displayed right-justified in fields 6 characters wide, the name, left-justified and padded to 20 characters.
Now you can loop on your list and display it like:
int maxNameLength = Player.maxNameLength( playerList );
for ( Player p : playerList ) {
System.out.println( p.getScoreLine( maxNameLength ) );
}
Note: if you want to put the getScoreLine method in your View rather than in the Player class (since you are trying to do MVC), you will need to give it the player as a parameter.
...that takes strings separated by commas as input.
Technically, it takes an array (more in this Java tutorial on varargs). But Java lets you create that array automatically when calling it with discrete arguments.
Since it accepts an array, and you have an ArrayList, you can easily get an array to pass to it, using toArray(T[]):
List<List<String>> linesToAdd = /*...*/;
// ...
for (List<String> line : linesToAdd) {
addLine(line.toArray(new String[line.size()]));
}
That said, it would be trivial (and a good coding exercise) to modify addLine to accept List<String> directly.
I followed the advice not to use the column class, even though I'd like to have tried using it. I semi-hardcoded the solution.
playerList is the list of players present in the game. and categories is obtained from another class to check which categories are pickable when scoring. (Displayed as X when unavailable and O when pickable.)
public void displayMainScoreBoard(ArrayList<Player> playerList, ArrayList<Boolean> categories) {
List<String> Name = new ArrayList<>();
List<String> Ones = new ArrayList<>();
List<String> Twos = new ArrayList<>();
List<String> Threes = new ArrayList<>();
List<String> Fours = new ArrayList<>();
List<String> Fives = new ArrayList<>();
List<String> Sixes = new ArrayList<>();
List<String> Threeofakind = new ArrayList<>();
List<String> Fourofakind = new ArrayList<>();
List<String> Fullhouse = new ArrayList<>();
List<String> Smallstraight = new ArrayList<>();
List<String> Largestraight = new ArrayList<>();
List<String> Chance = new ArrayList<>();
List<String> Yahtzee = new ArrayList<>();
List<String> Totalscore = new ArrayList<>();
for (Player p : playerList) { //For every player, append their category data.
Name.add(p.getName());
Ones.add(String.valueOf(p.getOnes()));
Twos.add(String.valueOf(p.getTwos()));
Threes.add(String.valueOf(p.getThrees()));
Fours.add(String.valueOf(p.getFours()));
Fives.add(String.valueOf(p.getFives()));
Sixes.add(String.valueOf(p.getSixes()));
Threeofakind.add(String.valueOf(p.getThreeofakind()));
Fourofakind.add(String.valueOf(p.getFourofakind()));
Fullhouse.add(String.valueOf(p.getFullhouse()));
Smallstraight.add(String.valueOf(p.getSmallstraight()));
Largestraight.add(String.valueOf(p.getLargestraight()));
Chance.add(String.valueOf(p.getChance()));
Yahtzee.add(String.valueOf(p.getYahtzee()));
Totalscore.add(String.valueOf(p.getTotalscore()));
}
boolean checkones = categories.get(0); //Checkers for which categories are available to score in.
boolean checktwos = categories.get(1);
boolean checkthrees = categories.get(2);
boolean checkfours = categories.get(3);
boolean checkfives = categories.get(4);
boolean checksixes = categories.get(5);
boolean checkthreeofkind = categories.get(6);
boolean checkfourofkind = categories.get(7);
boolean checkfullhouse = categories.get(8);
boolean checksmallstraight = categories.get(9);
boolean checklargestraight = categories.get(10);
boolean checkchance = categories.get(11);
boolean checkyahtzee = categories.get(12);
System.out.println("| "+ "| | Name " + stringBuilder(Name));
System.out.println("|" + isPickable(checkones) + "|1. | Ones " + stringBuilder(Ones));
System.out.println("|" + isPickable(checktwos) + "|2. | Twos " + stringBuilder(Twos));
System.out.println("|" + isPickable(checkthrees) + "|3. | Threes " + stringBuilder(Threes));
System.out.println("|" + isPickable(checkfours) + "|4. | Fours " + stringBuilder(Fours));
System.out.println("|" + isPickable(checkfives) + "|5. | Fives " + stringBuilder(Fives));
System.out.println("|" + isPickable(checksixes) + "|6. | Sixes " + stringBuilder(Sixes));
System.out.println("|" + isPickable(checkthreeofkind) + "|7. | Three of a kind " + stringBuilder(Threeofakind));
System.out.println("|" + isPickable(checkfourofkind) + "|8. | Four of a kind " + stringBuilder(Fourofakind));
System.out.println("|" + isPickable(checkfullhouse) + "|9. | Full House " + stringBuilder(Fullhouse));
System.out.println("|" + isPickable(checksmallstraight) + "|1. | Small Straight " + stringBuilder(Smallstraight));
System.out.println("|" + isPickable(checklargestraight) + "|11.| Large Straight " + stringBuilder(Largestraight));
System.out.println("|" + isPickable(checkchance) + "|12.| Chance " + stringBuilder(Chance));
System.out.println("|" + isPickable(checkyahtzee) + "|13.| Yahtzee " + stringBuilder(Yahtzee));
System.out.println("| "+ "| | Total Score " + stringBuilder(Totalscore));
}
/*
* Method for creating the lines for the scoreboard.
*/
public String stringBuilder(List<String> arrIn) {
StringBuilder sb = new StringBuilder();
for (String s : arrIn) {
sb.append("|");
sb.append(s);
sb.append(pad(s));
}
return sb.toString();
}
/*
* Method for padding the spaces between columns.
*/
public String pad(String s) {
int space = 15;
int sLength = s.length();
String retPad = "";
int temp = space - sLength;
for (int i = 0; i <= temp ; i++) {
retPad += " ";
}
return retPad;
}
public String isPickable(boolean b) {
if (b == true) {
return "O";
}
else {
return "X";
}
}
Gives this print out:
| | | Name |one |two |three
|X|1. | Ones |0 |0 |0
|X|2. | Twos |0 |0 |0
|X|3. | Threes |0 |0 |0
|X|4. | Fours |0 |0 |0
|X|5. | Fives |0 |0 |0
|X|6. | Sixes |0 |0 |0
|X|7. | Three of a kind |0 |0 |0
|X|8. | Four of a kind |0 |0 |0
|X|9. | Full House |0 |0 |0
|X|1. | Small Straight |0 |0 |0
|X|11.| Large Straight |0 |0 |0
|X|12.| Chance |0 |0 |0
|X|13.| Yahtzee |0 |0 |0
| | | Total Score |0 |0 |0
This way looks nice as long as a user doesn't enter a ridiculously long name. This can be fixed by asking the user to enter a shorter name (nick name).
Anyway, thanks for your help!
Since my last text and question was very vague here is my source as of now and a clearer question. It is all about the padding now.
Here is my code up to now:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
public class makeTable {
static ArrayList<String> val1 = new ArrayList<>(Arrays.asList("field1", "field1val2", "field1val3"));
static ArrayList<String> val2 = new ArrayList<>(Arrays.asList("field2", "field2val2", "field2val3"));
static int col1=15;
static int col2=15;
public static void main(String arg[]) {
BufferedWriter writeTable = null;
try {
writeTable = new BufferedWriter(new FileWriter("C:/testtable.txt"));
//Anfang erste Zeile
writeTable.write("+ ");
for (int i = 0; i < col1; i++){
writeTable.write("-");
}
writeTable.write(" + ");
for (int i = 0; i < col2; i++){
writeTable.write("-");
}
writeTable.write(" +");
writeTable.newLine();
//Ende erste Zeile
for (int i = 0; i < val1.size(); i++){
writeTable.write("| " + val1.get(i) + " "+ " + " +" "+ val2.get(i) + " "+ " |");
writeTable.newLine();
writeTable.write("+ ");
for (int j = 0; j < col1; j++){
writeTable.write("-");
}
writeTable.write(" + ");
for (int m = 0; m < col2; m++){
writeTable.write("-");
}
writeTable.write(" +");
writeTable.newLine();
}
} catch (IOException e) {
System.err.println(e);
} finally {
if (writeTable != null) {
try {
writeTable.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
}
}
Now I need to add a padding so that the result looks like :
+ -------------- + -------------- +
| field1 | filed2 |
+ -------------- + -------------- +
| field1val2 | field2val2 |
+ -------------- + -------------- +
and so on. It need to be centered. I can only think of adding something like val1.get(i).length() /2 and that is the amount of " " to add.... but how can I do that?
I cannot use other libraries (3rd party ones).
Here are the results of your program after I centered the text.
+ -------------- + -------------- +
| field1 + field2 |
+ -------------- + -------------- +
| field1val2 + field2val2 |
+ -------------- + -------------- +
| field1val3 + field2val3 |
+ -------------- + -------------- +
Here are the changes I made.
The biggest thing that I did was break your monolithic code into methods. By writing small methods, you can break your larger task into smaller tasks. The smaller tasks are easier to code.
A class name starts with a capital letter. I renamed makeTable to MakeTable.
I changed your code to use the List interface, rather than the ArrayList class. By using the interface, it makes it easier in the future to change the type of List. I can use a LinkedList by changing 2 lines of your code.
The main method now just creates the output. I couldn't write directly to the C drive on my Windows 8.1 laptop. I had to create the file in the same directory as the code.
The writeDashedLine method writes a dashed line. I use the code in 2 places, but by putting the code into a method, I only had to write the code once.
The writeDashes method writes the dashes part of a dashed line. Again, I use the code in 2 places, but by putting the code into a method, I only had to write the code once.
The writeValueLine method writes the values on a line. I use the code in one place, but to be consistent with the writeDashedLine method, I wrote a method for the code.
The rest of the methods are what I wrote to center text. First, I found the longest value in the 2 lists of values. Next, I added the 4 characters of padding. Next, I centered the text by adding padding to the front and the back of the String.
Study these methods so you can do this type of task in the future.
Here's the formatted code.
package com.ggl.testing;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MakeTable {
static List<String> val1 = new ArrayList<>(Arrays.asList("field1",
"field1val2", "field1val3"));
static List<String> val2 = new ArrayList<>(Arrays.asList("field2",
"field2val2", "field2val3"));
static int length = getLongestValue(val1, val2) + 4;
public static void main(String arg[]) {
BufferedWriter writeTable = null;
try {
writeTable = new BufferedWriter(new FileWriter("testtable.txt"));
writeDashedLine(writeTable);
writeTable.newLine();
// Ende erste Zeile
for (int i = 0; i < val1.size(); i++) {
writeValueLine(writeTable, val1.get(i), val2.get(i));
writeTable.newLine();
writeDashedLine(writeTable);
writeTable.newLine();
}
} catch (IOException e) {
System.err.println(e);
} finally {
if (writeTable != null) {
try {
writeTable.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
}
public static void writeDashedLine(BufferedWriter writeTable)
throws IOException {
// Anfang erste Zeile
writeTable.write("+ ");
writeDashes(writeTable);
writeTable.write(" + ");
writeDashes(writeTable);
writeTable.write(" +");
}
public static void writeDashes(BufferedWriter writeTable)
throws IOException {
for (int i = 0; i < length; i++) {
writeTable.write("-");
}
}
public static void writeValueLine(BufferedWriter writeTable, String value1,
String value2) throws IOException {
writeTable.write("| " + centerText(value1, length) + " + "
+ centerText(value2, length) + " |");
}
public static String centerText(String text, int length) {
int textLength = text.length();
if (textLength > length) {
return text.substring(0, length);
} else if (textLength == length) {
return text;
} else {
int diff1 = (length - textLength) / 2;
int diff2 = length - textLength - diff1;
return getPadding(' ', diff1) + text + getPadding(' ', diff2);
}
}
public static String getPadding(char pad, int length) {
String padding = "";
for (int i = 0; i < length; i++) {
padding += pad;
}
return padding;
}
public static int getLongestValue(List<String> val1, List<String> val2) {
int length = 0;
for (String s : val1) {
length = Math.max(length, s.length());
}
for (String s : val2) {
length = Math.max(length, s.length());
}
return length;
}
}
In the code below change append with StringBuilder with BufferedWriter.
public void appendCentered(StringBuilder sb, String s, int width) {
if (s.length() > width) {
s = s.substring(0, width);
}
int spaces = width - s.length();
int before = spaces / 2;
int after = spaces - before; // Could be 1 more than 'before'.
appendSpaces(sb, before);
sb.append(s);
appendSpaces(sb, after);
}
public void appendSpaces(StringBuilder sb, int width) {
while (width-- > 0) {
sb.append(' ');
}
}
I have a problem, I am not looking for answers to my problem I would like some help finding why my array even though specified in main unders switch: case1, case2, case3. I used a for loops with an array that stops at the 5th iteration. However when I run the program it only runs once, am I specifying correctly to make it run 5 times or should it be declared another way? thanks in advance. I should also include there are no errors reported by eclipse at this time until it is ran and only after the first input.
The text files contains
##B##
#---#
#-M-#
#---#
##B##
##B##########
#-----------#
#-----------#
#-----------B
#-----------#
#------M----#
#-----------#
#-----------#
#-----------#
#-----------#
#-----------#
#-----------#
#############
##B#####
#------#
#-M----#
#------#
#------#
#------#
#------#
#####B##
The island maps can be found here
[http://rapidshare.com/share/9704FE33EFF98F1C1E71F6F1DF2DC0D4]
This is the array (int i=0;i<5;i++) however I do not think this is the problem, I can also provide the text files if needed
This is the console out
CS1181 Mouse Island
1. mouseIsland1.txt
2. mouseIsland2.txt
3. mouseIsland3.txt
9. Exit
Please make your selection: 2
Filename: mouseIsland2.txt
Bridge1: 0,0
Bridge2: 0,0
Mouse: 0,0
OUCH! The Mouse fell into the water and died at: 1|1
01
0100000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
0000000000000
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at MouseEscape.runMouseIsland(MouseEscape.java:349)
at MouseEscape.main(MouseEscape.java:71)
End console
import java.io.File;
import java.util.Scanner;
public class MouseEscape {
public static Scanner input = new Scanner(System.in);
public static MouseEscape island1;
public static MouseEscape island2;
public static MouseEscape island3;
private String islandTxt;
private boolean moveDebug;
private int mouseEscaped;
private int mouseDrowned;
private int mouseStarved;
private int islandRows;
private int [] islandCols;
private int runCount;
private int [][] mousePosition;
private int [][] bridgePosition;
private int [][] islandIntArray;
private char [][] islandCharArray;
// main
// Allows the user to select which mouse island map to simulate
public static void main(String[] args) throws Exception
{
System.out.println("CS1181 Mouse Island");
int choice = 0, continueRun = 1;
boolean runResponce = false, correctInput = false;
while (continueRun == 1)
{
System.out.print("\n 1. mouseIsland1.txt"
+ "\n 2. mouseIsland2.txt"
+ "\n 3. mouseIsland3.txt"
+ "\n 9. Exit\n\nPlease make your selection: ");
continueRun = 9;
runResponce = false;
while (correctInput == false){
while (!input.hasNextInt()) {
input.next();
System.out.print("Enter a number 1-3 or 9 to exit.\nPlease make your selection: ");
}
choice = input.nextInt();
if (choice>=1 && choice <=3 || choice == 9){
correctInput = true;
break;
}
}
switch(choice)
{
case 1:
MouseEscape island1 = new MouseEscape("mouseIsland1.txt");
System.out.println("\nFilename: "+island1.getIslandTxt()
+"\nBridge1: "+island1.getBridgePosition(0,0)+","+island1.getBridgePosition(0,1)
+"\nBridge2: "+island1.getBridgePosition(1,0)+","+island1.getBridgePosition(1,1)
+"\nMouse: "+island1.getMousePosition(1,0)+","+island1.getMousePosition(1,1)+"\n");
//island1.drawCharIsland();
for (int i=0;i<5;i++) island1.runMouseIsland();
island1.printIslandStats();
correctInput=false; continueRun=1; break;
case 2:
MouseEscape island2 = new MouseEscape("mouseIsland2.txt");
System.out.println("\nFilename: "+island2.getIslandTxt()
+"\nBridge1: "+island2.getBridgePosition(0,0)+","+island2.getBridgePosition(0,1)
+"\nBridge2: "+island2.getBridgePosition(1,0)+","+island2.getBridgePosition(1,1)
+"\nMouse: "+island2.getMousePosition(1,0)+","+island2.getMousePosition(1,1)+"\n");
//island1.drawCharIsland();
for (int i=0;i<5;i++) island2.runMouseIsland();
island2.printIslandStats();
correctInput=false; continueRun=1; break;
case 3:
MouseEscape island3 = new MouseEscape("mouseIsland3.txt");
System.out.println("\nFilename: "+island3.getIslandTxt()
+"\nBridge1: "+island3.getBridgePosition(0,0)+","+island3.getBridgePosition(0,1)
+"\nBridge2: "+island3.getBridgePosition(1,0)+","+island3.getBridgePosition(1,1)
+"\nMouse: "+island3.getMousePosition(1,0)+","+island3.getMousePosition(1,1)+"\n");
//island1.drawCharIsland();
for (int i=0;i<5;i++) island3.runMouseIsland();
island3.printIslandStats();
correctInput=false; continueRun=1; break;
}
if (runResponce == false)
{
if (continueRun == 1)
{
runResponce = true;
correctInput = false;
}
}
}
input.close();
}
// MouseIslandClass
// Constructs a mouseIslandClass without specifying which mouseIsland to load
public MouseEscape() {
islandTxt = "";
mouseEscaped = 0;
mouseDrowned = 0;
mouseStarved = 0;
islandRows = 0;
runCount = 0;
mousePosition = null;
bridgePosition = null;
islandIntArray = null;
islandCharArray = null;
}
// MouseIslandClass
// Constructs a mouseIslandClass given a mouseIsland map name
public MouseEscape(String _islandTxt) throws Exception{
islandTxt = _islandTxt;
loadIsland();
}
// setIslandTxt
// Sets the mouseIsland filename for the current mouseIsland
public void setIslandTxt(String _islandTxt) throws Exception{
islandTxt = _islandTxt;
}
// getIslandTxt
// Gets the mouseIsland filename for the current mouseIsland
public String getIslandTxt(){
return islandTxt;
}
// getMouseEscaped
// Returns the total number of times a mouse has escaped from the current mouseIsland
public int getMouseEscaped(){
return mouseEscaped;
}
// getMouseDrowned
// Returns the total number of times a mouse has drowned on the current mouseIsland
public int getMouseDrowned(){
return mouseDrowned;
}
// getMouseStarved
// Returns the total number of times a mouse has starved on the current mouseIsland
public int getMouseStarved(){
return mouseStarved;
}
// getBridgePosition
// Returns the coordinate row(x) or column(y) to either of the bridges on the current mouseIsland
public int getBridgePosition(int x, int y){
return bridgePosition[x][y];
}
// getMousePosition
// Returns the coordinate row(x) or column(y) of the mouse on the current mouseIsland
public int getMousePosition(int x, int y){
return mousePosition[x][y];
}
// loadIsland
// Populates any information needed to run the simulation for the current mouseIsland
public void loadIsland() throws Exception{
if (islandTxt == "" || islandTxt == null){
System.out.println("loadIsland() failed! 'islandTxt' variable is empty!");
return;
}
findIslandRow();
findIslandCol();
setCharIslandArray();
findIslandVariables();
}
// printIslandStats
// Prints to the console the statistics for this mouseIsland at its current state
public void printIslandStats(){
System.out.println("Run count: " + runCount + " times\n"
+ "Drowned: " + mouseDrowned + " times\n"
+ "Starved: " + mouseStarved + " times\n"
+ "Escaped: " + mouseEscaped + " times \n");
}
// maxValue
// This function returns the max value of an integer array.
public int maxValue(int [] inArray){
int value = 0;
for (int i=0;i<inArray.length;i++)
if (value<inArray[i]) value = inArray[i];
return value;
}
// findIslandRow
// Counts the number of rows for the current mouseIsland
public void findIslandRow() throws Exception {
Scanner input = new Scanner(new File(islandTxt));
islandRows = 0;
while(input.hasNext()){
input.nextLine();
islandRows++;
}
//System.out.println("Rows: "+islandRows);
input.close();
}
// findIslandCol
// Counts and stores the number of columns for each row in the current mouseIsland
public void findIslandCol() throws Exception {
Scanner input = new Scanner(new File(islandTxt));
String inputLine = ""; int row = 0; islandCols = new int [islandRows];
while(input.hasNext()){
inputLine = input.nextLine();
islandCols[row] = inputLine.length();
//System.out.println("Col"+row+": "+islandCols[row]);
row++;
}
input.close();
}
// loads a mouse island map into a 2 dimensional character array
public void setCharIslandArray() throws Exception {
Scanner input = new Scanner(new File(islandTxt));
islandCharArray = new char [islandRows+1][maxValue(islandCols)+1];
String islandRow ="";
for(int row=0;row<islandRows;row++){
islandRow = input.nextLine();
for (int col=0;col<islandRow.length();col++) {
islandCharArray[row][col] = islandRow.charAt(col);
}
}
input.close();
}
// drawCharIsland
// Draws a character array to the console for testing
public void drawCharIsland() throws Exception{
String ln = "";
for (int row= 0;row<islandRows;row++){
for (int col= 0;col<islandCols[row];col++){
if (col == islandCols[row]-1) ln = "\n"; else ln ="";
System.out.print(islandCharArray[row][col]+ln);
}
}
System.out.println("");
}
// drawIntIsland
// Draws an integer array to the console for testing
public void drawIntIsland() throws Exception{
String ln = "";
for (int row= 0;row<islandRows;row++){
for (int col= 0;col<islandCols[row];col++){
if (col == islandCols[row]-1) ln = "\n"; else ln ="";
System.out.print(islandIntArray[row][col]+ln);
}
}
System.out.println("");
}
// drawBigIntIsland
// Draws an integer array with special formatting for larger numbers the console for testing
public void drawBigIntIsland() throws Exception{
String ln = ""; String rowZero = ""; String colZero = "";
int i=0;
for (int row= 0;row<islandRows;row++){
if (row <= 9) rowZero = " "; else rowZero ="";
for (int col= 0;col<islandCols[row];col++){
if (row == 0)
while (i<islandRows){
if (i == 0) System.out.print("XY");
if (i <= 9) colZero = " "; else colZero ="";
if (i == islandCols[row]-1) ln = "\n"; else ln ="";
System.out.print(colZero+i+ln);
i++;
}
if (col == islandCols[row]-1) ln = "\n"; else ln ="";
if (islandIntArray[row][col] <= 9) colZero = "|"; else colZero ="";
if (col == 0) System.out.print(rowZero+row);
if (row >=0 && col >=0) System.out.print(colZero+islandIntArray[row][col]+ln);
}
}
}
// findIslandVariables
// finds and stores all of the mouseIsland object variables
public void findIslandVariables() throws Exception{
int bCount = 0;
mousePosition = new int [2][2]; bridgePosition = new int [200][2];
for (int row= 0;row<islandRows;row++){
for (int col= 0;col<islandCols[row];col++){
//System.out.println(row+"|"+col);
switch(islandCharArray[row][col]) {
case 'X' : mousePosition[0][0] = row; mousePosition[0][1] = col; //current position
mousePosition[1][0] = row; mousePosition[1][1] = col; //start position
//System.out.println("Mouse found on: "+row+"|"+col);
break;
case '-' :
if (row == 0 || col == 0 || row == islandRows-1 || col == islandCols[row]-1){
bridgePosition[bCount][0] = row; bridgePosition[bCount][1] = col;
bCount++;
//System.out.println("Bridge"+bCount+": "+row+"|"+col);
} else if (col>=islandCols[row-1]-1 || col>=islandCols[row+1]-1){
bridgePosition[bCount][0] = row; bridgePosition[bCount][1] = col;
//System.out.println("Bridge found: "+row+"|"+col);
bCount++;
}
break;
}
}
}
}
// moveMouse
// Computes the movement for the mouse
// set moveDebug to 'true' to display the mouse's moves
public void moveMouse(){
moveDebug = false;
int mouseMove = (int)(Math.random() * 4);
switch(mouseMove){
case 0: mousePosition[0][0]--; if (moveDebug == true) System.out.print("Move: "+mouseMove+"[UP] "); break;
case 1: mousePosition[0][0]++; if (moveDebug == true) System.out.print("Move: "+mouseMove+"[DOWN] "); break;
case 2: mousePosition[0][1]--; if (moveDebug == true) System.out.print("Move: "+mouseMove+"[LEFT] "); break;
case 3: mousePosition[0][1]++; if (moveDebug == true) System.out.print("Move: "+mouseMove+"[RIGHT] "); break;
}
if (moveDebug == true) System.out.println(" Location:|"+mousePosition[0][0]+"|"+mousePosition[0][1]+"|");
}
// runMouseIsland
// Displays the outcome of one trial of the current mouseIsland
public void runMouseIsland() throws Exception{
islandIntArray = new int [islandRows][maxValue(islandCols)];
mousePosition[0][0] = mousePosition [1][0]; mousePosition[0][1] = mousePosition [1][1];
for (int count=0;count<100;count++){
moveMouse();
if (mousePosition[0][0] == bridgePosition[0][0] && mousePosition[0][1] == bridgePosition[0][1] || mousePosition[0][0] == bridgePosition[1][0] && mousePosition[0][1] == bridgePosition[1][1] ){
System.out.println("The mouse has escaped using the bridge at: "+mousePosition[0][0]+"|"+mousePosition[0][1]);
islandIntArray[mousePosition[0][0]][mousePosition[0][1]]++;
mouseEscaped++;
break;
} else
if (islandCharArray[mousePosition[0][0]][mousePosition[0][1]] == '#') {
System.out.println("OUCH! The Mouse fell into the water and died at: "+mousePosition[0][0]+"|"+mousePosition[0][1]);
islandIntArray[mousePosition[0][0]][mousePosition[0][1]]++;
mouseDrowned++;
break;
}
islandIntArray[mousePosition[0][0]][mousePosition[0][1]]++;
if (count == 99){
System.out.println("The mouse withered away (died) at: "+mousePosition[0][0]+"|"+mousePosition[0][1]);
mouseStarved++;
}
}
drawIntIsland();
runCount++;
}
}