// CONCURRENCIA rebre i enviar
  // Aquests dos métodes utilitzen recursos compartits, els buffers d'enviament
  // i recepció, per tant els synchronitzem.
  public synchronized void rebre(SelectionKey clau) throws IOException {
    SocketChannel s = ((SocketChannel) clau.channel());
    int userId = arraySocketChannels.indexOf(s);
    bbReceptor.clear();
    s.read(bbReceptor);
    bbReceptor.flip();

    // Comprovem que hagi rebut un Integer
    if (bbReceptor.remaining() == 4) controlador.keyPressed(bbReceptor.getInt(), userId);
  }
  @Override
  public void update(Observable o, Object arg) {

    // ENVIAR POSICIONS
    // Si el que volem és actualitzar les posicions al joc
    if (arg instanceof int[]) {
      int[] lastPosition = (int[]) arg;
      enviar(lastPosition);
    }

    // ACABAR PARTIDA
    // Si el que volem és acabar la partida
    else if (arg instanceof Integer) {
      if ((int) arg == Const.ACABA_PARTIDA) {
        System.out.println(
            "~Partida Acabada | Desconectem " + arraySocketChannels.size() + " jugadors");
        controlador.acaba();
        enviar(Const.FINISH_CODE);

        System.out.print("Cancelació de les Claus...");

        // CONCURRENCIA claus
        // Les claus son recursos compartits. Un dels problemes que ens podem trobar,
        // es que abans de que els clients rebin el FINISH_CODE, enviïn un paquet,
        // i quan es procesi la clau sigui cancelada.

        // CANCELEM LES CLAUS
        // Hem de cancelar només les claus que pertanyen a conexions amb
        // clients, que son les que retornen un SocketChannel quan invoquem
        // key.channel()
        synchronized (this) {
          for (SelectionKey key : selector.keys()) {
            if (key.channel() instanceof SocketChannel
                && arraySocketChannels.contains((SocketChannel) key.channel())) {
              key.cancel();
              System.out.print(" | Clau cancelada");
            }
          }
        }
        arraySocketChannels.clear();
        System.out.println("\nArray de SocketChannels 'cleared'");
      }
    }
  }
  public void ferAccept(SelectionKey clau) throws IOException {
    SocketChannel s = ((ServerSocketChannel) clau.channel()).accept();
    s.configureBlocking(false);
    s.register(selector, SelectionKey.OP_READ);
    arraySocketChannels.add(s);

    System.out.println("Conexió Acceptada | " + arraySocketChannels.size() + " jugadors conectats");

    // INICI DEL JOC
    // Inicia el Joc quan es conecta el 2n Jugador
    if (arraySocketChannels.size() > 1) {
      System.out.println("~Comença el Joc!~");
      controlador.inici();

      // Fem Broadcast de les millors puntuacions
      int[] score = model.getBestScore();
      enviar(new int[] {Const.ENVIA_PUNTIACIONS, Const.ENVIA_PUNTIACIONS, score[0], score[1]});
    }
  }