滑动积木块游戏设计— —A*算法的应用

               

滑动积木块游戏设计— —A*算法的应用

主题:

     1. 滑动积木快游戏:一个盒子中有七个格子,里面放了黑色,白色两种木块,三个黑色在左边,三个白色在右边,最右边一个格子空着;

     2. 游戏规则:每一个木块可以跳到相邻的空格中,也可以最多跳过相邻的两个木块到达空格,游戏中将所有白色木块跳到黑色木块左边为成功;

     3. 游戏目标:求最小步数。

设计思路:

    1. 根据初始棋局状态,找出所有可能的下一次走步;

    2. 根据游戏规则,找出最适合的下一次走步,移动木块;

    3. 重复前面两步,直到游戏结束。

模块化

   1.  SIZE:设置积木块数量,默认为3,即白色和黑色的木块各有3个,盒子有7格;

         如果积木块数量为4,则白色和黑色的木块各有4个,盒子有9格;

    2. gn:寻找最有走法时路径耗散值,有两个规则:

          a)  一个木块移入相邻空格,耗散值为1;

          b)  一个木块相邻一个或两个其他木块跳入空格,耗散值为跳过的木块数;

    3. hn:计算出的当前状态的评估函数,值为***每个白色木块前的黑色木块的数目的和***;

    4. status:是一个数组,大小为2*SIZE+1,数组的值:1:黑色木块,-1:白色木块,0:空格;

    5. PrintStatus:在一行上打印当前的棋局状态,耗散值以及评估函数;

    6. SetCurrentStatus:将输入的数组赋值给status;

    7. SetDisspativeValue:将输入的值加到gn上;

    8. SetEvaluationFunction:根据当前的status,计算得到棋局当前的评估函数,赋值给hn;

    9. 两个Status构造函数,无值的默认构造Status对象,需要传值的调用前面三个函数构造Status对象;

    10.  main函数用于测试。

    

    11. end:根据当前状态,查找得到下一步可能的走不的空格所在位编号;

    12. start:查找得到的下一步要移动的木块的位置编号。   

    13. Move:默认构造函数,什么也不干;

     

    14. CalDissipasiveValue:根据当前走步计算路径耗散值;

    15. GetNextMoves:根据当前格局,寻找下一步可能的所有走步,所有走步保存在List表中;

    16. GetNextStatus:根据所有走步的情况,找出所有可能的Status状态;

    17. GetBestNextStatus:调用前面两个函数,找出所有可能的Status,然后比较其中fn最小的,作为当前走步,下一步计算在这步的基础上(fn = gn = hn)。

    

    18. 此处显示了滑动积木快游戏的Main函数,在其中实现了对初始状态的初始化,利用前面类的对象的属性和方法,找出实现滑动积木快游戏的最有走步,我们的目标完成。

结果:

     见下面截图:
      

