Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在Java模式下工作正常,在Javascript中则不然(算法也有问题)_Algorithm_Processing - Fatal编程技术网

Algorithm 在Java模式下工作正常,在Javascript中则不然(算法也有问题)

Algorithm 在Java模式下工作正常,在Javascript中则不然(算法也有问题),algorithm,processing,Algorithm,Processing,我目前正在自学游戏编程,并重新制作一些经典游戏,以学习不同的技巧和东西(如上一篇文章所建议的) 我成功地编写了PONG代码,现在正在研究Snake(我想这就是Worm的意思)。现在我想出了很多东西,除了两件我想不起来的事情 我的算法很简单:玩家控制头部,身体跟随。头部有自己的类,从那里开始,每个部分都作为一个单独的对象进行控制。每个分段控制由速度向量定义的自身运动。第一段独立于控制其余段的阵列。因此,头部只向第一段发送命令,而第一段将其发送给其余的段 该系统基于BendinPoints。基本上,

我目前正在自学游戏编程,并重新制作一些经典游戏,以学习不同的技巧和东西(如上一篇文章所建议的)

我成功地编写了PONG代码,现在正在研究Snake(我想这就是Worm的意思)。现在我想出了很多东西,除了两件我想不起来的事情

我的算法很简单:玩家控制头部,身体跟随。头部有自己的类,从那里开始,每个部分都作为一个单独的对象进行控制。每个分段控制由速度向量定义的自身运动。第一段独立于控制其余段的阵列。因此,头部只向第一段发送命令,而第一段将其发送给其余的段

该系统基于BendinPoints。基本上,每个线段都有一个变量,用于存储弯曲点坐标和到达该弯曲点时的速度向量。一个标志告诉它当前是拥有一个弯曲点还是可以自由接受一个新坐标

所以当头部转动时,它会传输它转动的位置和转动的方向(速度矢量)。第一段传递给第二段,第二段传递给第三段,依此类推。如果每个段有一个要传递的命令,则每个段只将一个命令传递给下一个。每个细分市场仅在旧订单完成后接收新订单

现在我的问题是双重的。第一:这在Java模式下运行良好,但在Javascript模式下不起作用,我不明白为什么。第二:有时,当我改变方向太快时,除了头部和第一部分以外的身体其他部分似乎失去了方向,偏离了方向

我希望代码注释将解释其余内容。原谅我的幼稚

String MODE;

Menu menu;
String[] menuItems={"START","INSTRUCTIONS","CREDITS","EXIT"};

/*@ pjs font="data/waved.ttf" */
/*@ pjs font="data/sixty.ttf" */
PFont sMenu=createFont("waved",72);
PFont sItem=createFont("sixty",35);

String gOverText="GAME OVER";
String hScoreText="Your score is: ";

String iControl="W,A,S,D turns the Snake in the respective direction.";
String iScore="Each Food increases Score by 1 and a segement is added.";
String iScore2="After every 10 points, number of segments added per Food increases by 1.";

String cBy="coded By";
String cName="Le Shaun";

MenuItem back;

Snake snk;
Food fd;

int hScore;
int dF;

float sWidth=800;
float sHeight=600;

PVector sLoc=new PVector(sWidth/2,sHeight/2);
PVector sVel=new PVector(0,-1);
float sRad=10;
color sCol=#9D6C0A;

PVector fLoc=new PVector(450,300);
float fRad=10;
color fCol=#FCF18C;

