/*
		Denne filen inneholder kildekoden til hanoi.class, et enkelt .
		Koden er skrevet av Kurt Kristian Lyngholm ing99kkl@studpost.hsh.no
*/


class Pinne {

int etg0, etg1, etg2, pinneNr;

	Pinne( int pinneN ) { // klassens konstruktoer
		pinneNr = pinneN;
		if( pinneNr == 0 ) {
			etg0 = 3;
			etg1 = 2;
			etg2 = 1;
		} // end if
		else {
			etg0 = 0;
			etg1 = 0;
			etg2 = 0;
		} // end else

	}	 // slutt paa konstruktoer


	// "taImot()" returnerer 0 dersom mottak er umulig. Dersom mulig returneres 1.
	// stoerrelse er stoerrelsen paa talliken.

	public int taImot( int stoerrelse ) {		int ledigPlass = -1; 
	// I utgangspunktet regnes med at mottak er umulig, derfor -1

	if( stoerrelse == 0 ) {return 0;}
	// Tester hvilken etg. som er ledig.
	// Dersom ikke ledig forblir ledigPlass == -1
 		if( etg0 == 0 ) {
				ledigPlass = 0;
		} // end if
		else {

			if( etg1 == 0 ) {
				ledigPlass = 1;	
			} // end if	
			else {

				if( etg2 == 0 ) {
					ledigPlass = 2;
				} // end if

			} // end else

		} // end else


		// tester om talliken passer paa ledigPlass.
		// Legger den der dersom mulig, ellers returneres 0
		if( ledigPlass == -1 ) {
			return 0;  // kan ikke ta imot - ingen flytting blir utfoert
		} // end if

		else {

			if( ledigPlass == 0 ) {
				etg0 = stoerrelse;
				return 1;
			} // end if
						
			else {

				if( ledigPlass == 1 ) {
					if( stoerrelse < etg0 ) {
						etg1 = stoerrelse;
						return 1;
					} // end if 
					else { return 0; }
				} // end if

				else {
					if( ledigPlass == 2 ) {
						if( stoerrelse < etg1 ) {
							etg2 = stoerrelse;
							return 1;
						}	// end if
						else { return 0; }
					} // end if		
					else { return 0; }

				} // end else				

			} // end else

		} // end else

	}	 // end taImot()
	// naa er flyttingen utfoert og 1 returnert dersom mulig, ellers returneres 0


	// Funksjonen giBort() tar som argument pinneobjektet det skal gis bort til.
	// Den gir fra seg en tallik dersom mulig.
	// Dersom "til" kan ta imot returneres "1", ellers "0".
	// Dersom det ikke er noen aa gi bort returneres ogsaa "0".

	public int giBort( Pinne til ) {
		int test = 0;

		if( etg2 != 0 ) {
			test = til.taImot( etg2 );
			if( test == 1 ) { etg2 = 0; }
			return test;
		}

		if( etg1 != 0 ) {
			test = til.taImot( etg1 );
			if( test == 1 ) { etg1 = 0; }
			return test;
		}

		if( etg0 != 0 ) {
			test = til.taImot( etg0 );
			if( test == 1 ) { etg0 = 0; }
			return test;
		}
		return 0;
	} // end giBort()
} // end class pinne


//##########################################################
//Denne klassen beskriver hvordan spillebrettet skal se ut på skjermen
class Spillebrett {

	char[][] bilde = new char[3][52]; // Den delen av brettet som endrer seg
	// nullstill med blanke tegn
	Spillebrett() {
    for( int i = 0; i < 3; i++ ) {
      for(int j = 0; j < 52; j++ ) {
        bilde[i][j] = ' ';
      } // end for
    } // end for
	} // end Spillebrett()
	
