class Damier {
  
  int nbL;
  int nbC;
  int nbJ;
  FenetreGraphique fg;
  Jeton [] tJtn;
  
  Damier(int ty,int tx,int jetons) {
    nbL = ty;
    nbC = tx;
    nbJ = jetons;
    fg = null;
    tJtn = generationJetons();
  }

  Jeton [] generationJetons() {
    boolean [][] tB = new boolean[nbL][nbC];
    Jeton [] t = new Jeton[nbJ];
    for ( int i = 0 ; i < nbJ ; i++ ) {
      int px;
      int py;
      do {
        px =(int) (Math.random()*nbC);
        py =(int) (Math.random()*nbL); }
      while ( tB[py][px] == true );
      tB[py][px] = true;
      t[i] = new Jeton(py,px); }
    return t;
  }
  
  boolean evolutionFinie() {
    return (nbJ == 1);
  }
  
  void gererRebonds() {
    for ( int i = 0 ; i < nbJ ; i++ ) {
      tJtn[i].gererRebond(nbC,nbL); }
  }

  void detruireJeton(int j) {
    nbJ--;
    tJtn[j] = tJtn[nbJ];
  }
  
  void gererChocs1() {
    int [][] mJ = new int[nbL][nbC];
    for ( int l = 0 ; l < nbL ; l++ ) {
      for ( int c = 0 ; c < nbC ; c++ ) {
        mJ[l][c] = -1; } }
    for ( int j = 0 ; j < nbJ ; j++ ) {
      mJ[tJtn[j].pY][tJtn[j].pX] = j; }
    for ( int l = 0 ; l < nbL ; l++ ) {
      for ( int c = 0 ; c < nbC ; c++ ) {
        if ( mJ[l][c] != -1 ) {
          Jeton j1 = tJtn[mJ[l][c]];
          int dir1 = j1.dir;
          int px = c+Jeton.dX[dir1];
          int py = l+Jeton.dY[dir1];
          if ( mJ[py][px] != -1 ) {
            Jeton j2 = tJtn[mJ[py][px]];
            int dir2 = j2.dir;
            if ( (dir1+4)%8 == dir2 ) {
              detruireJeton(mJ[l][c]);
              mJ[l][c] = -1; } } } } }
  }

  void gererChocs2() {
    int [][] futur = new int[nbL][nbC];
    for ( int j = 0 ; j < nbJ ; j++ ) {
      futur[tJtn[j].pY+tJtn[j].dirY][tJtn[j].pX+tJtn[j].dirX]++; }
    int j = 0;
    while ( j < nbJ ) {
      int px = tJtn[j].pX+tJtn[j].dirX;
      int py = tJtn[j].pY+tJtn[j].dirY;
      if ( futur[py][px] > 1 ) {
        detruireJeton(j);
        futur[py][px]--; }
        else {
        j++; } }
  }
  
  void gererDeplacements() {
    for ( int i = 0 ; i < nbJ ; i++ ) {
      tJtn[i].deplacer(); }
  }
  
  void evolution() {
    gererRebonds();
    gererChocs1();
    gererChocs2();
    gererDeplacements();
  }
  
  void afficherEnGraphique() {
    fg.clear();
    fg.setColor(100,100,100);
    for ( int l = 0 ; l <= nbL+2 ; l++ ) {
      fg.drawLine(20,20+l*20,20+(nbC+2)*20,20+l*20); }
    for ( int c = 0 ; c <= nbC+2 ; c++ ) {
      fg.drawLine(20+c*20,20,20+c*20,20+(nbL+2)*20); }
    fg.setColor(50,50,50);
    for ( int l = 0 ; l < nbL+2 ; l++ ) {
      fg.fillRect(21,21+l*20,19,19);
      fg.fillRect(21+(nbC+1)*20,21+l*20,19,19); }
    for ( int c = 1 ; c < nbC+1 ; c++ ) {
      fg.fillRect(21+c*20,21,19,19);
      fg.fillRect(21+c*20,21+(nbL+1)*20,19,19); }
    fg.setColor(120,0,0);
    for ( int j = 0 ; j < nbJ ; j++ ) {
      fg.fillCircle(30+(tJtn[j].pX+1)*20,30+(tJtn[j].pY+1)*20,8); }
    fg.flush();
    FenetreGraphique.wait(100);
  }
  
  public String toString() {
    char [][] tc = new char[nbL+2][nbC+2];
    for ( int l = 1 ; l < nbL+1 ; l++ ) {
      for ( int c = 1 ; c < nbC+1 ; c++ ) {
        tc[l][c] = ' '; } }
    for ( int l = 0 ; l < nbL+2 ; l++ ) {
      tc[l][0] = 'X';
      tc[l][nbC+1] = 'X'; }
    for ( int c = 0 ; c < nbC+2 ; c++ ) {
      tc[0][c] = 'X';
      tc[nbL+1][c] = 'X'; }
    for ( int j = 0 ; j < nbJ ; j++ ) {
      tc[tJtn[j].pY+1][tJtn[j].pX+1] = 'O'; }
    String s = ""+nbJ+"\n";
    for ( int l = 0 ; l < nbL+2 ; l++ ) {
      for ( int c = 0 ; c < nbC+2 ; c++ ) {
        s += tc[l][c]; }
      s += "\n"; }
    return(s);
  }

  void afficher(int mode) {
    if ( mode != 1 ) {
      afficherEnGraphique(); }
    if ( mode != 2 ) {
      Console.afficherln(this); }
  }
  
  void lancement(int mode) {
    if ( mode != 1 ) {
      fg = new FenetreGraphique(10,10,740,700,710,630,"Jetons fous");
      fg.setWindowResizable(false);
      fg.setClearColor(255,255,255);
      fg.clear();
      fg.flush(); }
      else {
      fg = null; }
    afficher(mode);
    while ( !evolutionFinie() ) {
      evolution();
      afficher(mode); }
  }
}