void setup(){
  size(int(sWidth),int(sHeight));
  snk=new Snake(sLoc,sVel,sRad,sCol);
  fd=new Food(fLoc,fRad,fCol);
  frameRate(60);

  hScore=0;
  dF=1;

  menu=new Menu("SNAKE",menuItems,sMenu,sItem,color(#9D6C0A),color(#8CC610),color(#EDE724),color(#674707),color(255,0));

  MODE="NIL";

  back=new MenuItem("BACK",sItem,width/2,height/1.5,height/25,color(#8CC610),color(#EDE724),color(#674707),color(255,0));    //Common back button for some of the screens.
}

//Current screen is controlled by MODES. Each MODE defines which parts of the game will run, whether it be individual screens or the main gameplay itself.

void draw(){
  background(#EDB824);

  if(MODE.equals("NIL")){
    menu.render();
    MODE=menu.whichItem();
  }
  else if(MODE.equals("START")){  
    fd.render();
    if(fd.isEaten(snk)){
      for(int i=1;i<=dF;i++){
      snk.sInc();
      }
      hScore++;
    }

    snk.render();
    snk.update();
    if(snk.isDead()){
     MODE="GAMEOVER";
     sLoc=new PVector(width/2,height/2);
     fLoc=new PVector(width/2+100,height/2+100);
     sVel=new PVector(+1,0);
     snk=new Snake(sLoc,sVel,sRad,sCol);
    }

    dF=int(hScore/10)+1;

    textFont(sItem);
    textSize(height/25);
    text(str(hScore),width-textWidth(str(hScore))*3,height-height/25);
  }
  else if(MODE.equals("GAMEOVER")){
    stroke(0);
    fill(#9D6C0A);
    textFont(sMenu);
    textSize(72);
    text(gOverText,width/2-textWidth(gOverText)/2,height/3);
    text(hScoreText+hScore,width/2-textWidth(gOverText)/2,height/2);

    back.render();
    back.update();
    if(back.getClicked()){
      back.unClick();
      MODE="NIL";
      hScore=0;
      frameRate(60);
    }
  }
  else if(MODE.equals("INSTRUCTIONS")){
    stroke(0);
    fill(#9D6C0A);
    textFont(sMenu);
    textSize(72);
    text("INSTRUCTIONS",width/2-textWidth("INSTRUCTIONS")/2,height/3);

    textFont(sItem);
    textSize(20);
    text(iControl,width/2-textWidth(iControl)/2,height/2);
    text(iScore,width/2-textWidth(iScore)/2,height/2+35);
    text(iScore2,width/2-textWidth(iScore2)/2,height/2+70);

    back.render();
    back.update();
    if(back.getClicked()){
      back.unClick();
      MODE="NIL";
    }
  }
  else if(MODE.equals("CREDITS")){
    stroke(0);
    fill(#9D6C0A);
    textFont(sItem);

    textSize(35);
    text(cBy,width/2-textWidth(cBy)/2,height/2);

    textSize(45);
    text(cName,width/2-textWidth(cName)/2,height/1.7);

    back.render();
    back.update();
    if(back.getClicked()){
      back.unClick();
      MODE="NIL";
    }
  }


  //println(MODE);
}

void keyReleased(){
  if(MODE.equals("START")){
    String temp="";
    temp+=key;
    temp=temp.toUpperCase();
    snk.changeDir(temp);

    if(key=='v' || key=='V'){
      frameRate(60);
    }
  }
}

void keyPressed(){
    if(MODE.equals("START")){
    if(key=='v' || key=='V'){
      frameRate(180);
    }
  }
}

void mouseClicked(){
  if(MODE.equals("NIL")){
    menu.passTo(mouseX,mouseY);
  }
  if(MODE.equals("GAMEOVER") || MODE.equals("INSTRUCTIONS") || MODE.equals("CREDITS")){
    back.mClicked(mouseX,mouseY);
  }
}


//Menu class uses the objects from the MenuItem and forms a menu with a title and a list of MenuItem objects.

/*
  Constructor: Str-MenuTitle, Str[]-MenuItems, PF-MenuFont, PF-MenuItemFont, c-TitleColor, c-ItemTextColor, c-ItemBackColor, c-ItemHoverTextColor, c-ItemHoverBackColor.

  Methods:
      void render() - Renders the MenuTitle and the MenuItems.
      void passTo(float,float) - Passes the mouse coords to each MenuItem to check whether it has been clicked.
      void passTo(int) - Resets the clickState of the specified MenuItem by calling the unClick() method on that MenuItem.
      String whichItem() - Checks all the MenuItems for a their clickState and returns the one that's been clicked.
*/

class Menu{
  String titleT;

  PFont titleF;
  PFont menuItem;

  color titleC;

  float spacer;    //This is used to define the space between successive MenuItem objects.
  float iniY=height/2.5;

  MenuItem[] menuItems;

  Menu(String titleT,String[] menuItemsNames,PFont titleF,PFont menuItemF,color titleC,color menuItemC,color menuBackC,color itemHoverC,color backHoverC){
    this.titleT=titleT;
    this.titleF=titleF;
    this.titleC=titleC;

    menuItems=new MenuItem[menuItemsNames.length];  //Initializes the MenuItem objects depending on the array passed to it. This makes the menu system very flexible.
    spacer=48;
    for(int i=0;i<menuItemsNames.length;i++){      
      menuItems[i]=new MenuItem(menuItemsNames[i],menuItemF,width/2,iniY+(spacer*i),height/25,menuItemC,menuBackC,itemHoverC,backHoverC);
    }
  }

  void render(){  //Renders the menu.
    textFont(titleF);
    textSize(92);
    fill(titleC);
    text(titleT,width/2-(textWidth(titleT)/2),height/3.8);

    for(int i=0;i<menuItems.length;i++){
      menuItems[i].update();
      menuItems[i].render();
    }
  }

  void passTo(float mX,float mY){    //This accepts the X,Y mouse coords when the mouse is clicked and passes it to the relevant MenuItem object to check if the click occurs on that object.
    for(int i=0;i<menuItems.length;i++){
      menuItems[i].mClicked(mX,mY);
    }
  }

  /*void passTo(int item){  //This accepts an ineteger value and resets that particular menu item's click state.
    menuItems[item].unClick();
  }*/

  String whichItem(){  //Checks each time if the clickState of any MenuItem object is true. If it is, returns the array position of the relevant object.
    for(int i=0;i<menuItems.length;i++){
      if(menuItems[i].getClicked()){
        menuItems[i].unClick();
        return menuItems[i].menuItem;
      }
    }
    return "NIL";
  }
}


//MenuItem holds the attributes and methods relating to each single item on the menu. Thus each item is treated as a separate object.
//Each MenuItem object comprises mainly of a foreground text and a background object. 



class MenuItem{

  String menuItem;
  PFont menuFont;
  float itemX;
  float itemY;
  float itemSize;
  color itemColor;
  color backColor;
  color pressedColor;
  color pressedBack;

  color presentItem;
  color presentBack;

  float textWidth;

  boolean clickState=false;  //This vairable is used to check the clickState of the menu item. If the mouse is clicked over the menu item, this variable becomes true.

  MenuItem(String menuItem,PFont menuFont,float itemX,float itemY,float itemSize,color itemColor,color backColor,color pressedColor,color pressedBack){
    this.menuItem=menuItem;
    this.menuFont=menuFont;
    this.itemX=itemX;
    this.itemY=itemY;
    this.itemSize=itemSize;
    this.itemColor=itemColor;
    this.backColor=backColor;
    this.pressedColor=pressedColor;
    this.pressedBack=pressedBack;
  }

  void render(){    //Handles the rendering for individual menu objects.
    textFont(menuFont);
    textSize(itemSize);
    textWidth=textWidth(menuItem);

    stroke(0);
    fill(presentBack);
    rectMode(CENTER);
    rect(itemX,itemY,textWidth*1.3,itemSize*1.4,50);

    fill(presentItem);
    text(menuItem,itemX-textWidth/2,itemY+itemSize*.3);
  }

  void update(){             //Constatnly checks for the state of the object. If the mouse is over it a certain style is show and otherwise another style is shown.
    if(mouseX<(itemX+(textWidth*1.3)/2) && mouseX>(itemX-(textWidth*1.3)/2) && mouseY<(itemY+(itemSize*1.4)/2) && mouseY>(itemY-(itemSize*1.4)/2)){
     presentItem=pressedColor;
     presentBack=pressedBack;
     noStroke();
    }
    else{
     presentItem=itemColor;
     presentBack=backColor;
    }
  }

  boolean getClicked(){    //Returns the clickState of the object.
    return clickState;
  }

  void unClick(){      //Resets the click state after having been clicked once.
    clickState=false;
  }

  void mClicked(float mX,float mY){  //Changes the clickState of the object depending on the position of the mouse as inputs.
    if(mX<(itemX+(textWidth*1.3)/2) && mX>(itemX-(textWidth*1.3)/2) && mY<(itemY+(itemSize*1.4)/2) && mY>(itemY-(itemSize*1.4)/2)){
      clickState=true;
      println(menuItem);
    }
  }
}



/*
  All control comes from the Snake's head. The head works directly with the first segment(SnakeBits object) and the first segement works with the rest of the body.
  Each time a food is consumed, a new segment is created, it's position and velocity calculated as per the position of the last segment.
  A loop checks whether each segment is open to receiving a new set of orders(BendingPoint and the velocity for that point), and passes on if so.

*/

class Snake{  //Controls the snake's head as well as the segment objects.  

  PVector sLoc;  //Location and Velocity.
  PVector sVel;

  float sRad;  //Radius and Color
  float shRad;    
  color sCol;

  float baseVel;  //The base velocity of the snake.

  SnakeBits[] sBits={};  //Array of SnakeBits objects that forms the segments.

  PVector hold;

  Snake(PVector sLoc,PVector sVel,float sRad,color sCol){
    this.sLoc=sLoc;
    this.sVel=sVel;
    this.sRad=sRad;
    this.shRad=sRad*1.;
    this.sCol=sCol;
    this.baseVel=abs(sVel.x>0 ? sVel.x : sVel.y);  //The snake is initially given a vector in one of the cardinal directions. Whatever the value of velocity is in either direction is stored.

    hold=PVector.mult(sVel,shRad+sRad);
    hold=PVector.sub(sLoc,hold);
    sBits=(SnakeBits[])append(sBits,new SnakeBits(hold,sVel,sRad,sCol));
  }

  void update(){  //Updates the movement of the head as well as the segments.
    updateBP();

    sLoc.add(sVel);
    for(int i=0;i<sBits.length;i++){
      sBits[i].update();
    }    
  }

  void render(){  //The display.
    stroke(0);
    fill(sCol);
    ellipse(sLoc.x,sLoc.y,shRad*2.2,shRad*2.2);

    for(int i=0;i<sBits.length;i++){
      sBits[i].render();
    }
  }

  void sInc(){  //Gets called each time a food item is eaten, and increases the size of the snake by adding segments based on the velocity vector of the last segment.
    int lastInd=sBits.length-1;
    hold=PVector.mult(sBits[lastInd].sbVel,sRad*2);
    hold=PVector.sub(sBits[lastInd].sbLoc,hold);
    PVector appVel=new PVector(sBits[lastInd].sbVel.x,sBits[lastInd].sbVel.y);
    SnakeBits appBits=new SnakeBits(hold,appVel,sRad,sCol);
    sBits=(SnakeBits[])append(sBits,appBits);
  }

  void changeDir(String dir){  //Gets called when a directional button is pressed. 
    PVector chng=new PVector(0,0);  //Direction change can only occur perpendicular to the current direction. Uses baseVel to set the new direction.
    if(!sBits[0].hasBP){
      if(degrees(sVel.heading())==0 || degrees(sVel.heading())==180){
        if(dir.equals("W")){
          chng=new PVector(0,-baseVel);
          sVel=chng;
          updateFBP();
        }
        else if(dir.equals("S")){
          chng=new PVector(0,baseVel);
          sVel=chng;
          updateFBP();
        }
      }
      else if(degrees(sVel.heading())==90 || degrees(sVel.heading())==-90){
        if(dir.equals("D")){
          chng=new PVector(baseVel,0);
          sVel=chng;
          updateFBP();
        }
        else if(dir.equals("A")){
          chng=new PVector(-baseVel,0);
          sVel=chng;
          updateFBP();
        }
      }
    }
  }

  boolean isDead(){  //Checks for collision against the wall or it's own tail.
    if((sLoc.x-shRad)<0 || (sLoc.x+shRad)>width || (sLoc.y-shRad)<0 || (sLoc.y+shRad)>height){
       println("WALL");
      return true;
    }
    PVector temp;
    for(int i=0;i<sBits.length;i++){ 
      if(dist(sLoc.x,sLoc.y,sBits[i].sbLoc.x,sBits[i].sbLoc.y)<(shRad+sRad-sRad*.6)){
        println("TAIL");
        println(sLoc.x+" "+sLoc.y+" "+sBits[i].sbLoc.x+" "+sBits[i].sbLoc.y+" "+dist(sLoc.x,sLoc.y,sBits[i].sbLoc.x,sBits[i].sbLoc.y)+" "+(shRad+sRad-sRad*.6));
        return true;
      }
    }

    return false;
 }

 void updateFBP(){     //Updates the first segment's BendingPoint.
      sBits[0].takeNewBP(sLoc,sVel);
      sBits[0].hasNewBP(true);  
  }

 void updateBP(){  //Updates the rest of the segments as per the system of receiving new orders once the current orders have been executed.
   for(int i=0;i<sBits.length-1;i++){
     if(sBits[i].hasBP && !sBits[i+1].hasBP){
       sBits[i+1].takeNewBP(sBits[i].newBP,sBits[i].newVel);
       sBits[i+1].hasNewBP(true);
     }
   }
 }


}


/*
  Each SnakeBit has it's independent movement system. It holds a BendPoint(newBP) variable, a New BP Velocity(newVel) variable and a flag(hasBP) to show whether it has a new Bend Point.
  When the SnakeBit already has a BP, it will wait till it reaches that BP and then take on the velocity from newVel. It's flag will be set to false.
  In this state it will be open to receiving a new set of orders: a new BP and the velocity to take on for that BP. Thus new BP's are not taken on till the previous BP has been cleared.
*/

class SnakeBits{  //The individual bits of the snake that make up its body.

  boolean hasBP;

  PVector sbLoc;  //Location and Velocity vectors.
  PVector sbVel;

  float sbRad;  //Radius and color of the segment.
  color sbCol;

  PVector newBP;  //This works with the changeDir() method. It holds the position at which the direction will be changed.
  PVector newVel;  //Stores the new Velocity vector that will be applied when the above position is reached.

  SnakeBits(PVector sbLoc,PVector sbVel,float sbRad,color sbCol){
    this.sbLoc=sbLoc;
    this.sbVel=sbVel;
    this.sbRad=sbRad;
    this.sbCol=sbCol;
    newVel=new PVector(sbVel.x,sbVel.y);
    newBP=new PVector(width*2,height*2);  //Initialized it as such to avoid problems during first run.
    hasBP=false;
  }

  void render(){
    stroke(0);
    fill(sbCol);
    ellipse(sbLoc.x,sbLoc.y,sbRad*2,sbRad*2);
  }

  void update(){
    sbLoc.add(sbVel);  //Both updates the Location and checks if it's time to change direction.
    changeDir(); 
  }

  void changeDir(){
    if(sbLoc.x==newBP.x && sbLoc.y==newBP.y && hasBP){  //As soon as the segment reaches the Location where a change in dir is needed, the Velocity is changed over to the new velocity vector.
      println("FTRUE");
      hasNewBP(false);
      sbVel.x=newVel.x;  sbVel.y=newVel.y;
      newBP=new PVector(width*2,height*2);
    }

  }

  void takeNewBP(PVector pos,PVector vel){  //Called externally by the Snake class. Takes where last segment changed direction and stores that location as well as the new velocity vector.
    newBP.x=pos.x;  newBP.y=pos.y;
    newVel.x=vel.x; newVel.y=vel.y; 
  }

  void hasNewBP(boolean dat){  //Updates the hasBP state by accepting a boolean and assigning it to hasBP.
    hasBP=dat;
  }
}


class Food{

  PVector fLoc;

  float fRad;
  color fCol;

  Food(PVector fLoc,float fRad,color fCol){
    this.fLoc=fLoc;
    this.fRad=fRad;
    this.fCol=fCol;
  }

  void render(){
    stroke(0);
    fill(fCol);
    ellipse(fLoc.x,fLoc.y,fRad*2,fRad*2);
  }

  boolean isEaten(Snake sn){
    PVector temp;
    temp=PVector.sub(fLoc,sn.sLoc);
    if(temp.mag()<(sn.shRad+fRad)){
      reset(sn);
      return true;
    }

    return false;
  }

  void reset(Snake sn){
    boolean set=false;
    PVector tmp=new PVector();
    while(!set){
      tmp=new PVector(random(fRad,width-fRad),random(fRad,height-fRad));
      set=true;
      for(int i=0;i<sn.sBits.length;i++){
        if(dist(tmp.x,tmp.y,sn.sBits[i].sbLoc.x,sn.sBits[i].sbLoc.y)<(fRad+sn.sRad) || dist(tmp.x,tmp.y,sn.sLoc.x,sn.sLoc.y)<(fRad+sn.shRad)){
          set=false;
          break;
        }
      }
    }
    fLoc=tmp;
  }
}
字符串模式;
菜单;
字符串[]menuItems={“开始”、“指令”、“积分”、“退出”};
/*@pjs font=“data/waved.ttf”*/
/*@pjs font=“data/sixty.ttf”*/
PFont sMenu=createFont(“波浪式”,72);
PFont sItem=createFont(“六十”,35);
String gOverText=“游戏结束”;
String hScoreText=“您的分数是:”;
String iControl=“W、A、S、D将蛇转向各自的方向。”;
String iScore=“每种食物增加1分,并添加一个分段。”;
String iScore2=“每10点,每种食物添加的片段数增加1。”;
字符串cBy=“编码依据”;
字符串cName=“leshaun”;
MenuItem back;
Snake-snk;
食品fd;
int-hScore;
int-dF;
浮子开关H=800;
浮子高度=600;
PVector sLoc=新的PVector(sWidth/2,sHeight/2);
PVector sVel=新PVector(0,-1);
浮动sRad=10;
颜色sCol=#9D6C0A;
PVector絮体=新PVector(450300);
浮动fRad=10;
颜色fCol=#FCF18C;
无效设置(){
大小(整数(瑞士)、整数(瑞士));
snk=新蛇(sLoc、sVel、sRad、sCol);
fd=新食品(絮状物、fRad、fCol);
帧率(60);
hScore=0;
dF=1;
菜单=新菜单(“蛇”、菜单项、sMenu、站点、颜色(#9D6C0A)、颜色(#8CC610)、颜色(#EDE724)、颜色(#674707)、颜色(255,0));
MODE=“NIL”;
back=新菜单项(“back”,sItem,width/2,height/1.5,height/25,color(#8CC610),color(#EDE724),color(#674707),color(255,0));//一些屏幕的常用后退按钮。
}
//当前屏幕由模式控制。每个模式定义了游戏的哪些部分将运行,无论是单个屏幕还是主游戏本身。
作废提款(){
背景(EDB824);
如果(模式等于(“零”)){
menu.render();
模式=菜单。whichItem();
}
如果(MODE.equals(“START”){
fd.render();
如果(fd.isEaten(snk)){

对于(int i=1;iJavascript模式,textWidth()似乎有问题;要克服这个问题,可以将textWidth=textWidth(menuItem);在menuItem.render()中更改为textWidth=200;或者找到一个等效的工作模式

顺便说一句,我注意到当我在Javascript中运行它时,它不会使用它的完整大小,而您的size()命令是罪魁祸首。它似乎需要数字而不是变量才能正常工作(将其设置为size(800600);工作正常)

你的另一个问题似乎源于这样一个事实:当你按下一个按钮时,你改变了一些事情,但直到抽签时你才应用这些改变()功能。不幸的是,我无法通过做一些小的更改在您的代码中指出它,这让我相信您需要以不同的方式重构您的转向系统。我的建议是将每个人必须去的地方与前一个地方分离,选择将他必须去的位置和方向存储在ArrayList中,而不是ich基本上会随着每次转弯而增长。然后,蛇的每一个部位都必须经过自己的方向和位置列表,而不考虑前一个部位的瞬间变化。当它到达其中一个位置时,只需将其转到正确的方向,删除到达的方向和位置,然后开始前往下一个oArrayList的基本功能类似于一个队列,您可以在队列末尾添加内容,但从开头删除内容


也许将问题的第二部分贴到第二部分是有意义的,第一部分发生了什么?如果没有,请比“它不起作用”更清楚不,这两个问题完全不同。当我在Java模式下运行代码时,代码实际上会运行,但我面临第二个问题,而且只有当我改变方向太快时才会运行。但在Javascript模式下,菜单本身拒绝显示。你说的“Java模式”和“Javascript模式”是什么意思?Java和JavaScript是完全不同的编程语言。请原谅,我清楚地将这个问题标记为处理问题。我非常清楚Java和JavaScript是两种不同的语言,但如果您不知道我所说的各自模式是什么意思,那么您不熟悉处理,因此不适合帮助me、 这可能会给你一些启示:工作起来很有魅力!:D我使用了LinkedList而不是ArrayList,但算法保持不变,工作起来很漂亮。谢谢。