2d-board algorithm: Total number of different moves to reach a location

Please support our C advertiser: Programming Forums - DaniWeb Sister Site
Reply

Join Date: Sep 2009
Posts: 6
Reputation: macdonald12 is an unknown quantity at this point 
Solved Threads: 0
macdonald12 macdonald12 is offline Offline
Newbie Poster

2d-board algorithm: Total number of different moves to reach a location

 
0
  #1
Oct 8th, 2009
Hello all,

I'm trying to make a program in C, but it's actually the algorithm that's giving me hell.

The goal is to create a program that calculates and displays the total number of end-locations (all locations, including similar ones) an object can reach in a 2d board (grid), using a defined maximum of moves, using only pre-defined movements.

For example, if the object would start at (0,0), and the movements would be defined as:

movement1: (x+3) (y+1)
movement 2: (x+2) (y+3)

and the maximum of allowed moves would be 8. Then what would all the possible end-location coordinates be? (of the in total (2*2*2*2*2*2 = 64 moves?).

It's probably very easy, but i've been going crazy over it for a couple of hours now - and i keep on ending up with nested for-loops that just don't work out.

If anyone out here could give me a push into the right direction, it would be very much appreciated!
Last edited by macdonald12; Oct 8th, 2009 at 3:29 pm.
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 33
Reputation: SVR is an unknown quantity at this point 
Solved Threads: 4
SVR SVR is offline Offline
Light Poster
 
0
  #2
Oct 8th, 2009
If speed is not critical use a recursive function.

  1. GenNextMove(int depth)
  2. {
  3. if(depth == nMaxMove)
  4. {
  5. nTotalPos++;
  6. return;
  7. }
  8. for(i = 0;i<nMoves;i++)
  9. {
  10. GenNextMove(depth+1);
  11. }
  12.  
  13. }
  14.  
  15. main(...)
  16. {
  17. GenNextMove(0);
  18. }

You can pass the current position as well to store in a final positions array when MaxMoves is reached.
Reply With Quote Quick reply to this message  
Join Date: Sep 2009
Posts: 6
Reputation: macdonald12 is an unknown quantity at this point 
Solved Threads: 0
macdonald12 macdonald12 is offline Offline
Newbie Poster
 
0
  #3
Oct 8th, 2009
Thank you very much for your input SVR, i've used it to create the following code for me to practice and understand:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int x, y = 0;
  5.  
  6. int endLocations = 0;
  7. int maxJumps = 8;
  8.  
  9. void nextJump(int depth) {
  10.  
  11. if(depth == maxJumps) {
  12. printf("Endposition (x,y) = (%d,%d)\n", x, y);
  13. endLocations++;
  14. return;
  15. }
  16.  
  17. int i;
  18.  
  19. for(i=1;i<3; i++) {
  20.  
  21. switch(i) {
  22.  
  23. case 1:
  24. x = x+3;
  25. y = y+1;
  26. case 2:
  27. x = x+2;
  28. y = y+3;
  29. }
  30. nextJump(depth+1);
  31. }
  32. }
  33.  
  34. int main (int argc, char *argv[]) {
  35.  
  36. nextJump(1);
  37. printf("Total endlocations: %d\n", endLocations);
  38.  
  39. return 0;
  40. }

Considering it's getting late and i probably need some sleep, i'm most likely doing something stupid now - as this keeps on returning 128 endlocations which don't look correct.

Any further help would be much appreciated, thanks alot for your input already
Last edited by macdonald12; Oct 8th, 2009 at 6:07 pm.
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 33
Reputation: SVR is an unknown quantity at this point 
Solved Threads: 4
SVR SVR is offline Offline
Light Poster
 
0
  #4
Oct 8th, 2009
You'll want to keep your x & y local so each move is incremented from the correct position (you'll need to pass these in as params with the starting position sent in the first call). As it is the global position is getting added to (which is the last end position you happen to be on). The local version gets restored as you return to the previous depth and things can continue from there.

As for the depth, you are starting at 1. You should start at 0. 0 position being the start and not a move).
For each path down to MaxMove you will get positions as such ...

0: x = ?, y = ? // start pos
1: x = ?, y = ? // after move 1
2: ...
...
maxJumps: x = endx, y = endy // after maxJumps

Put a printf before the maxJumps check.

With 2 options and 8 depth I think it should give you 2^8 or 256 end positions.
Reply With Quote Quick reply to this message  
Join Date: Sep 2009
Posts: 6
Reputation: macdonald12 is an unknown quantity at this point 
Solved Threads: 0
macdonald12 macdonald12 is offline Offline
Newbie Poster
 
0
  #5
Oct 13th, 2009
Thanks again for your help! With it i was able to make a program that simulates the movement of an object in an infinite 2d-board. The movements of this object correspond to the movements of a knight in a chess-game.

