Teoria dei Giochi

Dama Italiana

  Move.java


Metodo per la gestione del giocatore umano
generates_moves
cattureMultiple
eseguiMossa


Codice


import java.util.*;


Indice 
/**
  *	Classe che genera le mosse possibili da eseguire e gestisce le esecuzioni delle mosse.
  */
public class Move
{
	//private class

//	I) definizione dei campi della classe: costanti che indicano il tipo di mossa

	final static int LEGALMOVE = 1;				// valore per indicare che la mossa e' legale
	final static int ILLEGALMOVE = 2;			// valore per indicare che la mossa e' illegale
	final static int INCOMPLETEMOVE = 3;			// valore per indicare che la mossa e' una cattura multipla


/*
	static boolean noMovesLeft(int[][] position,int toMove)
	{
		System.out.println("*****");
		for (int i=0; i<8; i++)
			for (int j=0; j<8; j++)
				if ( (float)(i+j)/2 == (i+j)/2 )
				{
					if (toMove == Checkers.WHITE &&
							(position[i][j] == Checkers.WHITE ||
									position[i][j] == Checkers.WKING))
					{
						if (canWalk(position,i,j)) return false;
						else if (canCapture(position,i,j)) return false;
					}
					else if (toMove == Checkers.BLACK &&
							(position[i][j] == Checkers.BLACK ||
									position[i][j] == Checkers.BKING))
					{
						if (canWalk(position,i,j)) return false;
						else if (canCapture(position,i,j)) return false;
					}
				} // if and for
		return true;
	}
*/

	/**
	  *	Metodo per stampare la mossa che si sta eseguendo
	  *	@param moves le coordinate della mossa
	  */

	static void printMoves(Vector> moves){
		System.out.println("MOSSE:");
		for(int i=0; i> mosseObbligate)
	{
		System.out.println("ESEGUO MOSSA: ("+startR+","+startC+")->("+endR+","+endC+")");
		System.out.println("INC IND:"+incInd);
		int i=0;
		//for(int i=0; i-1 && j+2<8)
				if ( (position[i-1][j+1] == Checkers.BLACK ||
						position[i-1][j+1] == Checkers.BKING)
						&&
						position[i-2][j+2] == Checkers.EMPTY)
					return true;
			break;
		case Checkers.BLACK:
			if (i+2<8 && j-2>-1)
				if ( (position[i+1][j-1] == Checkers.WHITE ||
						position[i+1][j-1] == Checkers.WKING)
						&&
						position[i+2][j-2] == Checkers.EMPTY)
					return true;
			if (i-2>-1 && j-2>-1)
				if ( (position[i-1][j-1] == Checkers.WHITE ||
						position[i-1][j-1] == Checkers.WKING)
						&&
						position[i-2][j-2] == Checkers.EMPTY)
					return true;
			break;
		case Checkers.WKING:
			if (i+2<8)
			{
				if (j+2<8)
					if ( (position[i+1][j+1] == Checkers.BLACK ||
							position[i+1][j+1] == Checkers.BKING )
							&&
							position[i+2][j+2] == Checkers.EMPTY)
						return true;
				if (j-2>-1)
					if ( (position[i+1][j-1] == Checkers.BLACK ||
							position[i+1][j-1] == Checkers.BKING )
							&&
							position[i+2][j-2] == Checkers.EMPTY)
						return true;
			}
			if (i-2>-1)
			{
				if (j+2<8)
					if ( (position[i-1][j+1] == Checkers.BLACK ||
							position[i-1][j+1] == Checkers.BKING )
							&&
							position[i-2][j+2] == Checkers.EMPTY)
						return true;
				if (j-2>-1)
					if ( (position[i-1][j-1] == Checkers.BLACK ||
							position[i-1][j-1] == Checkers.BKING )
							&&
							position[i-2][j-2] == Checkers.EMPTY)
						return true;
			}
			break;
		case Checkers.BKING:
			if (i+2<8)
			{
				if (j+2<8)
					if ( (position[i+1][j+1] == Checkers.WHITE ||
							position[i+1][j+1] == Checkers.WKING )
							&&
							position[i+2][j+2] == Checkers.EMPTY)
						return true;
				if (j-2>-1)
					if ( (position[i+1][j-1] == Checkers.WHITE ||
							position[i+1][j-1] == Checkers.WKING )
							&&
							position[i+2][j-2] == Checkers.EMPTY)
						return true;
			}
			if (i-2>-1)
			{
				if (j+2<8)
					if ( (position[i-1][j+1] == Checkers.WHITE ||
							position[i-1][j+1] == Checkers.WKING )
							&&
							position[i-2][j+2] == Checkers.EMPTY)
						return true;
				if (j-2>-1)
					if ( (position[i-1][j-1] == Checkers.WHITE  ||
							position[i-1][j-1] == Checkers.WKING )
							&&
							position[i-2][j-2] == Checkers.EMPTY)
						return true;
			}
			break;
		} // switch
		return false;
	} // canCapture()
*/

/*
	// canWalk() returns true if the piece on (i,j) can make a
	// legal non-capturing move
	static boolean canWalk(int[][] position, int i, int j)
	{
		switch ( position[i][j] )
		{
		case Checkers.WHITE:
			if ( isEmpty(position,i+1,j+1) || isEmpty(position,i-1,j+1) )
				return true;
			break;
		case Checkers.BLACK:
			if ( isEmpty(position,i+1,j-1) || isEmpty(position,i-1,j-1) )
				return true;
			break;
		case Checkers.WKING:
		case Checkers.BKING:
			if ( isEmpty(position,i+1,j+1) || isEmpty(position,i+1,j-1)
					|| isEmpty(position,i-1,j+1) || isEmpty(position,i-1,j-1) )
				return true;
		} // switch
		return false;
	} // canWalk()
*/