	void oppdater( Pinne p ) {
		int plassering = 0; // forteller hvilken pinne paa bildet vi arbeider med
		if( p.pinneNr == 0 ) plassering =  4;
    if( p.pinneNr == 1 ) plassering = 20;
    if( p.pinneNr == 2 ) plassering = 36;

		int etg = 0;
		// oppdater alle etasjene paa pinnen med 3 gjennomkjoeringer
		for( int i = 0; i < 3; i++ ) {
			if( i == 0 ) etg = p.etg2;
      if( i == 1 ) etg = p.etg1;
      if( i == 2 ) etg = p.etg0;
			
			if( etg == 0 ) {
				bilde[i][ 0 + plassering ] = ' ';
				bilde[i][ 1 + plassering ] = ' ';
				bilde[i][ 2 + plassering ] = ' ';
				bilde[i][ 3 + plassering ] = ' ';
				bilde[i][ 4 + plassering ] = ' ';
				bilde[i][ 5 + plassering ] = '|';
				bilde[i][ 6 + plassering ] = '|';
				bilde[i][ 7 + plassering ] = ' ';
				bilde[i][ 8 + plassering ] = ' ';
				bilde[i][ 9 + plassering ] = ' ';
				bilde[i][ 10+ plassering ] = ' ';
				bilde[i][ 11+ plassering ] = ' ';
			} // end if
		
			if( etg == 1) {
				bilde[i][ 0 + plassering ] = ' ';
				bilde[i][ 1 + plassering ] = ' ';
				bilde[i][ 2 + plassering ] = ' ';
				bilde[i][ 3 + plassering ] = ' ';
				bilde[i][ 4 + plassering ] = '#';
				bilde[i][ 5 + plassering ] = '#';
				bilde[i][ 6 + plassering ] = '#';
				bilde[i][ 7 + plassering ] = '#';
				bilde[i][ 8 + plassering ] = ' ';
				bilde[i][ 9 + plassering ] = ' ';
				bilde[i][ 10+ plassering ] = ' ';
				bilde[i][ 11+ plassering ] = ' ';
			} // end if
		
			if( etg == 2) {
				bilde[i][ 0 + plassering ] = ' ';
				bilde[i][ 1 + plassering ] = ' ';
				bilde[i][ 2 + plassering ] = '#';
				bilde[i][ 3 + plassering ] = '#';
				bilde[i][ 4 + plassering ] = '#';
				bilde[i][ 5 + plassering ] = '#';
				bilde[i][ 6 + plassering ] = '#';
				bilde[i][ 7 + plassering ] = '#';
				bilde[i][ 8 + plassering ] = '#';
				bilde[i][ 9 + plassering ] = '#';
				bilde[i][ 10+ plassering ] = ' ';
				bilde[i][ 11+ plassering ] = ' ';
			} // end if
			if( etg == 3) {
				bilde[i][  0 + plassering ] = '#';
				bilde[i][  1 + plassering ] = '#';
				bilde[i][  2 + plassering ] = '#';
				bilde[i][  3 + plassering ] = '#';
				bilde[i][  4 + plassering ] = '#';
				bilde[i][  5 + plassering ] = '#';
				bilde[i][  6 + plassering ] = '#';
				bilde[i][  7 + plassering ] = '#';
				bilde[i][  8 + plassering ] = '#';
				bilde[i][  9 + plassering ] = '#';
				bilde[i][ 10 + plassering ] = '#';
				bilde[i][ 11 + plassering ] = '#';
			} // end if
		} // end for
	} // end oppdater

	void skrivUt() {
		// Skriver ut den delen som er statisk over der endringene skjer
		System.out.print( "\n\n\n" +
			"         ||              ||              ||         \n" +								
			"         ||              ||              ||         \n" );

		// Skriver den delen som endrer seg
		for( int i = 0; i < 3; i++ ) {
			for(int j = 0; j < 52; j++ ) {
				System.out.print( bilde[i][j] );
			} // end for
			System.out.print( "\n" );
		} // end for		

	// Skriver ut den delen som er statisk under der endringene skjer
		System.out.print( 
			"====================================================\n\n"
		);
	} // end skrivUt()
} // end class spillebrett