This is the code for the program:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int endLocations = 0;
  5. int routes = 0;
  6.  
  7. int xNew, yNew;
  8.  
  9.  
  10. void nextJump(int depth, int x, int y, int xEnd, int yEnd, int totalMovesAllowed) {
  11.  
  12. int xValue = x;
  13. int yValue = y;
  14.  
  15. if(depth == totalMovesAllowed) {
  16. if(xValue == xEnd && yValue == yEnd)
  17. routes++;
  18. endLocations++;
  19. return;
  20. }
  21.  
  22. int i;
  23.  
  24. for(i=1;i<9; i++) {
  25.  
  26. /** Represents all eight movements a Knight can make **/
  27. switch(i) {
  28.  
  29. case 1:
  30. xNew = xValue+2;
  31. yNew = yValue+1;
  32. break;
  33. case 2:
  34. xNew = xValue+2;
  35. yNew = yValue-1;
  36. break;
  37. case 3:
  38. xNew = xValue-2;
  39. yNew = yValue+1;
  40. break;
  41. case 4:
  42. xNew = xValue-2;
  43. yNew = yValue-1;
  44. break;
  45. case 5:
  46. xNew = xValue+1;
  47. yNew = yValue+2;
  48. break;
  49. case 6:
  50. xNew = xValue+1;
  51. yNew = yValue-2;
  52. break;
  53. case 7:
  54. xNew = xValue-1;
  55. yNew = yValue+2;
  56. break;
  57. case 8:
  58. xNew = xValue-1;
  59. yNew = yValue-2;
  60. break;
  61. }
  62. nextJump(depth+1, xNew, yNew, xEnd, yEnd, totalMovesAllowed);
  63. }
  64. }
  65.  
  66. int main (int argc, char *argv[]) {
  67.  
  68. int xBegin, yBegin, xEnd, yEnd, totalMovesAllowed;
  69.  
  70. printf("Check total amount of Knightjump routes\n");
  71. printf("Coordinates begin position: x y: ");
  72. scanf("%d %d", &xBegin, &yBegin);
  73. printf("Coordinates end position: x y : ");
  74. scanf("%d %d", &xEnd, &yEnd);
  75. printf("Number of allowed jumps: ");
  76. scanf("%d", &totalMovesAllowed);
  77.  
  78. /** Check 1 for increased efficiency
  79. this is a simple check, checking for the minimum distance that needs to be covered to even reach the end-spot
  80. **/
  81.  
  82. int deltaX, deltaY, movesNeededX, movesNeededY, totalMovesNeeded;
  83. deltaX = xEnd-xBegin;
  84. deltaY = yEnd-yBegin;
  85.  
  86. if(deltaX<0)
  87. deltaX = deltaX*-1;
  88. if(deltaY<0)
  89. deltaY = deltaY*-1;
  90.  
  91. movesNeededX=deltaX/2;
  92. movesNeededY=deltaY/2;
  93.  
  94. if(movesNeededX<1)
  95. movesNeededX=1;
  96. if(movesNeededY<1)
  97. movesNeededY=1;
  98.  
  99. if(movesNeededX >= movesNeededY)
  100. totalMovesNeeded = movesNeededX+1;
  101. else
  102. totalMovesNeeded = movesNeededY+1;
  103.  
  104. if(totalMovesAllowed >= totalMovesNeeded)
  105. {
  106.  
  107. /** Check 2 for increased efficiency
  108. This check checks for the fact that a knight-move, on a black/white-square colored board
  109. will always move from black -> white or vice-versa.**/
  110.  
  111. int beginSquare, endSquare;
  112.  
  113. if((xBegin+yBegin)%2 != 0)
  114. beginSquare = 0;
  115. else
  116. beginSquare = 1;
  117. if((xEnd+yEnd)%2 != 0)
  118. endSquare = 0;
  119. else
  120. endSquare = 1;
  121.  
  122. int difference = totalMovesAllowed%2;
  123.  
  124. if(beginSquare == endSquare && difference == 0) {
  125. /** Checks passed - Call actual function **/
  126. nextJump(0,xBegin,yBegin, xEnd, yEnd, totalMovesAllowed);
  127. } else if(beginSquare == endSquare && difference != 0) {
  128. /* not possible -> do nothing */
  129. } else if(beginSquare != endSquare && difference == 0) {
  130. /*not possible -> do nothing */
  131. } else if(beginSquare != endSquare && difference != 0) {
  132. /** Checks passed - Call actual function **/
  133. nextJump(0,xBegin,yBegin, xEnd, yEnd, totalMovesAllowed);
  134. }
  135. }
  136. printf("\nTotal amount of routes: %d\n", routes);
  137.  
  138. return 0;
  139. }


Resulting in the following output with the given input:


However, i'm supposed to be making this program more efficient - so it can calculate upfront if a given end-position can be reached from the begin-position in the given amount of moves, so that it doesn't need to calculate all routes just to come to that conclusion.

For this i added 2 checks, i think the 2nd check is fairly simple and implemented correct, however, i'm not so sure on the first check.

If anyone can give some input regarding this it would be much appreciated. And thanks again, SVR!
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 33
Reputation: SVR is an unknown quantity at this point 
Solved Threads: 4
SVR SVR is offline Offline
Light Poster
 
0
  #6
Oct 14th, 2009
Originally Posted by macdonald12 View Post
i'm supposed to be making this program more efficient - so it can calculate upfront if a given end-position can be reached from the begin-position in the given amount of moves, so that it doesn't need to calculate all routes just to come to that conclusion.
That is a typical search problem. The given solution is a 'depth first' search where you search down the chain of moves before considering other moves. Potentially more efficient is a 'breadth first' search where you look at all moves at a given depth before proceeding down the chain.
Each has it's merit for a given task.

Most chess programs use a combination algorithm. Do a web search for 'A* search' and 'iterative deepening'.

Some of the logic can get pretty hairy so enjoy

As far as the current code, you should check the xEnd & yEnd before the depth. Otherwise you're only going to get routes that are maxMoves long. It may take less than that.

I dont see anything glaringly wrong with your check#1. It makes sense that the knight can move a max of 2 in any move so anything farther than movesallowed*2 can't be reached.
I bet if you think on it hard enough you can expand that logic to determine exactly how many moves it will take without having to search at all.
Last edited by SVR; Oct 14th, 2009 at 10:49 am.
Reply With Quote Quick reply to this message  
Reply

Message:




Views: 328 | Replies: 5
Thread Tools Search this Thread



Tag cloud for C
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC