I've been trying for two days to get this running, but I cant for the life of me.
what I'm trying to do is solve an 8 puzzle using the A star algorithm and manhattan heuristic.
this is the part of the code for the A star:
public void solve(){
State s = duplicateState(stateToSolve);
StringState ss = new StringState(s);
makeQ(ss.getStringState(),null,s);//add the first State to queue
//s.setG(0);
//s.setF(s.gettG()+heuristicTwo(ss.getStringState(),goal));
s.setF(heuristicTwo(ss.toString(),goal));
while(!states.isEmpty()){
LinkedList<State>child=new LinkedList<State>();
State state = lowestF(states);
StringState pre = new StringState(state);
if (goalReached(state)&&!solved){
s = state;
solved=true;
System.out.println("#########\n# Solved #\n#########");
break;
}
//explore(state);
child=neighbours(child,state);
for(int i=0;i<child.size();i++)
{
child.get(i).setTotalCost(state.gettG()+findDistance(state,child.get(i)));
if(open.containsKey(child.get(i)))
{
if(child.get(i).gettG()<=child.get(i).getTotalCost())
System.out.println(child.get(i).getSolution());
continue;
}
else if(close.containsKey(child.get(i)))
{
if(child.get(i).gettG()<=child.get(i).getTotalCost())
continue;
System.out.println(child.get(i).getSolution());
StringState next = new StringState(child.get(i));
makeQ(next.getStringState(),pre.getStringState(),child.get(i));
close.remove(child.get(i));
}
else
{
System.out.println(child.get(i).getSolution());
StringState next = new StringState(child.get(i));
makeQ(next.getStringState(),pre.getStringState(),child.get(i));
child.get(i).setH(heuristicTwo(next.getStringState(),goal));
}
child.get(i).setG(child.get(i).getTotalCost());
}
close.put(ss.getStringState(),ss.getStringState());
}
solution = s.getSolution();
if (solution.equals("")||solution.equals(null))
System.out.println("no solution");
else{
System.out.println("Astar");
System.out.println(solution);
}
}
StringState is just takes the state of the board of the puzzle and converts in to a string.
to make thins a little more clear here some other parts of the code:
private Queue<State> states;
private State stateToSolve;
boolean solved=false;
private final String goal = "0123456789ABCDEF";
private final String goal2 = "123456789ABCDEF0";
private Map<String,String> close;//to keep track of previous checked status
private Map<String, String> open;
private String solution;
//-1,-1 for decrement of coordinates
private final int up = -4;
private final int down = 4;
private final int left = -1;
private final int right = 1;
//CONSTRUCTOR
public Astar(State s){
solution = "";
states = new LinkedList<State>();
stateToSolve = duplicateState(s);
close = new HashMap<String, String>();
open = new HashMap<String, String>();
solve();
}
All the neighbours function does is to take a state of the board and returns the neighbours of the board-meaning moving the blank tile to the left/right/up/down(if possible)and giving back the board state after doing it.
so the neighbours are the new states.
The problem that I'm facing (I came to realize after running the program and tried to print it's state at some points)is that it's going inside an infinite loop apter 2 moves of the blank tile.For example, when I'm trying to find a path for the String str1 = "1 2 0 3 4 5 6 7 8 9 A B C D E F";
the answer should be-left left
but I'm getting
left
left
left
right
left
down
left
left
left
right
left
down
left
left
and it just go on and on infinitelly..
Any help would be appreciated..
((I was using this -pseudo code)
Related
I have java based application for Texas Holdem Poker. I have to introduce a feature wherein whenever all players except one goes for all in, we have to calculate probability of winning for each player.
This can happen in pre-flop, flop & turn round. As you may know in pre-flop stage all 5 cards have to be chosen, in flop there are already 3 community cards in the table, 2 more cards have to be
chosen, whereas in turn round 1 more cards have to be chosen. Let us assume there are 2 players.
So each of the players have 2 hole cards. So we have to choose 2 cards from deck of 52 -2*2 = 48 cards. By using combinatorics I am able to do that. But in pre-flop stage there are too many combinations, from 48 we have to choose 5 cards which is 48Cr5 = 1712304 combinations. If I do that much computation the game gets stuck. So tried to use ForkJoinPool. I found there are only 2 cores in the machine where the application is deployed. It is not working at all. Is ForkJoinPool suitable for this task or should I go for some other ExecutorService. Here is some of my RecursiveTask code
public class WinnerPercentageTask extends RecursiveTask<List<String>> {
private static int threshold = 50_000;
private List<List<Byte>> combinations;
private int start;
private int end;
private ITexasHoldemGame game;
public WinnerPercentageTask(ITexasHoldemGame game, List<List<Byte>> allCombinations, int start, int end) {
super();
this.game = game;
this.combinations = allCombinations;
this.start = start;
this.end = end;
}
#Override
protected List<String> compute() {
if (end - start < threshold) {
return computeDirectly();
}
else {
int middle = (end + start) / 2;
WinnerPercentageTask subTask1 = new WinnerPercentageTask(game,combinations, start, middle);
WinnerPercentageTask subTask2 = new WinnerPercentageTask(game,combinations, middle, end);
invokeAll(subTask1, subTask2);
List<String> ret = new ArrayList<>();
ret.addAll(subTask1.join());
ret.addAll(subTask1.join());
return ret;
}
}
private List<String> computeDirectly() {
List<Card> communityCards = game.getCommunityCardsDealt();
List<Winner> winners = new ArrayList<>();
List<String> winnersForAllCombinations = new ArrayList<>();
for(List<Byte> combination: combinations.subList(start, end)) {
List<Card> allCommunityCard = new ArrayList<>();
for (Card c : communityCards) {
allCommunityCard.add(new Card(c.getId(), c.getFaceValue(), c.getSuit()));
}
for (Byte b : combination) {
Card fakeCommunityCard = new Card(b);
allCommunityCard.add(fakeCommunityCard);
}
List<PokerHand> playerRankList = calculateHandRank(allCommunityCard);
winners = prepareWinnerList(playerRankList);
winnersForAllCombinations.addAll(
winners.stream()
.map(Winner:: getPlayerId)
.collect(Collectors.toList()));
}
return winnersForAllCombinations;
}
private List<PokerHand> calculateHandRank(List<Card> communityCardsDealt) {
List<PokerHand> playerRankList = new ArrayList<>();
Map<String, List<Card>> playersCards = this.game.getCardsDealtForAllPlayers();
playersCards.forEach((player, holeCards) -> {
PokerHand pokerHand = new PokerHand(player, holeCards);
HandRanker.checkRanking(pokerHand, communityCardsDealt);
playerRankList.add(pokerHand);
});
Collections.sort(playerRankList);
// if (logger.isInfoEnabled()) {
// logger.info("Player Rank List : {}", playerRankList);
// }
return playerRankList;
}
private List<Winner> prepareWinnerList(List<PokerHand> playerRankList) {
List<Winner> winnerList = new ArrayList<>();
if (!CollectionUtils.isEmpty(playerRankList)) {
// Grouping Players based on similar Ranks
Map<HandRankingEnum, List<PokerHand>> groupByRankMap = playerRankList.stream()
.collect(Collectors.groupingBy(PokerHand::getRankingEnum));
// Sort the Map based on Rank, highest rank first
List<Map.Entry<HandRankingEnum, List<PokerHand>>> sortedWinnerList = groupByRankMap
.entrySet().stream().sorted(reverseOrder(Map.Entry.comparingByKey()))
.collect(Collectors.toList());
// Reading the Winners of highest rank
Map.Entry<HandRankingEnum, List<PokerHand>> winnerListMap = sortedWinnerList
.get(0);
List<PokerHand> highestRankList = winnerListMap.getValue();
List<PokerHand> winnerHandList = new WinnerIdentifier().getWinners(highestRankList);
for (PokerHand hand : winnerHandList) {
Winner winnerPlayer = Winner.builder()
.rank((byte) hand.getRankingEnum().getValue())
.rankName(hand.getRankingEnum().name())
.playerId(hand.getGamePlayerId()).cards(hand.getRankingList())
.pots(new ArrayList<>()).build();
winnerList.add(winnerPlayer);
}
}
return winnerList;
}
}
`
I am going to be honest and up front here. This is homework, but I have become desperate and am looking for anyone to assist me. I have been working on this off and on for over a month and have gone to my instructor multiple times. Basically this program needs to create and sort a linked list that has an int, string and double in each node. It needs to be able to sort by each data type as well as print in input order but once I figure one out I can transfer it to the other data types. Please, everything needs to be "hand made", please do not use any built in commands as I need to create everything as per my instructor's demands.
I attempted to make the linked list and then sort it, but I ran into a problem so I decided to try and sort the list as I create it.
For example: Input the first node, then input the next node in front/behind the first, then put the next where it needs to go... and so forth.
Here is my code (I only focus on the strings):
String repeat = "y";
list1 fChr = null;
list1 p = fChr;
list1 copy = null;
//list1 dCopy = null;
//list1 iCopy = null;
list1 fd = fChr;//front of the double list
list1 fi = fChr;//front of the integer list
list1 fStr = fChr;//front of the string list~
list1 pStr = fStr;
boolean inserted = false;
int iii = 0;
String sss = "";
double ddd = 0.0;
while(repeat.equals("y"))//while the user agrees to adding a new node
{
if(fChr == null)// if the front is empty
{
fChr = new list1();//create a new node by calling object and sets it as the front
p = fChr;
copy = fChr;
sss = fChr.GetS();
iii = fChr.GetI();
ddd = fChr.GetD();
copy.SetS(sss);
copy.SetI(iii);
copy.SetD(ddd);
System.out.println("(1)");
}
else
{
System.out.println("(2)");
if(p!=null)
{
System.out.println("p = "+ p.GetS());
if(p.next != null)
{
System.out.println("p.next = "+ p.next.GetS());
System.out.println("p.next.next = "+ p.next.next.GetS());
}
}
p = fChr;
while(p.next != null)//finds the end of the Linked list
{
System.out.println("(3)");
p = p.next;//moves the pointer p down the list
}
list1 NextNode = new list1();//
p.next = NextNode;
sss = NextNode.GetS();
iii = NextNode.GetI();
ddd = NextNode.GetD();
copy = NextNode;
String gg = "hi";//tests to see if the setter is actually changing the value inside copy(it is not, it prints b)
copy.SetS(gg);
copy.SetI(iii);
copy.SetD(ddd);
System.out.println(copy.GetS());
System.out.println("p = "+ p.GetS());
}
pStr = fStr;
//System.out.println(copy.GetS()+"*");
inserted = false;
if(fStr == null)
{
System.out.println("(4)");
fStr = copy;//fStr = fChr;
inserted = true;
//System.out.println("p.next.next = "+ p.next.next.GetS());
}
else if(copy.GetS().compareTo(fStr.GetS()) < 0)
{
System.out.println("(5)");
//System.out.println("1)p.next.next = "+ p.next.next.GetS());
copy.next = fStr;//ERROR ON THIS LINE
System.out.println("2)p.next.next = "+ p.next.next.GetS());
System.out.println("fChr.next: "+fChr.next.GetS());
fStr = copy;
System.out.println("3)p.next.next = "+ p.next.next.GetS());
inserted = true;
System.out.println("p = "+ p.GetS());
System.out.println("p.next = "+ p.next.GetS());
System.out.println("4)p.next.next = "+ p.next.next.GetS());
}
else if(fStr.next == null && fStr != null)
{
System.out.println("(6)");
fStr.next = copy;
inserted = true;
}
else
{
System.out.println("(7)");
pStr = fStr;
System.out.println("RIP (8)");
while(pStr.next != null && inserted == false)
{
System.out.println("(9)");
System.out.println("RIP");
if(copy.GetS().compareTo(pStr.next.GetS()) < 0)//if it goes between 2 nodes
{
System.out.println("(10)");
copy.next = pStr.next;
pStr.next = copy;
inserted = true;
}
else
{
System.out.println("(11)");
pStr = pStr.next;
}
if(pStr.next == null && inserted == false)// it goes at the end(not necessary bc of the (in order) part)
{
System.out.println("(12)");
pStr.next = copy;
}
}
}
repeat = JOptionPane.showInputDialog("Would you like to add a node [y/n]");
System.out.println("End of Loop");
}
System.out.println(fStr.GetS());
PrintMenu(fChr, fi, fd, fStr);// sends the user to the menu screen
}
From all of my print statements I have (what I think) found the problem. This code runs through twice and upon hitting "y" for the third time, prints "(3)" in an infinite loop. I have found that (say the input for the strings is "c" then "b") "p" is equal to "c", p.next is equal to "b" and p.next.next is equal to "c". So, p is in an infinite loop. I have no idea why it does this, I have a theory that it could be because the front(fChr) changes and then "p" points to it and is just kinda drug along. I also just realized that me trying to set "copy" equal to "NextNode" was unsuccessful and copy just holds the value inside p.next(which is NextNode). That seems correct, but when I try to put something else in, it doesn't work. I could be testing this incorrectly and in that case the setter is correct. Setting is one of the main problems that I seem to be having. I will try to answer as many questions as I can if anyone has any.
Also here is the object in case you would like to see it. Thank you for your time, any help will be appreciated. Please if possible try to keep it relatively simple this is a high school assignment and I am so close and am stumped on how to fix what is wrong. Also, you may have noticed, but I have to use private variables. I am not asking for someone to give me a program that works, I am just asking if you know why what is going wrong is happening and if you know how to fix it. Thank you from the bottom of my heart!
import javax.swing.JOptionPane;
public class list1
{
private int i;
private String s;
private double d;
private String ss = null;
private int ii = 0;
private double dd = 0.0;
list1 next = null;
public list1()
{
String str;
s=JOptionPane.showInputDialog("Enter a String");
String temp =JOptionPane.showInputDialog("Enter an Integer");
i = Integer.parseInt(temp);
String temp2 =JOptionPane.showInputDialog("Enter a Double");
d = Double.parseDouble(temp2);
}
public double GetD()
{
return d;
}
public String GetS()
{
return s;
}
public int GetI()
{
return i;
}
public void SetS(String x)
{
ss = x;
}
public void SetI(int y)
{
ii = y;
}
public void SetD(double z)
{
dd = z;
}
}
I'm trying to implement an AI that uses Minimax for the dots and boxs game (http://en.wikipedia.org/wiki/Dots_and_Boxes)
Here is what I have so far:
public Line makeMove(GameState gs) {
if (gs.getRemainingLines().size() == 1) {
return gs.getRemainingLines().get(0);
}
if (gs.getPlayer() == 1) {
int minscore = -1;
GameState g = gs.clone();
Line lnew = null;
List<Line> l = gs.getRemainingLines();
for (Line l2 : l) {
g.addLine(l2);
if (evaluate(g) > minscore) {
minscore = (evaluate(g));
lnew = l2;
}
}
return lnew;
} else {
int maxscore = 999;
GameState g = gs.clone();
Line lnew = null;
List<Line> l = gs.getRemainingLines();
for (Line l2 : l) {
g.addLine(l2);
if (evaluate(g) < maxscore) {
maxscore = (evaluate(g));
lnew = l2;
}
}
return lnew;
}
}
However, it keeps returning null and I don't think I'm impementing minimax correctly. Can anyone give me some pointers.
getRemainingLines() returns a List of moves that are still possible.
evaluate() returns an int for the score.
I would like to suggest that you completely re-factor your code. The problem with looking at your code (and why there haven't been many responses here) is that it's hard to follow and hard to debug. For instance, what is gs.getRemainingLines and what does it do exactly? (Why remaining lines and not all legal lines?)
But, with some simplifications it will be much easier to figure out what is going on and to fix it.
At an abstract level minimax is just this procedure:
float minimax_max(GameState g)
{
if (g is terminal or max depth reached)
return eval(g);
float bestVal = -inf;
bestMove = null;
moves = g->getLegalMoves();
for (m : moves)
{
ApplyMove(m);
if (g->nextPlayer == maxPlayer)
nextVal = minimax_max(g);
else
nextVal = minimax_min(g);
if (nextVal > bestVal)
{
bestVal = nextVal;
bestMove = m;
}
UndoMove(m);
}
return bestVal;
}
I haven't shown exactly how to get/use the last move at the end, but it isn't that hard. You also need another procedure for minimax_min, or you can put an if statement into the code.
If you look at your code, you've written it close to this, but you've left a lot of game specific details in the code. But, you shouldn't have to think about those things to get minimax working correctly.
In particular, most games can be reasoned with abstractly if you provide functions for GetMoves(), ApplyMove(), UndoMove(), and eval(), which evaluates a state. (Further search enhancements would require more functions, but this will get you a long ways.)
Some reasons why you might want to re-factor in this way:
You can now test minimax and your other code separately.
You can test your dots and boxes code by validating that all legal moves are generated and that after applying a move you have a legal state with the correct player moving next. (You can play and undo long sequences of random moves to help validate that you always end up back in the start state afterwards.)
You can test your evaluation function easily on individual states to make sure it works properly. (In practice you can't usually search to the end of the game to determine the winner.)
You can test minimax by using a simple evaluation function and testing to see if the right moves are made. (e.g. if you prefer moves on the edges, a 1-ply search should return a move on the edge)
Other people can read your code more easily. We can look at each piece of code and see if it is correct on its own, instead of having to mix the game-specific implementation details into the minimax-specific details.
If you can apply and undo moves properly, you don't need to make copies of the game states. This will make the code much more efficient.
While you could try to fix your code without refactoring (e.g. just find the first place it returns null, and that will point out where your error is), in the long term your code will be hard to debug and improve without these changes.
The first thing to check is that gs.getRemainingLines() actually has lines remaining.
A separate problem is that you are adding every line to the GameState g to check. You either need to remove each added line after calling evaluate or put the clone inside the loop at the top such as
int minscore = -1;
Line lnew = null;
List<Line> l = gs.getRemainingLines();
for (Line l2 : l) {
GameState g = gs.clone();
g.addLine(l2);
if (evaluate(g) > minscore) {
minscore = (evaluate(g));
lnew = l2;
}
}
or
int minscore = -1;
GameState g = gs.clone();
Line lnew = null;
List<Line> l = gs.getRemainingLines();
for (Line l2 : l) {
g.addLine(l2);
if (evaluate(g) > minscore) {
minscore = (evaluate(g));
lnew = l2;
}
g.removeLine(l2);
}
However if you are trying to use minimax (http://en.wikipedia.org/wiki/Minimax) then you will need to change your code to recursively call makeMove (unless you modify the algorithm to do determine the min-max using loop constructs).
public GameState makeMove(GameState gs) {
if (gs.getRemainingLines().size() == 1) {
GameState g = gs.clone();
g.addLine(gs.getRemainingLines().get(0));
return g;
}
if (gs.getPlayer() == 1) {
GameState g = gs.clone();
g.setPlayer(2);
int bestValue = -1;
Line lbest = null;
List<Line> lines = gs.getRemainingLines();
for (Line line : lines) {
g.addLine(line);
GameState val = makeMove(g);
g.removeLine(line);
if (evaluate(val) > bestValue) {
bestValue = evaluate(g);
lbest = line;
}
}
g.addLine(lbest);
return g;
} else {
GameState g = gs.clone();
g.setPlayer(1);
int bestValue = 999;
Line lbest = null;
List<Line> lines = gs.getRemainingLines();
for (Line line : lines) {
g.addLine(line);
GameState val = makeMove(g);
g.removeLine(line);
if (evaluate(val) < bestValue) {
bestValue = evaluate(g);
lbest = line;
}
}
g.addLine(lbest);
return g;
}
}
I'm creating a program in Java that solves the n-puzzle, without using heuristics, simply just with depth-first and breadth-first searches of the state space. I'm struggling a little bit with my implementation of depth-first search. Sometimes it will solve the given puzzle, but other times it seems to give up early.
Here's my DFS class. DepthFirstSearch() is passed a PuzzleBoard, which is initially generated by shuffling a solved board (to ensure that the board is in a solvable state).
public class DepthFirst {
static HashSet<PuzzleBoard> usedStates = new HashSet<PuzzleBoard>();
public static void DepthFirstSearch(PuzzleBoard currentBoard)
{
// If the current state is the goal, stop.
if (PuzzleSolver.isGoal(currentBoard)) {
System.out.println("Solved!");
System.exit(0);
}
// If we haven't encountered the state before,
// attempt to find a solution from that point.
if (!usedStates.contains(currentBoard)) {
usedStates.add(currentBoard);
PuzzleSolver.print(currentBoard);
if (PuzzleSolver.blankCoordinates(currentBoard)[1] != 0) {
System.out.println("Moving left");
DepthFirstSearch(PuzzleSolver.moveLeft(currentBoard));
}
if (PuzzleSolver.blankCoordinates(currentBoard)[0] != PuzzleSolver.n-1) {
System.out.println("Moving down");
DepthFirstSearch(PuzzleSolver.moveDown(currentBoard));
}
if (PuzzleSolver.blankCoordinates(currentBoard)[1] != PuzzleSolver.n-1) {
System.out.println("Moving right");
DepthFirstSearch(PuzzleSolver.moveRight(currentBoard));
}
if (PuzzleSolver.blankCoordinates(currentBoard)[0] != 0) {
System.out.println("Moving up");
DepthFirstSearch(PuzzleSolver.moveUp(currentBoard));
}
return;
} else {
// Move up a level in the recursive calls
return;
}
}
}
I can assert that my moveUp(), moveLeft(), moveRight(), and moveDown() methods and logic work correctly, so the problem must lie somewhere else.
Here's my PuzzleBoard object class with the hashCode and equals methods:
static class PuzzleBoard {
short[][] state;
/**
* Default constructor for a board of size n
* #param n Size of the board
*/
public PuzzleBoard(short n) {
state = PuzzleSolver.getGoalState(n);
}
public PuzzleBoard(short n, short[][] initialState) {
state = initialState;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.deepHashCode(state);
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PuzzleBoard other = (PuzzleBoard) obj;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (state[i][j] != other.state[i][j])
return false;
}
}
return true;
}
}
As previously stated, sometimes the search works properly and finds a path to the solution, but other times it stops before it finds a solution and before it runs out of memory.
Here is a snippet of the output, beginning a few moves before the search stops searching.
...
Moving down
6 1 3
5 8 2
0 7 4
Moving right
6 1 3
5 8 2
7 0 4
Moving left
Moving right
Moving up
6 1 3
5 0 2
7 8 4
Moving left
Moving down
Moving right
Moving up
Moving up
Moving right
Moving down
Moving up
Moving down
Moving up
Moving down
Moving up
Moving down
Moving up
Moving down
...
I truncated it early for brevity, but it ends up just moving up and down dozens of times and never hits the solved state.
Can anyone shed light on what I'm doing wrong?
Edit: Here is MoveUp(). The rest of the move methods are implemented in the same way.
/**
* Move the blank space up
* #return The new state of the board after the move
*/
static PuzzleBoard moveUp(PuzzleBoard currentState) {
short[][] newState = currentState.state;
short col = blankCoordinates(currentState)[0];
short row = blankCoordinates(currentState)[1];
short targetCol = col;
short targetRow = row;
newState[targetCol][targetRow] = currentState.state[col - 1][row];
newState[targetCol - 1][targetRow] = 0;
return new PuzzleBoard(n, newState);
}
I have had many problems with hashset in the past best thing to try is not to store object in hashset but try to encode your object into string.
Here is a way to do it:-
StringBuffer encode(PuzzleBoard b) {
StringBuffer buff = new StringBuffer();
for(int i=0;i<b.n;i++) {
for(int j=0;j<b.n;j++) {
// "," is used as separator
buff.append(","+b.state[i][j]);
}
}
return buff;
}
Make two changes in the code:-
if(!usedStates.contains(encode(currentBoard))) {
usedStates.add(encode(currentBoard));
......
}
Note:- Here no need to write your own hashcode function & also no need to implement equals function as java has done it for you in StringBuffer.
I got one of the problems in your implementation:-
In th following code:-
static PuzzleBoard moveUp(PuzzleBoard currentState) {
short[][] newState = currentState.state;
short col = blankCoordinates(currentState)[0];
short row = blankCoordinates(currentState)[1];
short targetCol = col;
short targetRow = row;
newState[targetCol][targetRow] = currentState.state[col - 1][row];
newState[targetCol - 1][targetRow] = 0;
return new PuzzleBoard(n, newState);
}
Here you are using the reference of same array as newState from currentState.state so when you make changes to newState your currentState.state will also change which will affect DFS when the call returns. To prevent that you should initialize a new array. Heres what to be done:-
static PuzzleBoard moveUp(PuzzleBoard currentState) {
short[][] newState = new short[n][n];
short col = blankCoordinates(currentState)[0];
short row = blankCoordinates(currentState)[1];
short targetCol = col;
short targetRow = row;
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
newState[i][j] = currentState.state[i][j];
}
}
newState[targetCol][targetRow] = currentState.state[col - 1][row];
newState[targetCol - 1][targetRow] = 0;
return new PuzzleBoard(n, newState);
}
Do this change for all moveup,movedown....
Moreover I donot think your hashset is working properly because if it was then you would always find your new state in hashset and your program would stop. As in equals you comparing the state arrays with same reference hence will always get true. Please try and use my encode function as hash.
I'm currently in the process of building a small Asteroids style game which is intended for use by the kids at a local junior school. The aim is to help them with their times-tables.
A randomly generated question is displayed on-screen, (example: 6 * ? = 12), and a number of star images with numbers on them are floating around, waiting to be be shot at! You control a ship and fly around hunting the correct answer.
Bullets collide with the stars and a test needs to be performed to see if the user has shot the correct answer or not.
The star's filenames are simply "1.png", "2.png" etc, and I have a small function to return the first character of the filename, and convert it to an int:
public rightAnswer() {
String filename = "12.png"; //would be passed as parameters
int coefficient = 2; //
int answer = 24; //
char first = filename.charAt(0);
char second = filename.charAt(1);
int target;
if (second != '.') { //dealing only with 1 or 2-digit numbers
String both = String.valueOf(first) + String.valueOf(second);
target = Integer.parseInt(both);
}
else {
target = Character.digit(first, 10);
}
if (target * coefficient == answer) {
System.out.println("Answer is correct! (target = " + target + ")");
}
else {
System.out.println("Wrong! (target = " + target + ")");
}
}
While writing I got struck by a problem. I can't figure out how to retrieve the filename of the collided star to pass it to the above test function.
edit:
taking a shot at Enno Shioji's solution, I've come to this:
//star map
Map<ImageEntity, Integer> star_number = new HashMap<ImageEntity, Integer>();
//later, while loading the images into the game...
for (int n = 0; n < 10; n++) { // 10 loops
stars[n] = new ImageEntity(this);
String filename = (n+2) + ".png"; // 2- 12 range
stars[n].load(filename);
star_number.put(stars[n], n+2);
}
//then later again, run when collision is detected between a bullet and a star...
public boolean correctAnswer(ImageEntity star, int expectedAnswer) {
if (star_number.get(star) == expectedAnswer)
return true;
else return false;
}
Is this looking right?
I would not try to grab the filename. Instead, you should keep track of which star corresponds to which number, in a Map.
// Do this wherever you have easy access to the file name
Map<Star,Integer> star_number = new HashMap<Star,Integer>();
star_number.put(star1,1);
star_number.put(star2,2);
etc...
//Then later...
boolean collided(Star star, Integer expectedAnswer){
Integer answerGiven = star_number.get(star);
return expectedAnswer.equals(answerGiven);
}
or, you could also keep track by defining the Star object as such:
class Star{
Integer number;
StarImage image;
Star(StarImage image, Integer number){
this.number = number;
this.image = image;
}
// then later...
boolean collided(Star star, Integer expectedAnswer){
return star.number.equals(expectedAnswer);
}
Hope this helps. Good luck with your project :)