源代码:

   1. 测试主类 AppMain:

  
  
  1. package ai.ouc.g2;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class AppMain {
  5. public static void main(String args[]){
  6. //首先创建一个棋局作为初始棋局
  7. int[] s = { 1, 1, 1,- 1,- 1,- 1, 0};
  8. int i = 0;
  9. Status firstStat = new Status(s, 0);
  10. Move move = new Move();
  11. List<Status> statList = new ArrayList<Status>();
  12. statList.add(i++,firstStat);
  13. Status curStat1,curStat2,printStat;
  14. do {
  15. curStat2 = statList.get(i- 1);
  16. curStat1 = move.GetBestNextStatus(curStat2);
  17. statList.add(i++, curStat1);
  18. } while (curStat1.hn != 0);
  19. System.out.println( "在下面打印走步:");
  20. System.out.println( " 棋局状态 耗散值 评估函数");
  21. for ( int j = 0;j < statList.size();j++){
  22. printStat = statList.get(j);
  23. printStat.PrintStatus();
  24. }
  25. }
  26. }
   2.Move类:

  
  
  1. package ai.ouc.g2;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.List;
  5. public class Move {
  6. public Move(){
  7. }
  8. private List<boxMove> GetNextMoves(Status stat){
  9. int empty = 0; //记录空格的位置
  10. int i,j; //用于计数的变量
  11. int counter = 0; //计算积木块走步的数量
  12. List<boxMove> moveList = new ArrayList<boxMove>();
  13. for (i = 0;i < stat.status.length;i++){
  14. if (stat.status[i] == 0)
  15. empty = i; //找到空格位置
  16. }
  17. for (j = empty- 3;j <= empty+ 3;j++){
  18. if (j >= 0 && j < Status.SIZE* 2+ 1 && j != empty)
  19. moveList.add(counter++, new boxMove(j,empty));
  20. }
  21. return moveList;
  22. } //根据当前棋局状态,找到下一步可能的boxMove
  23. private List<Status> GetNextStatus(List<boxMove> move,Status stat){
  24. int g1,g2,temp; //用于计算耗散值
  25. g1 = stat.gn;
  26. int[] s;
  27. boxMove pmove = new boxMove();
  28. List<Status> availableStat = new ArrayList<Status>();
  29. for ( int i = 0;i < move.size();i++){
  30. pmove = move.get(i);
  31. g2 = this.CalDissipativeValue(pmove.start, pmove.end);
  32. s = Arrays.copyOf(stat.status, stat.status.length);
  33. temp = s[pmove.start];
  34. s[pmove.start] = s[pmove.end];
  35. s[pmove.end] = temp;
  36. availableStat.add(i, new Status(s,g1+g2));
  37. }
  38. return availableStat;
  39. }
  40. public Status GetBestNextStatus(Status stat){
  41. List<boxMove> moveList = new ArrayList<boxMove>();
  42. List<Status> statList;
  43. Status nextStat;
  44. moveList = this.GetNextMoves(stat);
  45. statList = this.GetNextStatus(moveList, stat);
  46. //在此处计算下一步选择哪个状态,即选择走步
  47. nextStat = statList.get( 0);
  48. Status pstat;
  49. for ( int j = 1;j < statList.size();j++){ //有问题
  50. pstat = statList.get(j);
  51. if ((nextStat.gn + nextStat.hn) > (pstat.gn + pstat.hn)){
  52. nextStat = statList.get(j);
  53. }
  54. }
  55. return nextStat;
  56. } //根据走步boxMove的值,从中找到fn = gn +hn 最小的走步
  57. private int CalDissipativeValue(int st, int en) {
  58. // TODO Auto-generated method stub
  59. int gn = 1;
  60. if ((Math.abs(st-en) == 1) && (Math.abs(st-en) == 2))
  61. gn = 1;
  62. else if (Math.abs(st-en) == 3)
  63. gn = 2;
  64. return gn;
  65. } //CalDissipativeValue,计算路径耗散值
  66. public static void main(String args[]){
  67. int g = 3;
  68. int[] s = {- 1, 1,- 1, 1, 1,- 1, 0};
  69. Status stat = new Status(s,g);
  70. Status nextStat1,nextStat2;
  71. Move mov = new Move();
  72. nextStat1 = mov.GetBestNextStatus(stat);
  73. nextStat2 = mov.GetBestNextStatus(nextStat1);
  74. System.out.println( "在下面打印走步:");
  75. System.out.println( " 棋局状态 耗散值 评估函数");
  76. stat.PrintStatus();
  77. nextStat1.PrintStatus();
  78. System.out.println( "第二次走步:");
  79. nextStat1.PrintStatus();
  80. nextStat2.PrintStatus();
  81. }
  82. }
    3. Status类:

  
  
  1. package ai.ouc.g2;
  2. public class Status {
  3. public static int SIZE = 3; //通过修改SIZE的大小,可以实现不同规格的滑动积木块游戏
  4. int status[] = new int[SIZE* 2+ 1]; //当前格局,1:黑块,-1:白块,0:空格
  5. int gn; //累计路径耗散值(Dissipative value)
  6. int hn; //评价函数(Evaluation function)
  7. public Status(int[] s,int g){
  8. if (s.length != SIZE* 2+ 1)
  9. System.out.println( "Wrong input!");
  10. else{
  11. this.SetCurrentStatus(s);
  12. this.SetDissipativeValue(g);
  13. this.SetEvaluationFunction();
  14. }
  15. }
  16. public Status(){
  17. }
  18. private void SetCurrentStatus(int status[]){
  19. this.status = status;
  20. }
  21. private void SetDissipativeValue(int g){
  22. this.gn += g;
  23. }
  24. private void SetEvaluationFunction(){
  25. this.hn = 0;
  26. for ( int i = 0;i < this.status.length;i++){
  27. if ( this.status[i] == - 1){
  28. for ( int j = i;j >= 0;j--){
  29. if ( this.status[j] == 1)
  30. this.hn++;
  31. }
  32. }
  33. }
  34. } //评估函数的值是当前格局中每个白块前面黑块数目的和
  35. public void PrintStatus(){
  36. for ( int i = 0;i < this.status.length;i++){
  37. if ( this.status[i] == 1)
  38. System.out.print( "(黑)");
  39. else if ( this.status[i] == - 1)
  40. System.out.print( "(白)");
  41. else
  42. System.out.print( "(空)");
  43. }
  44. System.out.print( " " + this.gn);
  45. System.out.println( " " + this.hn);
  46. }
  47. public static void main(String args[]){
  48. int g = 3;
  49. int[] s = { 1,- 1, 1,- 1,- 1, 1, 0};
  50. Status stat = new Status(s,g);
  51. for ( int i = 0;i < stat.status.length;i++){
  52. if (stat.status[i] == 1)
  53. System.out.print( "(黑)");
  54. else if (stat.status[i] == - 1)
  55. System.out.print( "(白)");
  56. else
  57. System.out.print( "(空)");
  58. }
  59. System.out.println();
  60. System.out.println( "耗散值:" + stat.gn);
  61. System.out.println( "评估函数:" + stat.hn);
  62. //stat.ChangeStatus(3, 6);
  63. for ( int i = 0;i < stat.status.length;i++){
  64. if (stat.status[i] == 1)
  65. System.out.print( "(黑)");
  66. else if (stat.status[i] == - 1)
  67. System.out.print( "(白)");
  68. else
  69. System.out.print( "(空)");
  70. }
  71. System.out.println();
  72. System.out.println( "耗散值:" + stat.gn);
  73. System.out.println( "评估函数:" + stat.hn);
  74. }
  75. }
    4.boxMove类:

  
  
  1. package ai.ouc.g2;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class boxMove {
  5. int start;
  6. int end;
  7. public boxMove(int st,int en){
  8. this.start = st;
  9. this.end = en;
  10. }
  11. public boxMove(){
  12. }
  13. public static void main(String args[]){
  14. List<boxMove> moveList = new ArrayList<boxMove>();
  15. moveList.add( 0, new boxMove( 2, 0));
  16. moveList.add( 1, new boxMove( 3, 0));
  17. moveList.add( 2, new boxMove( 4, 0));
  18. moveList.add( 3, new boxMove( 5, 0));
  19. moveList.add( 4, new boxMove( 6, 0));
  20. for ( int i = 0;i < moveList.size();i++) {
  21. boxMove m = moveList.get(i);
  22. System.out.println( " ( " + m.start + " , " + m.end + " ) ");
  23. }
  24. }
  25. }




  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值