//#######################################################################

public class hanoi {
	public static void main( String[] args ) throws Exception {

		boolean slutt = false;
		int fra, til;  // input fra bruker legges i disse.
		int trekkteller = 0;
		int umulig = 0;
		boolean avbrutt = false;

		Pinne pinne0 = new Pinne( 0 );
		Pinne pinne1 = new Pinne( 1 );
		Pinne pinne2 = new Pinne( 2 );

   Spillebrett brett = new Spillebrett();
		ATConsoleIo input = new ATConsoleIo();
		
		System.out.println( "\n\n\n\n\nVelkommen til hanoi!\ntrykk fra = 0 og til =0 for aa avslutte\n" );	

		while( slutt == false ){

			brett.oppdater( pinne0 );
			brett.oppdater( pinne1 );
			brett.oppdater( pinne2 );
			brett.skrivUt();

			// Tester om forrige trekk var umulig, i saafall skriv forklaring
			if( umulig == 1 ) {
				System.out.println( "Ugyldig trekk, du kan ikke legge en stoerre oppaa en mindre!\n" );
			} // end if

			if( umulig == 2 ) {
				System.out.println( "Ugyldig trekk, du kan ikke flytte fra og til samme pinne!\n" );
			} // end if

			if( umulig == 3 ) {
				System.out.println( "Ugyldig trekk, pinnenummeret eksisterer ikke!\n" );
			} // end if

			if( umulig == 0 ) trekkteller++;
			umulig = 0;			// settes ulik 0 dersom et umulig trekk blir tastet inn

			// Tester om spillet er ferdig
			if( pinne2.etg2 != 0 ) break;

			fra = Integer.parseInt( input.get("flytte fra pinne nr: ") ) - 1 ;
			til = Integer.parseInt( input.get("flytte til pinne nr: ") ) - 1 ;

			// For aa haandtere brukeravsluttning
			if( fra == -1 ) {
				if( til == -1 ) {avbrutt = true; break;}
				else {umulig =	3; continue;}
			}	// end if
	
			if( fra == 0) {
				if( til == 0 ) {umulig =	2; continue;}
				if( til == 1 ) {pinne0.giBort( pinne1 ); continue;}	
				if( til == 2 ) {pinne0.giBort( pinne2 ); continue;}
				else {umulig =	3; continue;}
			}	// end if
		
			if( fra == 1) {
				if( til == 0 ) {pinne1.giBort( pinne0 ); continue;}
				if( til == 1 ) {umulig =	2; continue;}	
				if( til == 2 ) {pinne1.giBort( pinne2 ); continue;}
				else {umulig =	3; continue;}
			}	// end if
		
			if( fra == 2) {
				if( til == 0 ) {pinne2.giBort( pinne0 );	continue;}
				if( til == 1 ) {pinne2.giBort( pinne1 ); continue;}
				if( til == 2 ) {umulig =	2; continue;}
			}	// end if

			umulig = 3;
		} // end while

		if( avbrutt == false) System.out.println( "Jippi!\nDu brukte " + (trekkteller - 1) + " trekk (beste mulige er 7 :)" );
		if( avbrutt == true ) System.out.println( "Spillet ble avbrudt, du brukte " + (trekkteller -1) + " trekk så langt...\n\n");

	} // end main
} // end class hanoi

//#######################################################################



class ATConsoleIo {

  void put( String tekstTilUtskrift ) {
    System.out.print( tekstTilUtskrift );
  }

  String get( String ledetekst ) throws Exception {
    System.out.print( ledetekst );
    java.io.BufferedReader hentetTekst =
      new java.io.BufferedReader(
        new java.io.InputStreamReader( System.in ));

    return hentetTekst.readLine();
  }
} // end ATConsoleIo
