import java.util.Scanner;
import java.util.Random;

public class TicTacToe
{
  // Spielfeld als Bitmaske
  // Erste 9 Bits markieren bei eins, dass das Feld ausgefüllt ist
  // Zweite 9 Bits markieren die Spielernummer (0 oder 1)
  private int mField;

  public static void main(String args[])
    {
    TicTacToe Field          = new TicTacToe();
    Scanner   keyboardReader = new Scanner(System.in);
    int i=0,j=0,iInput=0,iPlayerOnTurn=0,iPlayerBeginTurn=0,iTurnCount=0
           ,KIFirstPlayer=0,KISecondPlayer=0,ScoreFirstPlayer=0,ScoreSecondPlayer=0;
    Boolean BreakUp=false;

    // Informationen
    System.out.println("1 bis 9 zur Feldauswahl, 42 zum Spielabbruch.");

    // KI einschalten oder nicht
    System.out.println("\n0 = Keine KI, 1 = zweiter Spieler KI, 2 = beide KI");
    System.out.print("KI für Spieler: ");
    iInput=keyboardReader.nextInt();
    if (iInput>0) KISecondPlayer=1;
    if (iInput>1) KIFirstPlayer =1;

    // KI-Menü
    if (KISecondPlayer>0||KIFirstPlayer>0)
      {
      // KI-Schwierigkeit
      System.out.println("\n1 = Leicht, 2 = Mittel, 3 = Schwer, 4 = Randomizer, 5 = Zufällig");
      System.out.print("Schwierigkeit: ");
      iInput=keyboardReader.nextInt();
      if (iInput>0&&iInput<6)
        {
        if (KISecondPlayer>0) KISecondPlayer=iInput;
        if (KIFirstPlayer >0) KIFirstPlayer =iInput;
        }
      }

    // Rundenanzahl
    System.out.print("Anzahl der Runden: ");
    while (iTurnCount<=0) iTurnCount=keyboardReader.nextInt();

    // Runden abarbeiten
    while (j++<iTurnCount)
      {
      // Spiel abgebrochen
      if (BreakUp) break;

      // Das hier auf Null
      iInput=0;i=1;

      // Neues Feld mit Nummern
      System.out.print("\nNächste Runde\n1|2|3\n-----\n4|5|6\n-----\n7|8|9\n");

      // Beginnender Spieler
      iPlayerOnTurn=iPlayerBeginTurn;

      // Neues Feld
      Field=new TicTacToe();

      // Nur 9 Züge
      while (i<10)
        {
        // Feld anzeigen
        Field.displayField();

        // Sagen wer am Zug ist
        System.out.println("\n" + Field.getPlayerSymbol(iPlayerOnTurn) + " am Zug \n");

        // Wenn KI dann ziehen lassen sonst Input von irgendjemandem der vorm Rechner bzw. Mac sitzt
        if (iPlayerOnTurn==0&&KIFirstPlayer>0)
          {
          // Spieler 1 am Zug und KI-gesteuert
          iInput=Field.KiTurn(iPlayerOnTurn,KIFirstPlayer,i);
          }
        else if (iPlayerOnTurn==1&&KISecondPlayer>0)
          {
          // Spieler 2 am Zug und KI-gesteuert
          iInput=Field.KiTurn(iPlayerOnTurn,KISecondPlayer,i);
          }
        else
          {
          // sonst Zahl eingeben
          iInput=keyboardReader.nextInt();
          }

        // Spielabbruch
        if (iInput==42) {BreakUp=true; break;}

        // So gehts nicht
        if (iInput<1||iInput>9) continue;

        // Versuche Feld zu Markieren
        if (Field.setField(1<<iInput,iPlayerOnTurn))
          {
          // Anderer Spieler am Zug
          if (iPlayerOnTurn==1)
            iPlayerOnTurn=0;
          else
            iPlayerOnTurn=1;
          }
        // Ging nicht? Nochmal eingeben!
        else
          continue;

        // Hat wer gewonnen?
        if (Field.WinCheck()==0) {ScoreFirstPlayer++;  break;}
        if (Field.WinCheck()==1) {ScoreSecondPlayer++; break;}

        // Anzahl der gemachten Züge erhöhen
        i++;
        }

      // Endzustand anzeigen
      Field.displayField();

      // Anderer Spieler beginnt
      if (iPlayerBeginTurn==1)
        iPlayerBeginTurn=0;
      else
        iPlayerBeginTurn=1;
      }

    // Ende des Spiels, Punkte ausgeben
    System.out.println("\n Spieler " + Field.getPlayerSymbol(0) + ": " + ScoreFirstPlayer  + " Punkte."
                     + "\n Spieler " + Field.getPlayerSymbol(1) + ": " + ScoreSecondPlayer + " Punkte.");
    
    }

