Brett.java [Last ned]

/* 
 * Representasjon av spillbrettet.
 */
 
public class Brett {
 
  // Er en celle ledig eller tilhører den en av spillerne?
  public static final int LEDIG     = 0;
  public static final int SPILLER1  = 1;
  public static final int SPILLER2  = 2;
  public static final int UDEFINERT = 3;
 
  // Ulike måter å få "n på rad"
  public static final int DIAGONALOPPHØYRE   = 1;
  public static final int DIAGONALOPPVENSTRE = 2;
  public static final int HORISONTAL         = 3;
  public static final int VERTIKAL           = 4;
 
  // Spillbrettet
  private int[][] brett;
  private int sidelengde;
  private int antPåRadKrav;
 
  // Siste trekk
  private int sisteRad;
  private int sisteKol;
 
 
  public Brett(int sidelengde, int antPåRadKrav) {
    this.sidelengde = sidelengde;
    this.antPåRadKrav = antPåRadKrav;
    brett = new int[sidelengde][sidelengde];
    nullstill();
  }
 
 
  // Tilbakestiller brettet
  public void nullstill() {
    for (int r=0; r<sidelengde; r++)
      for (int k=0; k<sidelengde; k++)
        brett[r][k] = LEDIG;
 
    sisteRad = -1;
    sisteKol = -1;
  }
 
 
  // Markerer i spillbrettet hvis ruten er ledig og spillet ikke er over.
  public void trekk(int r, int k, int spiller) {
    if (ledigRute(r, k) && !avgjort()) {
      brett[r][k] = spiller;
      sisteRad = r;
      sisteKol = k;
    }
  }
 
 
  // Er denne ruten eiet av spiller?
  public boolean spillerRute(int r, int k, int spiller) {
    return (verdi(r,k) == spiller);
  }
 
 
  // Er denne ruten ledig?
  public boolean ledigRute(int r, int k) {
    return (verdi(r,k) == LEDIG);
  }
 
 
  // Har spiller vunnet?
  public boolean spillerVant(int spiller) {
    for (int r=0; r<sidelengde; r++)
      for (int k=0; k<sidelengde; k++)
        if ((maxPåLinje(r, k)>=antPåRadKrav
             && verdi(r,k)==spiller))
          return true;
 
    return false;
  }
 
 
  // Ble det uavgjort?
  public boolean uavgjort() {
    return (ingenLedige() && !spillerVant(SPILLER1) && !spillerVant(SPILLER2));
  }
 
 
  // Er spillet over?
  public boolean avgjort() {
    return (spillerVant(SPILLER1) || spillerVant(SPILLER2) || ingenLedige());
  }
 
 
  // Ble siste trekk utført i denne ruten?
  public boolean sisteTrekk(int r, int k) {
    return (r==sisteRad && k==sisteKol);
  }
 
 
  // Er denne ruten med i en seiersrekke?
  public boolean påSeiersRekke(int r, int k) {
    return (maxPåLinje(r, k) == antPåRadKrav);
  }
 
 
  // Gir størrelsen på spillbrettet (sidelengde).
  public int sidelengde() {
    return sidelengde;
  }
 
 
  // Beregner største antall kryss langs en linje som kan
  // utvides til antPåRadKrav og som inneholder (rad,kol).
  public int maxSekvens(int rad, int kol, int linje, int spiller) {
    if (verdi(rad, kol) != spiller && verdi(rad,kol) != LEDIG)
      return 0;
 
    int dR = settRadDiff(linje);
    int dK = settKolDiff(linje);
 
    int antall = 0;
    int r1 = rad;
    int k1 = kol;
    int blanke1 = 0;
    int r2 = rad - dR;
    int k2 = kol - dK;
    int blanke2 = 0;
 
    boolean utvidbar = true;
    while (antall+blanke1+blanke2 < antPåRadKrav && utvidbar) {
      if (verdi(r1,k1) == spiller) {
        antall++;
        r1 = r1 + dR;
        k1 = k1 + dK;
      }
      else if (verdi(r2,k2) == spiller) {
        antall++;
        r2 = r2 - dR;
        k2 = k2 - dK;
      }
      else if (blanke1 < blanke2 && verdi(r1,k1) == LEDIG) {
        blanke1++;
        r1 = r1 + dR;
        k1 = k1 + dK;
      }
      else if (verdi(r2,k2) == LEDIG) {
        blanke2++;
        r2 = r2 - dR;
        k2 = k2 - dK;
      }
      else if (verdi(r1,k1) == LEDIG) {
        blanke1++;
        r1 = r1 + dR;
        k1 = k1 + dK;
      }
      else
        utvidbar = false;
    }
 
    if (utvidbar)
      return antall;
    else
      return 0;
  }
 
 
  // Er ruten (r1,k1) nærmere midten enn ruten (r2,k2)?
  public boolean nærmereMidten(int r1, int k1, int r2, int k2) {
    int rm = sidelengde/2;
    int km = sidelengde/2;
    return (avstand(r1, k1, rm, km) < avstand(r2, k2, rm, km));
  }
 
 
  // Største antall på rad gjennom ruten (r,k) 
  // for spiller som har satt celle (r,k)
  private int maxPåLinje(int r, int k) {
    int celle = verdi(r, k);
    if (celle == LEDIG)
      return 0;
    return Math.max(
             Math.max(maxSekvens(r,k,DIAGONALOPPHØYRE, celle),
                      maxSekvens(r,k,DIAGONALOPPVENSTRE, celle)),
             Math.max(maxSekvens(r,k,HORISONTAL, celle),
                      maxSekvens(r,k,VERTIKAL, celle)));
  }
 
 
 
  // Er det noen ledige ruter igjen?
  private boolean ingenLedige() {
    for (int r=0; r<sidelengde; r++)
      for (int k=0; k<sidelengde; k++)
        if (verdi(r, k) == LEDIG)
          return false;
    return true;
  }
 
 
  // Finn horisontal leteretning
  private int settRadDiff(int linje) {
    int dR;
    if (linje == HORISONTAL)
      dR = 0;
    else
      dR = -1;
    return dR;
  }
 
 
  // Finn vertikal leteretning
  private int settKolDiff(int linje) {
    int dK;
    if (linje == VERTIKAL)
      dK = 0;
    else if (linje == HORISONTAL || linje == DIAGONALOPPHØYRE)
      dK = 1;
    else
      dK = -1;
    return dK;
  }
 
 
  // Avstanden mellom to ruter
  private int avstand(int r1, int k1, int r2, int k2) {
    return (int) Math.sqrt(Math.pow(r2-r1, 2) + Math.pow(k2-k1, 2));
  }
 
 
  // Indeksering utenfor tabellgrensene håndteres ved at det
  // legges en tenkt rad med "udefinerte" celler.
  private int verdi(int r, int k) {
    if (r >= 0 && r < sidelengde && k >= 0 && k < sidelengde)
      return brett[r][k];
    else
      return UDEFINERT;
  }
 
}
 
Kildekode blir vist ved hjelp av GeSHi.