/**
@author Sidibe Moise (msmoise@hotmail.fr)
informations sur les pions et dames
b: pion noir
B: dame noire
w: pion blanc,
W: dame blanche
v:case jouable vide,
k: pion blanc tu�
l: pion noir tu�
f:case fix�e, i.e non jouable
*/
//LLLLLLLLLLLLESSSSSSSSSSSSSSSS CCCCCCOMMMMMMMMMMMMMMENTAIRESSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
package com.appspot.mscheckers.core;
import java.util.ArrayList;
import com.appspot.mscheckers.iACore.CPlayer;
public class CheckerModel{
///CheckerBoard : la matrice du jeu
private char cBrd[][] = null;
///Les deux joueurs
private Player plyr1 = null, plyr2 = null;
private CPlayer cplyr = null;
///indique le tour des joueurs (w ou b)
private char turn;
///coordonn�es du pion en mouvement
private Position pos;
///coordonn�es de la case destination du pion en mouvement
private Position des;
///contiendra la table deplacement d'un joueur qui doit jouer ou qui est en train de joueur
private ArrayList<ArrayList<Position> > mTable;
///contiendra les positions des pions tu�s par le pion en mouvement
private ArrayList<Position> pawnsKil = new ArrayList<Position>(0);
///d�termine s'il y a plusieurs directions de prise pour une m�me destination
private boolean ram;
///contiendra le message � afficher s'il y a une ramification
private String notice;
///Pour joueur, le joueur indique une position de d�part et une position de fin qui peuvent �tre
///separ�es de plusieurs sauts(prise ou simplement). La m�thode move n'effectue qu'un seul saut � la fois,
///donc pour ex�cuter le d�placement demander par le joueur, la m�thode devra �tre appel�e pluisieurs fois de fa�on automatique.
///Cet attribut vaut "true" pendant ces appels automatiques
private boolean takeFinish;
///Quand un joueur a un deplacement (prise ou simple deplament), cet attribut vaut "true" tant que le joueur ne l'a pas effectuer
///Remarque: quant le joueur a une prise, il n'est pas obliger d'effectuer tous les sauts d'un seul coup. Il peut indiquer une position
///de d�part et fin qui ne couvrent pas tous les sauts qu'il a.
private boolean moveFinish;
private int mode;
///contiendra toujours les coordonn�es de depart du dernier pion deplac�. Les coordonn�es d'arriv�es �tant dans pos et des.
private Position old = null;
///initialise les joueurs
public CheckerModel(int mode, int level)
{
this.mode = mode;
if( this.mode == 0) { plyr1 = new Player("moise",22,'w'); cplyr = new CPlayer('b', level); }
else if(this.mode == 1) { plyr1 = new Player("moise",22,'w'); plyr2 = new Player("marc",22,'b'); }
}
///initialise les attributs pour un nouveau jeu
///@param cBrd : est la matrice du nouveau jeu
///@param turn : indique le joueur qui joue en 1er
public void setModel(char[][] cBrd, char turn, int mode, int level)
{
if( this.cBrd == null) this.cBrd = new char[10][10];
if( cBrd != null ) for(int j = 0; j < 10; j++) for(int i = 0; i < 10; i++ ) this.cBrd[j][i] = cBrd[j][i];
else
for(int j = 0; j < 10; j++)
{
int p = j%2;
for( int i = 1 - p; i < 10; i+=2 ) this.cBrd[j][i] = 'v';
for( int i = p; i < 10; i+=2 ) this.cBrd[j][i] = 'f';
}
this.turn = turn;
this.mTable = null;
this.pos = new Position(-1,-1);
this.des = new Position(-1,-1);
this.pawnsKil.clear();
this.ram = false;
this.takeFinish = false;
this.moveFinish = true;
this.mode = mode;
this.mode = mode;
if( mode == 0)
{
plyr1 = new Player("moise",22,'w');
cplyr = new CPlayer('b', level);
plyr2 = null;
}
else if( mode == 1 )
{
plyr1 = null;
cplyr = new CPlayer('b', level);
plyr2 = null;
}
else if(mode == 2)
{
plyr1 = new Player("moise",22,'w');
plyr2 = new Player("marc",22,'b');
cplyr = null;
}
}
///@return : une nouvelle matrice de jeu
public static char[][] checkerBoard()
{
char[][] cs = new char[10][10];
char p1 = 'f', p2 = 'b';
int i,j;
for(j = 0; j < 10; j++)
{
for(i = 0; i <10 ; i++)
{
cs[j][i] = p1;
p1=( p1 == p2 )?'f':p2;
}
p1=( p1 == p2 )?'f':p2;
if( j >= 3 && j <= 4) p2 = 'v';
else if( j >= 5 )p2 = 'w';
}
return cs;
}
///effectue un seul deplacement de position p1 vers la position p2 si bien s�r ce deplacement est possible
///@return un entier indiquant ce qui s'est pass� durant le deplacement
/// = 0 rien � faire (deplacement impossible)
/// = 1 deplacement effectu�, la vue devra donc se mettre � jour
/// = 2 une ramification rencontr�e le joueur devra donc indiquer le chemin � prendre
///Le dernier cas se produit lorsque le joueur indique une position de depart et fin assez eloign�es(en terme de saut), de sorte
///que lors des appels automatiques � la methode il y a plusieurs directions possibles pour arriver � la position fin
public int move(Position p1, Position p2)
{
///represente la valeur de retour
int vmove = 0;
int i,n;
ArrayList<Position> array;
//checkers.core.Main.afficher(this.cBrd);
///Si mTable est null => un nouveau d�placement, on construit donc le MoveTable(mTable) du joueur et
///apr�s on v�rifie si deplacement demander de p1 � p2 est possible
if( this.mTable == null || this.mTable.size() == 0)
{
this.takeFinish = false;
this.moveFinish = true;
///construction de la table de deplacement pour le joueur
if( this.turn == 'w' ) mTable = new ArrayList<ArrayList<Position> >(plyr1.play(cBrd)); else mTable = new ArrayList<ArrayList<Position> >(plyr2.play(cBrd));
//checkers.core.Main.afficher(this.mTable);
///On v�rifie si deplacement est possible gr�ce � la methode cutMTable(..)
if( this.cutMTable(new Position(p1),new Position(p2),false) == true)
{
///on initialise alors pos et des
this.pos = new Position(p1);
this.des = new Position(p2);
///sauvegarde des coordonn�es de depart
this.old = new Position(pos);
///on indique qu'il y a un d�placement en cours
this.moveFinish = false;
}
///Si le deplacment n'est possible on retourne la valeur 0 qui signifie qu'il n'y a rien faire
else return 0;
}
///sinon si mTable n'est pas vide => il y a un deplacement ou une prise qui n'est pas encore fini
else if( (this.takeFinish == false && this.moveFinish == true) || this.ram == true ) //une prise est en cours et le joueur ne l'a pas fini
{
///On v�rifie donc si le d�placement demand� est possible
if( this.cutMTable(new Position(p1),new Position(p2),this.ram) == true)
{
///On sauvegarde alors les positions de depart et fin
this.pos = new Position(p1);
this.des = new Position(p2);
///comme le deplacement est possible, on indique qu'il n y a pas de ramification au cas s'il y en avait
if( this.ram == true ) this.ram = false;
}
///deplacement impossible
else return 0; ///rien a faire
}
if( this.mTable != null && this.mTable.size() != 0)
{
n = mTable.size();
for( i = 1; i < n; i++ ) //recherche de ramifications
{
array = mTable.get(i);
if( Position.equal(mTable.get(0).get(1),array.get(1)) == false )
{
this.ram = true;
this.notice = new String("Il y a plusieurs directions possibles pour atteindre la destination indiqu�e,\nvous devez donc indiquer une direction � suivre pour continuer.");
//this.notice = new String("You must indicate a take direction! because many take direction are possible.");
return 2; //notice available
}
}
//ex�cution du deplacement
makeMove();
vmove = 1; //update available
}
return vmove;
}
public int move(char[][] cell)
{
if( mTable == null || mTable.size() == 0 )
{
this.takeFinish = false;
this.moveFinish = true;
ArrayList<Position> array;
mTable = new ArrayList<ArrayList<Position> >(0);
if( cell != null ) { cBrd = cell; turn = 'b';}
Position pos[] = cplyr.play(this.cBrd);;
if( pos == null ) {takeFinish = true; return 1;}
mTable.add(new ArrayList<Position>(0));
for(int i = 0; i< pos.length; i++ ) mTable.get(0).add(pos[i]);
if( mTable.size() != 0) //sinon fin de jeu
{
array = this.mTable.get(0);
//this.mTable.get(0).addAll(array);
this.pos = new Position(array.get(0));
this.des = new Position(array.get(array.size()-1));
this.old = new Position(this.pos);
}
}
if( mTable.size() != 0) makeMove();
else takeFinish = true;
return 0;
}
public char getTurn(){ return this.turn;}
public void setTurn(char turn) { this.turn = turn; }
public Position getDes() { return this.des; }
public Position getPos() { return this.old; }
public char[][] getModel()
{
int j,i;
char[][] res = new char[10][10];
for(j = 0; j < 10; j++) for( i = 0; i < 10; i++ ) res[j][i] = cBrd[j][i];
return res;
}
public String getNotice(){ return this.notice;}
public boolean moveFinish(){ return this.moveFinish;}
public boolean takeFinish(){ return this.takeFinish;}
public Position[] getPTool(){ if( cplyr == null ) return null; return cplyr.getPTool(); }
public float[] getVTool(){ if( cplyr == null ) return null; return cplyr.getVTool(); }
//renvoie les coordonn�es des pions morts � la vue
//et les supprime du model
public ArrayList<Position> getPawnsKil()
{
ArrayList<Position> res = new ArrayList<Position>(this.pawnsKil);
int i, n = this.pawnsKil.size();
Position p;
for( i = 0; i < n; i++ )
{
p = this.pawnsKil.get(i);
this.cBrd[p.getY()][p.getX()] = 'v';
}
this.pawnsKil.clear();
return res;
}
//simplifie la table de deplacement
private boolean cutMTable(Position p1, Position p2, boolean ramf)
{
boolean r = false;
int i,j,n = mTable.size();
int m = mTable.get(0).size();
boolean b = false;
char dame = (this.turn == 'w')?'W':'B';
ArrayList<Position> array;
for(i = 0; i < n; i++ )
if( Position.equal(mTable.get(i).get(0), p1) == true )
{
array = mTable.get(i);
for( j = 1; j < m; j++ )
{
if( Position.equal(array.get(j), p2) == true) { b = true; break; }
if(j == m-1 && cBrd[p1.getY()][p1.getX()] == dame )
if(p2.between(array.get(j),array.get(j-1))==true)
{
if(Position.pawnBetween(p2,array.get(j),this.cBrd)==null ) b = true;
else if( Position.pawnBetween(array.get(j),array.get(j-1),this.cBrd)== null ) b = true;
}
}
}
if( b == true )
{
r = true;
for(i = n-1; i >=0; i-- )
if( Position.equal(mTable.get(i).get(0), p1) == false ) mTable.remove(i);
else
{
array = mTable.get(i);
boolean c = false;
for( j = 1; j < m; j++ )
{
if( Position.equal(array.get(j), p2) == true) { c = true; break; }
if(j == m-1 && cBrd[p1.getY()][p1.getX()] == dame && p2.between(array.get(j),array.get(j-1))==true) c = true;
}
if( c == false ) mTable.remove(i);
}
}
if(ramf == true && b == true) //suppression des branches qui ont les memes composants mais dans l'ordre different(ramifications indentiques)
{
ArrayList<Position> array1;
n = mTable.size();
boolean t,t1;
int k;
for( i = n-1; i >= 1; i-- )
{
t = false;
array = mTable.get(i);
array1 = mTable.get(i-1);
for( j = 0; j < m; j++)
{
t1 = false;
for( k = 0; k <m; k++)
if(Position.equal(array.get(j),array1.get(k))==true) { t1 = true; break;}
if( t1 == false ) { t = false; break;}
}
if( t == false ) mTable.remove(i);
}
}
return r;
}
//Effectue le deplacement
private void makeMove()
{
ArrayList<Position> array = mTable.get(0);
int y,x;
if( mTable.get(0).size() == 2) { y = this.des.getY(); x = this.des.getX(); }
else { y = array.get(1).getY(); x = array.get(1).getX();}
cBrd[y][x] = cBrd[this.pos.getY()][this.pos.getX()];
cBrd[this.pos.getY()][this.pos.getX()] = 'v';
Position pp = Position.pawnBetween(new Position(y,x),this.pos, cBrd);
if( pp != null)
{
cBrd[pp.getY()][pp.getX()] = (this.turn=='w')?'l':'k';
pawnsKil.add(pp);
}
//deplacement sur la position suivante
this.pos = new Position(y,x);
//v�rification si fin de deplacement
if( Position.equal(this.pos, this.des)== true ) this.moveFinish = true; else this.moveFinish = false;
//suppression des positions jou�es
int n = mTable.size();
for(int i = 0; i < n; i++ ) mTable.get(i).remove(0);//
//si la prise est finie
if( mTable.get(0).size() == 1 )
{
mTable.clear();
if( this.turn == 'w' )
{
if(this.pos.getY() == 0 && cBrd[this.pos.getY()][this.pos.getX()] == 'w') cBrd[this.pos.getY()][this.pos.getX()] ='W';
this.turn = 'b';
}
else
{
if(this.pos.getY() == 9 && cBrd[this.pos.getY()][this.pos.getX()] == 'b') cBrd[this.pos.getY()][this.pos.getX()] ='B';
this.turn = 'w';
}
this.takeFinish = true;
}
}
/*public static void main(String[] args){
CheckersModel dm = new CheckersModel();
String t="";
for(int j = 0; j < 10; j++)
{
for(int i = 0; i <10 ; i++)
{
t = t + (new String(dm.cs[j][i]+" "));
}
t = t +"\n";
}
System.out.println(t);
}*/
}