	/**
	  *	Metodo che controlla se la posizione della board passata e' vuota
	  *	@param position la board di gioco
	  *	@param i coordinata x della posizione da controllare
	  *	@param j coordinata y della posizione da controllare
	  *	@return true nel caso in cui sia vuota, false altrimenti
	  */
	private static boolean isEmpty(int[][] position, int i, int j)
	{
		if (i>-1 && i<8 && j>-1 && j<8)
			if (position[i][j] == Checkers.EMPTY)
				return true;
		return false;
	} // isEmpty()


	/**
	  *	Metodo che controlla se la posizione della board passata contiene una pezzo bianco
	  *	@param position la board di gioco
	  *	@param i coordinata x della posizione da controllare
	  *	@param j coordinata y della posizione da controllare
	  *	@return true nel caso in cui contenga un pezzo bianco, false altrimenti
	  */
	private static boolean isWhite(int[][] position, int i, int j)
	{
		if (i>-1 && i<8 && j>-1 && j<8)
			if (color(position[i][j]) == Checkers.WHITE)
				return true;
		return false;
	} // isWhite()


	/**
	  *	Metodo che controlla se la posizione della board passata contiene una pezzo bianco
	  *	@param position la board di gioco
	  *	@param i coordinata x della posizione da controllare
	  *	@param j coordinata y della posizione da controllare
	  *	@return true nel caso in cui contenga un pezzo nero, false altrimenti
	  */
	private static boolean isBlack(int[][] position, int i, int j)
	{
		if (i>-1 && i<8 && j>-1 && j<8)
			if (color(position[i][j]) == Checkers.BLACK)
				return true;
		return false;
	} // isBlack()


	/**
	  *	Metodo che ritorna il colore di un pezzo
	  *	@param piece il pezzo
	  *	@return returns the color of a piece
	  */
	static int color(int piece)
	{
		switch (piece)
		{
		case Checkers.WHITE:
		case Checkers.WKING:
			return Checkers.WHITE;
		case Checkers.BLACK:
		case Checkers.BKING:
			return Checkers.BLACK;
		}
		return Checkers.EMPTY;
	}


	/**
	  *	Metodo che controlla se una posizione e' legale, ossia se si trova all'interno della board
	  *	@param i coordinata x della posizione da controllare
	  *	@param j coordinata y della posizione da controllare
	  *	@return ritorna true nel caso in cui la posizione sia regolare, false altrimenti
	  */
	// checkers that i and j are between 0 and 7 inclusive
	public static boolean inRange(int i, int j)
	{
		return (i>-1 && i<8 && j>-1 && j<8);
	}

	
	  