  TicTacToe()
    {
    mField=0;
    }

  TicTacToe(int aField)
    {
    mField=aField;
    }

  /*-KI-------*/

  public int KiTurn(int aPlayer,int aDifficulty,int iTurn)
    {
    // KI auswählen
    int markfield=42;
    if (aDifficulty==5) aDifficulty=1+(new Random().nextInt(4));
    switch (aDifficulty) {
    case 1:  { markfield=KiTurnEasy(aPlayer,iTurn);   break; }
    case 2:  { markfield=KiTurnMedium(aPlayer,iTurn); break; }
    case 3:  { markfield=KiTurnHard(aPlayer,iTurn);   break; }
    case 4:  { markfield=KiTurnRandom(aPlayer,iTurn); break; }
    default: { } }
    return markfield;
    }

  public int KiTurnEasy(int aPlayer,int iTurn)
    {
    // Also das ist doch einfach und extrem berechenbar
    if (getPlayerOnPosition(5)<0) return 5;
    if (getPlayerOnPosition(1)<0) return 1;
    if (getPlayerOnPosition(9)<0) return 9;
    if (getPlayerOnPosition(2)<0) return 2;
    if (getPlayerOnPosition(8)<0) return 8;
    if (getPlayerOnPosition(3)<0) return 3;
    if (getPlayerOnPosition(7)<0) return 7;
    if (getPlayerOnPosition(4)<0) return 4;
    if (getPlayerOnPosition(6)<0) return 6;
    return 42;
    }

  public int KiTurnMedium(int aPlayer,int iTurn)
    {
    // Kann ich sofort gewinnen?
    int markfield=getWinnerField(aPlayer);
    // Das dumme java hat leider keine Auto-Bool-Konvertation
    if (markfield==0) if (aPlayer==1) markfield=getWinnerField(0); else markfield=getWinnerField(1);
    // Ziehen falls nötig
    if (markfield>0) return markfield;
    // Keine Strategie
    return KiTurnRandom(aPlayer,iTurn);
    }

  public int KiTurnHard(int aPlayer,int iTurn)
    {
    // Kann ich sofort gewinnen?
    int markfield=getWinnerField(aPlayer);
    // Das dumme java hat leider keine Auto-Bool-Konvertation
    if (markfield==0) if (aPlayer==1) markfield=getWinnerField(0); else markfield=getWinnerField(1);
    // Ziehen falls nötig
    if (markfield>0) return markfield;
    // Strategisch gewinnen oder Unentschieden
    // Erster Zug -> immer links oben
    if (iTurn==1) return(1);
    // Erster Zug als Zweiter -> mitte
    if (iTurn==2)
      {
      if (getPlayerOnPosition(5)<0) return(5);
      if (getPlayerOnPosition(9)<0) return(9);
      }
    // Zweiter Zug -> mitte, sonst -> rechts unten
    if (iTurn==3)
      {
      if (getPlayerOnPosition(5)<0) return(5);
      if (getPlayerOnPosition(9)<0) return(9);
      }
    // Dritter Zug -> links unten oder rechts oben
    if (iTurn==5)
      {
      if (getPlayerOnPosition(7)<0) return(7);
      if (getPlayerOnPosition(3)<0) return(3);
      }
    // Zug irgendwie anders machen
    return KiTurnRandom(aPlayer,iTurn);
    }

  public int KiTurnRandom(int aPlayer,int iTurn)
    {
    // Komplett randomisiert
    int markfield=1+(new Random().nextInt(9));
    while (getPlayerOnPosition(markfield)>-1) markfield=1+(new Random().nextInt(9));
    return markfield;
    }

  /*-Feld-----*/

  public int getField()
    {
    return mField;
    }

  public int getMarkedPosition(int aPos)
    {
    return (mField & (1 << aPos)) >> aPos;
    }

