基于文本的战舰敌人AI不按预期工作 - Java

时间:2013-01-17 20:29:59

标签: java artificial-intelligence

我正在制作一个基于文本的战舰游戏,而玩家正在对抗计算机。 3个随机的3单位长的船被放置在板上,我希望计算机能够猜测他的最后猜测在哪里,如果他的最后一次猜测是一个打击。 (但是我希望它可以工作,这样他就可以在同一个地方猜测,直到他受到打击并继续猜测,直到他获得整艘船,或者3次点击) 它有点工作;计算机会猜到他的最后一次猜测,如果它是一个命中,但如果他错过了那个猜测,那么他就会开始随机猜测。有人可以帮我一点吗? -getGuess()方法是带有AI的那个 -

/*
 * computer class to handle computers guesses/ etc
 * most methods are copied from player class, but slightly altered to account for variable names
 * Methods that havent been copied have comments
 */ 

public class Computer{
  static int firstCo, secondCo;
  static int[] guessedHits={7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
  //int array to store last guess
  static int[] lastGuess = new int[2];
  //int array to store current guess
  static int[] guess=new int[2];

  public static int[] computerShip1=new int[6];
  public static int[] computerShip2=new int[6];
  public static int[] computerShip3=new int[6];

  /*
   * method to choose random guess for computer - but make it guess around last guess if last guess was a hit
   * return guess coordinate numbers in an array
   */
  public static int[] getGuess(){
    int[] guess=new int[2];
    int firstCo, secCo;
    int ran; //random int between 0 and 1 - will help to make random choices for guesses
    if(isHit(lastGuess[0],lastGuess[1])){
      ran=(int)(Math.random()*2);
      //if ran is 0 and last guesses x coordinate was correct, set next guess to last x, and next y to last y +1
      if((ran==0 && lastGuess[0]==Player.playerShip1[0]) || (ran==0 && lastGuess[0]==Player.playerShip1[2]) || (ran==0 && lastGuess[0]==Player.playerShip1[4])){
        guess[0]=lastGuess[0];
        guess[1]=lastGuess[1]+1;
      //if ran is 1 and last guesses x coordinate was correct, set next guess to last x, and next y to last y -1
      }else if((ran==1 && lastGuess[0]==Player.playerShip1[0]) || (ran==1 && lastGuess[0]==Player.playerShip1[2]) || (ran==1 && lastGuess[0]==Player.playerShip1[4])){
        guess[0]=lastGuess[0];
        guess[1]=lastGuess[1]-1;
      //if ran is 0 and last guesses y coordinate was correct, set next guess to last y, and next x to last x +1
      }else if((ran==0 && lastGuess[1]==Player.playerShip1[1]) || (ran==0 && lastGuess[1]==Player.playerShip1[3]) || (ran==0 && lastGuess[1]==Player.playerShip1[5])){
        guess[0]=lastGuess[0]+1;
        guess[1]=lastGuess[1];
      //if ran is 1 and last guesses y coordinate was correct, set next guess to last y, and next x to last x -1
      }else if((ran==1 && lastGuess[1]==Player.playerShip1[1]) || (ran==1 && lastGuess[1]==Player.playerShip1[3]) || (ran==1 && lastGuess[1]==Player.playerShip1[5])){
        guess[0]=lastGuess[0]-1;
        guess[1]=lastGuess[1];
      }
    return guess;
    }else{
      guess[0]=(int)(Math.random()*7);
      guess[1]=(int)(Math.random()*7);
      return guess;
    }
  }

  public static boolean isHit(int firstC, int secC){
    for(int i=0; i<Player.playerShip1.length; i=i+2){
      if(firstC==Player.playerShip1[i] && secC==Player.playerShip1[i+1]){
        return true;
      }
      if(i==4){
        break;
      }
      }
    for(int i=0; i<Player.playerShip2.length; i=i+2){
      if(firstC==Player.playerShip2[i] && secC==Player.playerShip2[i+1]){
        return true;
      }
        if(i==4){
        break;
        }
      }

    for(int i=0; i<Player.playerShip3.length; i=i+2){
      if(firstC==Player.playerShip3[i] && secC==Player.playerShip3[i+1]){
        return true;
      }
      if(i==4){
        break;
      }
      }

    return false;
  }


  public static void addHits(int firstC, int secC){
    int index=-1;
    for(int i=0; i<guessedHits.length; i++){
      if(guessedHits[i]==7){
        index=i;
        break;
      }
    }
    guessedHits[index]=firstC;
    guessedHits[index+1]=secC;
  }


  public static void setComputerShips(){
   int randX, randY;
   int direction; //will be random int 0-1, determines direction ship will extend(up/down, left/right)

   randX=(int)(Math.random()*7);
   randY=(int)(Math.random()*7);
   direction=(int)(Math.random()*2);

   computerShip1[0]=randX;
   computerShip1[1]=randY;
   if(direction==0){//extend upwards or downwards 2 units(y values change, x stays the same)
    computerShip1[2]=randX;
    computerShip1[4]=randX;
    if(randY>3){//if y value is greater than 3, has to extend down or it wont fit
     computerShip1[3]=randY-1;
     computerShip1[5]=randY-2;
    }else if(randY<2){//if y value is less than 2, has to extend up or it wont fit
     computerShip1[3]=randY+1;
     computerShip1[5]=randY+2;
    }else{//if direction doesnt matter, just extend upwards
     computerShip1[3]=randY+1;
     computerShip1[5]=randY+2;
    }
   }else if(direction==1){//extends left or right 2 units(y values stay the same, x changes)
    computerShip1[3]=randY;
    computerShip1[5]=randY;
    if(randX>3){//if x is greater than 3, must extend left or it wont fit
     computerShip1[2]=randX-1;
     computerShip1[4]=randX-2;
    }else if(randX<2){//if x is less than 2, must extend right or it wont fit
     computerShip1[2]=randX+1;
     computerShip1[4]=randX+2;
    }else{//if direction doesnt matter, just extend right
     computerShip1[2]=randX+1;
     computerShip1[4]=randX+2;
    }
   }
   //do same for both other ships
   do{
   randX=(int)(Math.random()*7);
   randY=(int)(Math.random()*7);
   }while((randX==computerShip1[0] && randY==computerShip1[1])||(randX==computerShip1[2]&&randY==computerShip1[3])||(randX==computerShip1[4]&&randY==computerShip1[5]));
   direction=(int)(Math.random()*2);

   computerShip2[0]=randX;
   computerShip2[1]=randY;
   if(direction==0){
    computerShip2[2]=randX;
    computerShip2[4]=randX;
    if(randY>3){
     computerShip2[3]=randY-1;
     computerShip2[5]=randY-2;
    }else if(randY<2){
     computerShip2[3]=randY+1;
     computerShip2[5]=randY+2;
    }else{
     computerShip2[3]=randY+1;
     computerShip2[5]=randY+2;
    }
   }else if(direction==1){
    computerShip2[3]=randY;
    computerShip2[5]=randY;
    if(randX>3){
     computerShip2[2]=randX-1;
     computerShip2[4]=randX-2;
    }else if(randX<2){
     computerShip2[2]=randX+1;
     computerShip2[4]=randX+2;
    }else{
     computerShip2[2]=randX+1;
     computerShip2[4]=randX+2;
    }
   }
   do{
   randX=(int)(Math.random()*7);
   randY=(int)(Math.random()*7);
   }while((randX==computerShip1[0] && randY==computerShip1[1])||(randX==computerShip1[2]&&randY==computerShip1[3])||(randX==computerShip1[4]&&randY==computerShip1[5])||(randX==computerShip2[0] && randY==computerShip2[1])||(randX==computerShip2[2]&&randY==computerShip2[3])||(randX==computerShip2[4]&&randY==computerShip2[5]));
   direction=(int)(Math.random()*2);

   computerShip3[0]=randX;
   computerShip3[1]=randY;
   if(direction==0){
    computerShip3[2]=randX;
    computerShip3[4]=randX;
    if(randY>3){
     computerShip3[3]=randY-1;
     computerShip3[5]=randY-2;
    }else if(randY<2){
     computerShip3[3]=randY+1;
     computerShip3[5]=randY+2;
    }else{
     computerShip3[3]=randY+1;
     computerShip3[5]=randY+2;
    }
   }else if(direction==1){
    computerShip3[3]=randY;
    computerShip3[5]=randY;
    if(randX>3){
     computerShip3[2]=randX-1;
     computerShip3[4]=randX-2;
    }else if(randX<2){
     computerShip3[2]=randX+1;
     computerShip3[4]=randX+2;
    }else{
     computerShip3[2]=randX+1;
     computerShip3[4]=randX+2;
    }
   }
  }

  public static boolean hasWon(){
    if(guessedHits[17]!=7)
      return true;
    else
      return false;
  }
}

2 个答案:

答案 0 :(得分:1)

你的getGuess()函数是你追求的那个吗?

1)你从不考虑两次猜测同一地点的时间。设置一个布尔值,确定您尝试猜测的坐标是否尚未被猜到。

