Move.java
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
|