  public int getPlayerOnPosition(int aPos)
    {
    if (getMarkedPosition(aPos)==0) return -1;
    return (mField & (1 << (aPos + 9))) >> (aPos + 9);
    }

  public String getPlayerSymbol(int aPlayer)
    {
    if (aPlayer==0) return "X";
    return "O";
    }

  public int getWinnerField(int aPlayer)
    {
    if (getPlayerOnPosition(5)==aPlayer)
      {
      if (getPlayerOnPosition(1)==aPlayer&&getPlayerOnPosition(9)<0) return 9;
      if (getPlayerOnPosition(9)==aPlayer&&getPlayerOnPosition(1)<0) return 1;
      if (getPlayerOnPosition(8)==aPlayer&&getPlayerOnPosition(2)<0) return 2;
      if (getPlayerOnPosition(2)==aPlayer&&getPlayerOnPosition(8)<0) return 8;
      if (getPlayerOnPosition(3)==aPlayer&&getPlayerOnPosition(7)<0) return 7;
      if (getPlayerOnPosition(7)==aPlayer&&getPlayerOnPosition(3)<0) return 3;
      if (getPlayerOnPosition(4)==aPlayer&&getPlayerOnPosition(6)<0) return 6;
      if (getPlayerOnPosition(6)==aPlayer&&getPlayerOnPosition(4)<0) return 4;
      }
    if (getPlayerOnPosition(1)==aPlayer)
      {
      if (getPlayerOnPosition(2)==aPlayer&&getPlayerOnPosition(3)<0) return 3;
      if (getPlayerOnPosition(3)==aPlayer&&getPlayerOnPosition(2)<0) return 2;
      if (getPlayerOnPosition(4)==aPlayer&&getPlayerOnPosition(7)<0) return 7;
      if (getPlayerOnPosition(7)==aPlayer&&getPlayerOnPosition(4)<0) return 4;
      }
    if (getPlayerOnPosition(9)==aPlayer)
      {
      if (getPlayerOnPosition(8)==aPlayer&&getPlayerOnPosition(7)<0) return 7;
      if (getPlayerOnPosition(7)==aPlayer&&getPlayerOnPosition(8)<0) return 8;
      if (getPlayerOnPosition(6)==aPlayer&&getPlayerOnPosition(3)<0) return 3;
      if (getPlayerOnPosition(3)==aPlayer&&getPlayerOnPosition(6)<0) return 6;
      }
    return 0;
    }

  /*-Anzeige--*/

  private void displayField()
    {
    System.out.println("");
    int i=0;
    while (i++<9)
      {
      if (getMarkedPosition(i)>0)
        System.out.print(getPlayerSymbol(getPlayerOnPosition(i)));
      else
        System.out.print(" ");

      if (i%3>0) System.out.print("|"); else if (i!=9) System.out.print("\n-----\n");
      }
    System.out.println("");
    }

  /*-Setter---*/

  private Boolean setField(int aField, int aPlayer)
    {
    // Feld bereits besetzt
    if ((mField&aField)>0) return false;
    // Feld bei den kleineren Bits besetzen
    mField |= aField;
    // Spieler bei den größeren Bits Markieren
    if (aPlayer==1) mField |= aField << 9;
    // Erfolgreich gesetzt
    return true;
    }

  /*----------*/

  public int WinCheck()
    {
    int a=-1;
    while (++a<2)
      {
      if (getPlayerOnPosition(5)==a)
        {
        if (getPlayerOnPosition(1)==a) if (getPlayerOnPosition(9)==a) return a;
        if (getPlayerOnPosition(2)==a) if (getPlayerOnPosition(8)==a) return a;
        if (getPlayerOnPosition(3)==a) if (getPlayerOnPosition(7)==a) return a;
        if (getPlayerOnPosition(4)==a) if (getPlayerOnPosition(6)==a) return a;
        }

      if (getPlayerOnPosition(1)==a)
        {
        if (getPlayerOnPosition(2)==a) if (getPlayerOnPosition(3)==a) return a;
        if (getPlayerOnPosition(4)==a) if (getPlayerOnPosition(7)==a) return a;
        }

      if (getPlayerOnPosition(9)==a)
        {
        if (getPlayerOnPosition(7)==a) if (getPlayerOnPosition(8)==a) return a;
        if (getPlayerOnPosition(3)==a) if (getPlayerOnPosition(6)==a) return a;
        }
      }
    return -1;
    }
}