人工智能-基于文本的战舰敌人AI不像想要的那样工作- Java



我正在制作一款基于文本的战舰游戏,玩家与电脑对抗。在棋盘上随机放置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;
  }
}

你的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年前编写了一款带有先进AI的战舰游戏。链接到这里: https://github.com/GrahamBlanshard/AI-Battleship/blob/master/prograham/battleship/player/AIPlayer.java

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

在它的核心,你需要创建某种形式的数据类型来存储他的点击。一旦"命中"得分,您将其推入数据类型,我使用的是Stack。成功命中的射击将被存储在堆栈中,直到船被击沉。在这一点上,它从属于刚刚沉没的船只的照片中取出照片。如果堆栈上还有炮弹,它知道在这个过程中它击中了第二艘船,并继续在该区域猜测。

为了完成这个任务,它经历了以下几个阶段:

1)随机射击直到命中。

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

3)用这两个点画一条"线",沿着这条线射击,直到船沉没或……

4)把线倒过来,朝另一个方向拍。

这会给你一个好的开始吗?

要看的代码太多了。所以现在我将给出一些想到的一般建议:

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

最新更新