2)你保持船坐标的方法很尴尬,其中0,2,4是X坐标,而1,3,5是Y坐标?你最好创建一个处理坐标的Ship类,并检查像isHit。

public class Ship {
    int[] xCoords = new int[3];
    int[] yCoords = new int[3];

    public boolean isHit(int x, int y) {
      return (Arrays.asList(xCoords).contains(x) && Arrays.asList(yCoords).contains(y));
    }
}

然后你可以:

if (Player.ship1.isHit(guess[0],guess[1])) {
  ....
}

在它的核心,你有一点路要走。如果你开始解决这个问题,那么你会得到更好的回答,然后回过头来解决你可能遇到的具体问题。在给出代码片段时尽量做到尽可能简洁,因为没有多少人会花很多时间通过整个课程找到一两行给出问题。

祝你好运!

--- --- PS

我在大约3 - 4年前用一些相当先进的人工智能写了一个战舰游戏。我会在这里链接:

https://github.com/GrahamBlanshard/AI-Battleship/blob/master/prograham/battleship/player/AIPlayer.java

首先,我为...蹩脚的代码道歉(我是一个更年轻的程序员,我发誓!)。如果你想查看它以获得很好的提示。简要说明:

它的核心是你需要创建一种存储其命中的数据类型。一旦“命中”得分,你将它推到数据类型,我使用Stack。成功击中的镜头将被存储在堆叠中,直到船沉没为止。此时它会从堆叠中移除属于刚刚沉没的船只的射击。如果仍然在堆叠上有射击,它知道它在该过程中撞到了第二艘船,并继续猜测该区域。

为了实现这一目标,它将经历各个阶段:

1)随机拍摄直至击中。

2)围绕该镜头拍摄(使用随机(4)调用获得N / S / E / W方向) - 继续这样做,直到你获得第二次射击

3)用两个点创建一条“线”并沿着它开火直到船沉没或......

4)反转线并射向另一个方向。

这会给你一个良好的开端吗?

答案 1 :(得分:0)

要查看的代码很多。所以现在我会提出一些想到的一般性建议:

当计算机AI获得“命中”时,设置“全局”标志(更可能是类变量)并“记住”命中发生的位置。在接下来的转弯中,以某个预定顺序(比如北,南,东,西)猜测相邻的方格,直到找到另一个命中。然后设置另一个标志,并在下一个回合猜测与第二次击中相同的方向。只有在找到所有三个匹配时才应重置初始标志。这应该可以解决后续未命中导致计算机AI再次开始随机猜测的问题。