This code visualises the A* algorithm. When it reaches the end of the algorithm, it pops with an alerts saying the path is found using
JOptionPane.showMessageDialog(null, "Path Found")
After clicking away the windows disappears but then gets rendered again in the top left corner without the option to close it. Also, the path to the goal is rendered after clicking away however, in the code it gets rendered before the alert appears. I am sure that the problem is in this method specifically in the way I draw or call the repaint method and not in the actual algorithm itself. Could someone please explain where I am going wrong with this?
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.renderGrid(g);
this.renderCloseCells(g);
this.renderOpenCells(g);
if (aStar.getOpenSet().size() > 0) {
int lowestCostIndex = 0;
for (int i = 0; i < aStar.getOpenSet().size(); i++){
if (aStar.getOpenSet().get(i).getF() < aStar.getOpenSet().get(lowestCostIndex).getF()){
lowestCostIndex = i;
}
}
Cell current = aStar.getOpenSet().get(lowestCostIndex);
if (aStar.getOpenSet().get(lowestCostIndex) == aStar.getEnd()){
Cell temp = current;
aStar.addItemPath(temp);
while (temp.getParent() != null){
aStar.addItemPath(temp.getParent());
temp = temp.getParent();
}
System.out.println("Done");
this.renderPath(g);
JOptionPane.showMessageDialog(null, "Path Found");
return;
}
aStar.removeCellOpenSet(current);
aStar.addCellCloseSet(current);
for (int i = 0; i < current.getNeighbors().size(); i++){
Cell neighbor = current.getNeighbors().get(i);
if (!aStar.getCloseSet().contains(neighbor)){
int tempG = current.getG() + 1;
if (aStar.getOpenSet().contains(neighbor)) {
if(tempG < neighbor.getG()){
neighbor.setG(tempG);
}
} else {
neighbor.setG(tempG);
aStar.addCellOpenSet(neighbor);
}
neighbor.setH(aStar.heuristic(neighbor, aStar.getEnd()));
neighbor.setF(neighbor.getG() + neighbor.getH());
neighbor.setParent(current);
}
}
} else {
JOptionPane.showMessageDialog(null, "Path Not Found!");
}
this.repaint();
}
Related
I have problem at Conway Game of Life. To avoid an index out of bounds I started the loop at 1 and limited the back boundary with field.length-1.
However, the last column and row is not output for me and I don't know why.
I know that there are several solutions available on the Internet. Unfortunately these did not help me directly. Can someone tell me what I am doing wrong?
for(int i=1; i<feld.length-1;i++)
{
int zählvariable=0;
for(int j=1; j<feld.length-1;j++)
{
for(int l=-1;l<=1;l++)
{
for(int m=-1;m<=1;m++)
{
if(feld[i+l][j+m]=='+')
{
zählvariable++;
}
}
}
if ((feld[i][j]=='+') && (zählvariable<2))
{
neuesFeld[i][j] = '-';
}
else if((feld[i][j]=='+') && (zählvariable>3))
{
neuesFeld[i][j] = '-';
}
else if((feld[i][j]=='-') && (zählvariable==3))
{
neuesFeld[i][j] = '+';
}
else
neuesFeld[i][j]=feld[i][j];
zählvariable=0;
Solution:
I am making a graphical sudoku solver. Currently, I have a board where the user can enter the starting board configuration. Then they can click "solve" and it will solve the puzzle. To display the results, the method "displayResults()" is called:
void displayResult(int[][] boardArray) {
sudokuBoard.updateArray(boardArray);
sudokuPanel.repaint();
sudokuPanel.revalidate();
}
This then calls the updateArray() method:
void updateArray(int[][] boardArray) {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(boardArray[i][j] == 0) sudokuArray[i][j] = "";
else sudokuArray[i][j] = Integer.toString(boardArray[i][j]);
squares[i][j].removeAll();
squares[i][j].add(new JLabel(sudokuArray[i][j], JLabel.CENTER));
squares[i][j].repaint();
squares[i][j].revalidate();
}
}
}
This works fine for "solve", displaying the results.
I have a menu bar in my program with an "open" item. This is meant to read in a text file (with an initial board configuration) and show the contents on the board.
I have tried calling the "displayResult()" method after reading in the file (passing in the resulting array). Unfortunately, nothing displays in the grid when it is called. Strangely, I have tried clicking solve, and the correct results will then appear in the grid.
sudokuPanel // the panel in the main window that contains the grid
sudokuBoard // an object of a Board class that contains all of the board info
squares // a 9x9 array of JPanels, representing the grid
sudokuArray // an array of Strings, containing the up to date information about the board configuration
I am having a similar problem with another method, however I am guessing that they are related. The read() method is:
protected void read() {
StringBuilder sb = new StringBuilder();
FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text");
chooser = new JFileChooser();
chooser.setFileFilter(filter);
if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
try {
File file = chooser.getSelectedFile();
Scanner input = new Scanner(file);
while(input.hasNext()) {
sb.append(input.nextLine());
sb.append("\n");
}
input.close();
readInToArray(sb);
} catch(FileNotFoundException e) {
System.err.println("File does not exist");
}
}
else return;
}
And readInToArray(), which calls displayResult():
private void readInToArray(StringBuilder sb) {
int[][] newArray = new int[9][9];
String[] lines = (sb.toString()).split("\n");
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
char c = lines[i].charAt(j);
newArray[i][j] = Character.getNumericValue(c);
}
}
if(!checkArray(newArray)) {
errorMessage("Incorrect configuration");
return;
}
displayResult(newArray);
}
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I am writing a basic Tic-Tac-Toe Single player game using basic swing graphics. I completed the game, but there is a weird problem I am facing. At one place, I used a while loop with a SOP statement. If I omit this statement, program works differently and nothing happens (like some kind of infinite loop), and if I keep it, it works just fine. I don't know what's happening in the code. Please help.
Below is the source code which causing problem. Sorry for my amateur coding style.
import java.util.Random;
public class SinglePlayer implements Runnable{
public final int MINIMUM = -1000000;
private GameBoard game;
public SinglePlayer(){
game = new GameBoard("Single Player");
}
public static void main(String[] args){
SinglePlayer gameSingle = new SinglePlayer();
gameSingle.run();
}
public void run(){
boolean machinePlayed = true, userPlayed = false;
// Outer loop is to maintain re-match option of program
while(this.game.quitTwoPlayer == false){
// Inner loop is a single game b/w user and machine
while(this.game.GameQuitStatus() == false){
/* I kept two conditions to switch b/w machine and user mode
* of game and they just keep changing to simulate the game
* b/w machine and user.
*/
if(machinePlayed == false && userPlayed){
try {
MachineMove("O");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
break;
}
this.game.ChangePlayerLabels();
machinePlayed = true;
userPlayed = false;
}
else if(machinePlayed && userPlayed == false){
int earlierCount = this.game.CountSteps();
/* THIS IS THE WHILE LOOP I AM TALKING ABOUT.
* If I omit the print statement inside the body of loop,
* program behaves differently, but when I keep it,
* it working just fine.
* */
while(earlierCount == this.game.CountSteps()){
System.out.println("Player User thinking");
}
this.game.ChangePlayerLabels();
machinePlayed = false;
userPlayed = true;
}
this.game.DeclareResult();
}
this.game.dispose();
}
}
public void MachineMove(String player) throws CloneNotSupportedException{
/* If board is empty, play at center of the board */
if(this.game.CountSteps() == 0){
this.game.MakeMove(1, 1);
}
/* If center is blank, play it there. Otherwise, pick a corner randomly */
else if(this.game.CountSteps() == 1){
if(this.game.IsEmpty(1, 1))
this.game.MakeMove(1, 1);
else{
Random randomNum = new Random();
int num = randomNum.nextInt(4);
if(num == 0)
this.game.MakeMove(0, 0);
else if(num == 1)
this.game.MakeMove(2, 0);
else if(num == 2)
this.game.MakeMove(0, 2);
else if(num == 3)
this.game.MakeMove(2, 2);
}
}
else{
/* If the next move is such that it should be taken, otherwise opponent will win */
String opponent = "";
if(this.game.GetCurrentPlayer().equals("O"))
opponent = "X";
else
opponent = "O";
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(this.game.IsEmpty(i,j)){
GameBoard tempGame = new GameBoard(this.game, "Single Player");
tempGame.MakePossibleMove(i, j, opponent);
if(tempGame.GameWinner().equals(opponent + " wins")){
this.game.MakeMove(i,j);
return;
}
}
}
}
/* If the next move is not such that if missed, game is lost, then play most optimal move towards winning */
Move tempMove = new Move(MINIMUM, 0, 0);
Move bestMove = new Move(MINIMUM, 0, 0);
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(this.game.IsEmpty(i,j)){
GameBoard tempGame = new GameBoard(this.game, "Single Player");
tempMove = MakeMoves(tempGame, i, j);
if(tempMove.score > bestMove.score){
bestMove.row = tempMove.row;
bestMove.col = tempMove.col;
bestMove.score = tempMove.score;
}
}
}
}
this.game.MakeMove(bestMove.row, bestMove.col);
}
}
public Move MakeMoves(GameBoard tempGame, int row, int col){
String player = tempGame.GetCurrentPlayer();
tempGame.MakeMove(row, col);
if(tempGame.GameWinner().equals("Match Draw")){
return new Move(0, row, col);
}
else if(tempGame.GameWinner().equals("X wins")){
if(player.equals("X")){
return new Move(1, row, col);
}
else{
return new Move(-1, row, col);
}
}
else if(tempGame.GameWinner().equals("O wins")){
if(player.equals("O")){
return new Move(1, row, col);
}
else{
return new Move(-1, row, col);
}
}
else{
Move bestMove = new Move(MINIMUM, 0, 0);
Move tempBestMove = new Move(0, 0, 0);
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(tempGame.IsEmpty(i,j)){
GameBoard newGame = new GameBoard(tempGame, "Single Player");
tempBestMove = MakeMoves(newGame, i, j);
if(tempBestMove.score > bestMove.score)
bestMove = tempBestMove;
}
}
}
return bestMove;
}
}
}
class Move{
public int score;
public int row;
public int col;
public Move(int score, int row, int col){
this.score = score;
this.row = row;
this.col = col;
}
}
Your loop is likely typing up your processor, and the SOP slows the loop enough to allow other processes to occur. But regardless and most importantly, you don't want to have this loop present in the first place. You state that you have a,
Tic-Tac-Toe Single player game using basic swing graphics
Remember that Swing is an event driven GUI library, so rather than loop as you would in a linear console program, let events occur, but respond to them based on the state of the program.
In other words, give your class several fields including a boolean variable that tells whose turn it is, such as boolean playersTurn, a boolean variable gameOver, ..., and change the state of these variables as the game is played, and base the games behavior depending on these states. For instance the game would ignore the player's input if it was not his turn.
The code below is taking 27 seconds to load 51 images each image is about 22 KB (timed between the starting and ending alerts I inserted). Is it possible to make it a lot more efficient (I would like to get it to under 3 seconds)?
At first I thought it was the database so I put the alerts in to make sure and found it was this code.
Regards,
Glyn
public void renderYMAwardsTable(List<YouthMemberAwards> ymAwardsList) {
if (!ymAwardsList.isEmpty()) {
flexTableLink.clear();
int linkRow = 0;
int linkCol = 0;
flexTableLeadership.clear();
int leadershipRow = 0;
int leadershipCol = 0;
flexTableBoomerang.clear();
int boomerangRow = 0;
int boomerangCol = 0;
flexTableAchievement.clear();
int achievementRow = 0;
int achievementCol = 0;
flexTableSpecialInterest.clear();
int specialInterestRow = 0;
int specialInterestCol = 0;
totalAwards = 0;
Window.alert("Start populating page.");
for (final YouthMemberAwards ymAwards : ymAwardsList) {
// Display awards and, if applicable, date awarded
if (((ymAwards.getCaAwardedDate() != null)
|| (ymAwards.getAwArchivedDate() == null)
|| (ymAwards.getCaAwardStarted().equals("Y"))
) && (ymAwards.getAwStartedDate().before(ymEndDate))) {
//Display each award in the correct area with:
// the date awarded, if applicable, and
// the date box shaded if the award has been started but not awarded
String imageDataString = ymAwards.getAwAwardPicture();
Image image = new Image(imageDataString);
image.setWidth("75px");
image.setHeight("75px");
image.setStyleName("gwt-Selectable");
final DateBox awardedDate = new DateBox();
awardedDate.setFormat(new DefaultFormat(DateTimeFormat.getFormat("dd/MM/yyyy")));
awardedDate.setValue(ymAwards.getCaAwardedDate());
awardedDate.setWidth("75px");
awardedDate.setFireNullValues(true);
//Check if the Youth Member has started the Award,
//if they have then colour the date box Green.
if (ymAwards.getCaAwardStarted()!= null){
if ((ymAwards.getCaAwardedDate() == null)
&& (ymAwards.getCaAwardStarted().equals("Y"))){
awardedDate.setStyleName("gwt-Green-Background");
}else{
awardedDate.setStyleName("gwt-Label-Login");
}
}else{
awardedDate.setStyleName("gwt-Label-Login");
}
//Tally the number of Awards the Youth Member has been awarded.
if (ymAwards.getCaAwardedDate() != null){
totalAwards = totalAwards + 1;
}
//Display each Award in the appropriate category.
if (ymAwards.getAwAwardType().equals("Link")){
flexTableLink.setWidget(linkRow, linkCol, image);
flexTableLink.setWidget(linkRow + 1, linkCol, awardedDate);
if (linkCol < 10){
linkCol = linkCol + 1;
}else{
linkCol = 0;
linkRow = linkRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Leadership")){
flexTableLeadership.setWidget(leadershipRow, leadershipCol, image);
flexTableLeadership.setWidget(leadershipRow + 1, leadershipCol, awardedDate);
if (leadershipCol < 10){
leadershipCol = leadershipCol + 1;
}else{
leadershipCol = 0;
leadershipRow = leadershipRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Boomerang")){
flexTableBoomerang.setWidget(boomerangRow, boomerangCol, image);
flexTableBoomerang.setWidget(boomerangRow + 1, boomerangCol, awardedDate);
if (boomerangCol < 10){
boomerangCol = boomerangCol + 1;
}else{
boomerangCol = 0;
boomerangRow = boomerangRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Achievement")){
flexTableAchievement.setWidget(achievementRow, achievementCol, image);
flexTableAchievement.setWidget(achievementRow + 1, achievementCol, awardedDate);
if (achievementCol < 10){
achievementCol = achievementCol + 1;
}else{
achievementCol = 0;
achievementRow = achievementRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Special Interest")){
flexTableSpecialInterest.setWidget(specialInterestRow, specialInterestCol, image);
flexTableSpecialInterest.setWidget(specialInterestRow + 1, specialInterestCol, awardedDate);
if (specialInterestCol < 10){
specialInterestCol = specialInterestCol + 1;
}else{
specialInterestCol = 0;
specialInterestRow = specialInterestRow + 2;
}
}else{
//If not found then default to Special Interest.
flexTableSpecialInterest.setWidget(specialInterestRow, specialInterestCol, image);
flexTableSpecialInterest.setWidget(specialInterestRow + 1, specialInterestCol, awardedDate);
if (specialInterestCol < 10){
specialInterestCol = specialInterestCol + 1;
}else{
specialInterestCol = 0;
specialInterestRow = specialInterestRow + 2;
}
}
}
}
}
}
//Add a click handler to the image
image.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event){
//Store the data from this view for use in subsequent Views (ScoutAwardView).
AsyncCallback<ViewData> callback = new ViewDataStoreHandler<ViewData>();
rpc.setViewData(accountId, accountLevel, youthMemberID, ymAwards.getAwId(), "0", callback);
//If the Award has sub groups then display the Groups and allow one the
//be selected to display the details. Otherwise, display the details.
if (ymAwards.getAwGrouped().equals("Y")) {
//Go to the AwardGroupView
navHandler2.go("AwardGroup");
}else{
//Go to the ScoutAwardView
navHandler2.go("ScoutAward");
}
}
});
//Add change handler for the awarded date.
//Only a Leader or Administrator can update the date
if (accountLevel.equals("Leader") || accountLevel.equals("Administrator")) {
awardedDate.addValueChangeHandler(new ValueChangeHandler<java.util.Date>() {
public void onValueChange(ValueChangeEvent<java.util.Date> event) {
//Check for a null date and handle it for dateBoxArchived and dateBoxPackOut
java.sql.Date sqlDateAwarded = awardedDate.getValue() == null ? null : new java.sql.Date(awardedDate.getValue().getTime());
AsyncCallback<Void> callback = new YMAwardedDateHandler<Void>();
rpc.updateYMAwarded(youthMemberID, ymAwards.getAwId(), sqlDateAwarded, callback);
#SuppressWarnings("unused")
AdjustAwardStock adjustAwardStock = new AdjustAwardStock(sqlDateAwarded, ymAwards.getAwId());
}
});
}
}
}
}
Window.alert("Finish populating page.");
//Hide "Loading please wait" popup.
popup.hide();
//Display the number of Awards earned.
String totalAwardsString = Integer.toString(totalAwards);
textBoxTotalAwards.setText(totalAwardsString);
}
First of all, an image with 75x75 pixels size should not be 22kB. Even a PNG-24 image of this size is about 3kB, let alone GIF. Store your images in the correct sizes and the appropriate file format (use PNG or GIF). For 51 images that means a difference between 1MB and 150kB. This is the first big improvement.
Second, if you use a limited number of images, combine them into a single sprite. This will reduce the number of round-trip server calls from 51 (in your example) to 1. That's another huge improvement.
You don't need to make this sprite manually (unless you want to). You can use GWT's ImageResource ClientBundle. Note that this sprite can be cached, so a browser won't need to load it every time a user visits this page.
The other suggestions (like using switch statements) are good for code readability and maintenance, but they won't give you a significant performance boost because your Java code is compiled into JavaScript, and the compiler is pretty smart.
For combining the images and other JS files, you can always use gzip functionality supported by browser so that all the files can b zipped and send to the browser to unzip. It will lot of network time and transferred data size will b much reduced.
This class is in a program for a game I'm writing that is basically Space Invaders. I'm getting Exceptions for some reason and I don't see why I should be getting them.
Here's the class in question, but I can post all the code if necessary:
public class GamePanel extends JPanel {
Launcher launcher1;
Background bground1;
Shot shot;
public ArrayList<Shot> shots;
public int numShots;
public static int counter;
public GamePanel() throws IOException {
super();
this.shots = new ArrayList<>();
this.numShots = 0;
launcher1 = new Launcher();
bground1 = new Background();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bground1.background, 0, 0, getWidth(), getHeight(), null);
g.drawImage(launcher1.baldEagleImage, launcher1.getLxCoord(), launcher1.lyCoord, null);//paint the launcher
while (counter == 1) {
for (int i = 0; i < shots.size(); i++) {
g.drawImage(shots.get(i).mcDShotImage, shots.get(i).staticXLauncherCoord, shots.get(i).getSyCoord(), null);
}
}
}
public void move(GamePanel gamePanel) {
launcher1.moveX();
if (numShots > 0) {
moveShot();
}
repaint();
}
public void moveShot() {
for (int i = 0; i < numShots; i++) {//loop to move all the shots
if (shots.get(i).getSyCoord() > 10) { // THIS IS THE ISSUE, but I don't know why
counter = 1;
shots.get(i).moveY();
repaint();
} else {
counter = 0;
shots.remove(i);
repaint();
}
}
}
public void createShots() {
try {
for (int j = 0; j < numShots; j++) {
shots.add(new Shot());
}
} catch (IOException | IndexOutOfBoundsException e) {
System.out.println("caught an exception" + e);
}
}
}
The problem is in this piece of code:
} else {
counter = 0;
shots.remove(i);
repaint();
}
You remove an item from shots without adjusting numShots, causing an index out of bounds exception in one of subsequent iterations.
To fix this, either add numShots-- in the else branch, or use the built-in size() method that returns the count of elements in a list instead: unlike numShots which you need to maintain, shots.size() never gets "out of sync" with the actual count.
In the above line of code what is apparent is the issue is numShots is > shots.size() (because you also remove shots.
Since I couldn't where you are incrementing the numShots, in this piece of code one simple (albeit not sure from your logic perspective) change your for loop as below:
for (int i = 0; i < shots.size(); i++)