	Indice
	/**
	 * Esegue la mossa in input ed eventualmente "mangia"
	 * @param board e' la damiera con la configurazione corrente
	 * @param posR	la coordinata x di partenza
	 * @param posC  la coordinata y di partenza
	 * @param endR 	la coordinata x d'arrivo
	 * @param endC  la coordinata y d'arrivo
	 */
	static void eseguiMossa(int[][] board, int startR, int startC, int endR, int endC){
		if(Math.abs(startR-endR) == 2){ //sto mangiando?
			board[startR+(endR-startR)/2][startC+(endC-startC)/2]=Checkers.EMPTY; //mangio
		}
		board[endR][endC]=board[startR][startC]; //sposto la pedina nella nuova posizione
		board[startR][startC]=Checkers.EMPTY;    //libero la posizione di partenza
		// check for new king
		if ( board[endR][endC] == Checkers.WHITE && endR == 7)
			board[endR][endC] = Checkers.WKING;
		else if ( board[endR][endC] == Checkers.BLACK && endR == 0)
			board[endR][endC] = Checkers.BKING;

	}

	/**
	  *	Esegue la mossa di input ed eventualmente "mangia"
	  * 	@param board e' la damiera con la configurazione corrente
	  *	@param m  la mossa che deve essere eseguita
	  *	@param stampa flag che controlla se la mossa da eseguire deve essere stampata nell'area di visualizzazione delle mosse
	  *	@param scacchiera oggetto di tipo board
	  */
	static void eseguiMossa(int[][] board, Vector m, boolean stampa, Board scacchiera){
		int pedina;

		if(stampa){
			Checkers.mosseFatte.append("PLAYER: "+Move.color(board[m.get(0)[0]][m.get(0)[1]])+" ");
			for(int t=0; t 
	Indice
	/**
	 * Gestisce le catture multiple.
	 * @param board e' la damiera con la configurazione corrente
	 * @param posR	la coordinata x di partenza
	 * @param posC  la coordinata y di partenza
	 * @param player il giocatore attuale che sta giocando
	 * @param sequenzaCatture la stringa che indica il tipo di catture che sono state eseguite fino a questo momento
	 * @param nDamePrese mantiene il conto del numero di dame prese
	 * @param pezzo indica il pezzo che sta mangiando
	 * @param infoMossa indica la mossa di base eseguita fino a quel momento
	 * @param ms la struttura dati dove sono salvate le mosse
	 */
	static void cattureMultiple(int[][] board, int posR, int posC, int player, String sequenzaCatture, int nDamePrese, char pezzo, InfoMossa infoMossa, MoveScheduler ms){

		ms.add(infoMossa);				// inserisco la mossa base nella struttura


		InfoMossa tmpMossa;				// definizione di una InfoMossa ausiliaria

	// determino il verso del gioco in base a chi gioca: bianco o nero,
		int verso=0;
		if(player == Checkers.WHITE || player == Checkers.WKING)	// bianco incrementa le coordinate delle ascisse
			verso=1;
		else
			verso=-1;		// nero decrementa le coordinate delle ascisse

	// memorizzo la sequenza prima del branching
		String sequenzaTmp = sequenzaCatture;

	// determino quale sono le mosse legali del giocatore a partire dalla posizione posR, posC
		for(int k=-2;k<=2; k+=4){ //provo le 2 mosse legali per la pedina (e la dama)
			sequenzaCatture = sequenzaTmp;
			if(Move.inRange(posR+2*verso,posC+k) && board[posR+2*verso][posC+k] == Checkers.EMPTY) //sono nella scacchiera
				if(color(board[posR+verso][posC+k/2]) == Engine.opponent(player) &&
						(isKing(board[posR][posC]) || (!isKing(board[posR][posC]) && !isKing(board[posR+verso][posC+k/2])))){ //posso mangiare?
					// costruisco la sequenza del tipo di pedine mangiate
					if(board[posR+verso][posC+k/2]==Checkers.BLACK || board[posR+verso][posC+k/2]==Checkers.WHITE){
						sequenzaCatture+="p";
					}
					else{
						sequenzaCatture+="d";
						nDamePrese--;
					}

					int[][] tmpBoard=Engine.copy_board(board);		// eseguo una copia della board
					eseguiMossa(tmpBoard,posR,posC,posR+2*verso,posC+k);	// eseguo la mossa sulla copia
					tmpMossa=new InfoMossa(""+pezzo+nDamePrese+sequenzaCatture, infoMossa.getMossa());// eseguo una copia di infoMossa
					tmpMossa.addStep(posR+2*verso,posC+k);			// aggiongo il nuovo passo

					cattureMultiple(tmpBoard, posR+2*verso,posC+k, player, new String(sequenzaCatture), nDamePrese, pezzo,  tmpMossa, ms);	// richiamo la funzione ricorsiva di cattura multiple
				}
		}

	// nel caso in cui si stia analizzando una dama, devo considerare anche le possibili mosse che puo' eseguire tornando indietro
		if(board[posR][posC] == Checkers.BKING || board[posR][posC] == Checkers.WKING){ //se muove una dama
			for(int k=-2;k<=2; k+=4){ //provo le 2 mosse legali per la pedina (e la dama)
				sequenzaCatture = sequenzaTmp;
				if(Move.inRange(posR-2*verso,posC+k) && board[posR-2*verso][posC+k] == Checkers.EMPTY) //sono nella scacchiera
					if(color(board[posR-verso][posC+k/2]) == Engine.opponent(player)){ //posso mangiare?


						if(board[posR-verso][posC+k/2]==Checkers.BLACK || board[posR-verso][posC+k/2]==Checkers.WHITE){
							sequenzaCatture+="p";
						}
						else{
							sequenzaCatture+="d";
							nDamePrese--;
						}

						int[][] tmpBoard=Engine.copy_board(board);
						eseguiMossa(tmpBoard,posR,posC,posR-2*verso,posC+k);

						tmpMossa=new InfoMossa(""+pezzo+nDamePrese+sequenzaCatture, infoMossa.getMossa());
						tmpMossa.addStep(posR-2*verso,posC+k);

						cattureMultiple(tmpBoard, posR-2*verso,posC+k, player, new String(sequenzaCatture), nDamePrese, pezzo, tmpMossa, ms);
					}

			}//fine controllo altre 2 mosse legali dama
		}
	}// finito cattureMultiple()


	/**
	  *	Metodo che controlla se il pezzo che viene passato \`e una dama, ritornado true, false altrimenti.
	  *	@param pezzo indica il pezzo del quale si vuole sapere se \`e una dama o una pedina.
	  *	@return Verr\`a ritornato true nel caso in cui il pezzo sia una dama, false altrimenti.
	  */
	static boolean isKing(int pezzo){
		return (pezzo == Checkers.BKING || pezzo == Checkers.WKING);
	}

	
	 generates_moves 
Indice /** * given a board, generates all the possible moves depending on whose turn * @param board e' la damiera con la configurazione corrente; * @param player il giocatore attuale che sta giocando. * @return ritorna tutte e sole le mosse obbligate. */ static Vector> generate_moves(int[][] board, int player) { MoveScheduler ms=new MoveScheduler(); //serve per diversificare le liste di mosse possibili in funzione del numero //e tipo di catture (vedi regole) char pezzo; // indica il tipo di pezzo che deve eseguire la mossa int nDamePrese=99; // indica 99-il numero di dame da mangiare int verso=0; // per considerare il verso corretto del pezzo, dovuto al colore String sequenzaCatture; // la stringa ove salvare l'etichetta che specifica la mossa // si assegna, in base al colore del pezzo che deve muovere, il verso corretto. if(player == Checkers.WHITE || player == Checkers.WKING) verso=1; // se \`e bianco si muove verso valori crescenti delle y else verso=-1; // se \`e nero si muove verso valori decrescenti delle y // si scansiona l'intera damiera for(int i=0;i<8;i++) for(int j=0;j<8;j++){ if(color(board[i][j]) == player){ // si controlla se il pezzo selezionato e' del colore giusto // si assegna al pezzo che deve eseguire la mossa, il tipo if(board[i][j]==Checkers.BLACK || board[i][j]==Checkers.WHITE) pezzo='p'; else pezzo='d'; // si controllano, le due mosse in avanti che puo' eseguire lungo la diagonale for(int k=-2;k<=2; k+=4){ //provo le 2 direzioni legali per la pedina (e la dama) sequenzaCatture=new String(); nDamePrese=99; if(Move.inRange(i+2*verso,j+k) && board[i+2*verso][j+k] == Checkers.EMPTY){ //nel tentativo di mangiare, sono nella scacchiera if(color(board[i+verso][j+k/2]) == Engine.opponent(player) && (isKing(board[i][j]) || (!isKing(board[i][j]) && !isKing(board[i+verso][j+k/2])))){ //posso mangiare? if(board[i+verso][j+k/2]==Checkers.BLACK || board[i+verso][j+k/2]==Checkers.WHITE) sequenzaCatture+="p"; else{ sequenzaCatture+="d"; nDamePrese--; } int[][] tmpBoard=Engine.copy_board(board); eseguiMossa(tmpBoard,i,j,i+2*verso,j+k); // Vector vettoreMosse = new Vector(); // int[] inizioMossa={i,j}; // vettoreMosse.add(inizioMossa); cattureMultiple(tmpBoard, i+2*verso, j+k, player,sequenzaCatture,nDamePrese,pezzo,new InfoMossa(i, j, i+2*verso, j+k, ""+pezzo+nDamePrese+sequenzaCatture),ms); } else if(board[i+verso][j+k/2] == Checkers.EMPTY){ //mossa semplice ms.add(new InfoMossa(i,j,i+verso,j+k/2,"p99")); //inserisco "p99" perchè il passo è singolo e non devo fare catture cosi' la dama non ha priorita' } } else if(Move.inRange(i+verso,j+k/2) && board[i+verso][j+k/2] == Checkers.EMPTY){ //posso fare mossa semplice? ms.add(new InfoMossa(i,j,i+verso,j+k/2,"p99"));//inserisco "p99" perchè il passo è singolo e non devo fare catture cosi' la dama non ha priorita' } } //fine controllo mosse possibili per pedina e dama nel verso "verso l'avversario" if(board[i][j] == Checkers.BKING || board[i][j] == Checkers.WKING){ for(int k=-2;k<=2; k+=4){ //provo le altre 2 direzioni legali per la la dama sequenzaCatture=new String(); nDamePrese=99; if(Move.inRange(i-2*verso,j+k) && board[i-2*verso][j+k] == Checkers.EMPTY){ //nel tentativo di mangiare, sono nella scacchiera if(color(board[i-verso][j+k/2]) == Engine.opponent(player)){ //posso mangiare? if(board[i-verso][j+k/2]==Checkers.BLACK || board[i-verso][j+k/2]==Checkers.WHITE) sequenzaCatture+="p"; else{ sequenzaCatture+="d"; nDamePrese--; } int[][] tmpBoard=Engine.copy_board(board); eseguiMossa(tmpBoard,i,j,i-2*verso,j+k); // Vector vettoreMosse = new Vector(); // int[] inizioMossa={i,j}; // vettoreMosse.add(inizioMossa); cattureMultiple(tmpBoard, i-2*verso,j+k, player,sequenzaCatture,nDamePrese,pezzo,new InfoMossa(i,j,i-2*verso,j+k,""+pezzo+nDamePrese+sequenzaCatture),ms); } else if(board[i-verso][j+k/2] == Checkers.EMPTY){ //mossa semplice ms.add(new InfoMossa(i,j,i-verso,j+k/2,"p99"));//inserisco "p99" perchè il passo è singolo e non devo fare catture cosi' la dama non ha priorita' } } else if(Move.inRange(i-verso,j+k/2) && board[i-verso][j+k/2] == Checkers.EMPTY){ //posso fare mossa semplice? ms.add(new InfoMossa(i,j,i-verso,j+k/2,"p99"));//inserisco "p99" perchè il passo è singolo e non devo fare catture cosi' la dama non ha priorita' } } }//fine controllo altre 2 possibili mosse se muove una dama } } return ms.getMossePossibili(); }//generate_moves } // class Move