Accueil > > > PROBLEME DU CAVALIER [BACKTRACKING]
PROBLEME DU CAVALIER [BACKTRACKING]
Information sur la source
Description
résolution du problème du cavalier : trouver une parcours du cavalier sur un jeu d'échec dans lequel il passe par toutes les cases une et une seule fois. L'algorithme consite à énumerer toutes les solutions, enfin presque, on ne visite pas des branches entieres de solutions quand on sait a l'avance qu'il n'y aura aucune solution. Des que l'on sait que l'on va aboutir sur une impasse, on retourne en arrière, on rebrousse chemin, et on passe a une autre solution, c'est le principe du "backtracking" L'algorithme peut etre améliorer avec quelques optimisations, mais je préfére donner l'algorithme brute, directment lié au principe du "backtracking".
Source
- //-------------------------------------------------
- // INCLUDES
- //-------------------------------------------------
- #ifndef _UTIL_H_
- #include "util.h"
- #endif // _UTIL_H_
-
- #ifndef _MATH_H_
- #include "math.h"
- #endif // _MATH_H_
-
- #ifndef _DATA_H_
- #include "data.h"
- #endif // _DATA_H_
-
- #ifndef _WINUTIL_H_
- #include "winutil.h"
- #endif // _WINUTIL_H_
-
- //-------------------------------------------------
- #define SIZE_CHESSBOARD 8
-
- //-------------------------------------------------
- // DATA_WINDOW
- //-------------------------------------------------
- typedef struct tagDATA_WINDOW
- {
- // handle sur la fenetre
- HWND hwnd;
- // est-ce-que l'algorithme est fini ou non ? (vraiment utile pour un echiquier de taille < 8*8 ...)
- BOOL bEndOfAlgo;
- // le damier, ou l'echiquier, une simple matrice d'entier
- // 0 -> case vide
- // i -> le cheval etait present au i-eme coup
- U32 chessboard[SIZE_CHESSBOARD][SIZE_CHESSBOARD];
- // quelques informations
- int nbSol,nbTest;
- // pile des etapes ("STEP")
- STACK stack;
- }DATA_WINDOW,*P_DATA_WINDOW,**PP_DATA_WINDOW;
-
- //-------------------------------------------------
- // permet de representer un couple d'entier
- // (une coordonnee dans l'echiquier par exemple)
- // qui pourront etre en fait dans une liste de
- // couple
- typedef struct tagPOSITION
- {
- LINK_DBL_LIST link; // le lien de la liste
- int i,j; // les coordonnees
- }POSITION,*P_POSITION,**PP_POSITION;
-
- //-------------------------------------------------
- // represente une etape
- // le programme possede couramment une pile
- // d'etape, une etape represente la position
- // du cavalier a la <iStep>-eme etape sur la
- // case de coordonnee (i,j)
- // on construit a chaque fois la liste des cases
- // que le cavalier pourra explorer a partir
- // de ca position-ci et bien-sur en fonction
- // de la configuration de l'echiquier courant
- // (s'il est deja passe par un case par exemple...)
- typedef struct tagSTEP
- {
- DBL_LIST lstPos; // liste des cases a visiter
- int iStep; // numero de l'etape
- int i,j; // coordonnees
- LINK_STACK lnkStack; // lien de la pile
- }STEP,*P_STEP,**PP_STEP;
-
- //-------------------------------------------------
- // fonction tres stupide, mais tres utile !
- // elle permet de rajouter un case a la liste des
- // cases q'un cavalier peut aller (dans un etape)
- // pour cela on lui fournit l'echiquier, la liste
- // et les coordonnees (i,j)
- // la valeur ajoutee de cette fonction, c'est que
- // c'est elle qui verifie que (i,j) soit bien dans
- // l'echiquier (par exemple on pourrait sortir
- // du plateau) et que la case est bien vide
- void addPos(U32 chessboard[SIZE_CHESSBOARD][SIZE_CHESSBOARD],P_DBL_LIST dblList,int i,int j)
- {
- if(
- // teste de validite de la plage des (i,j)
- i >= 0 && i < SIZE_CHESSBOARD && j >=0 && j< SIZE_CHESSBOARD
- &&
- // teste que la case est bien vide
- 0 == chessboard[i][j]
- )
- {
- // tout est OK, on ajoute :
- P_POSITION pos;
- pos = Malloc(POSITION,1); // creation de la structure par allocation memoire
- pos->i = i; // initialisation des champs
- pos->j = j;
- InsertFirstLinkDblList(dblList,&pos->link); // on insert dans la liste ce nouvel element
- }
- } // addPos()
-
- //-------------------------------------------------
- // la creation d'une etape consiste
- // a placer le cavalier a la position
- // et a construire la liste des cases accessibles
- P_STEP createStep(P_DATA_WINDOW data,int i,int j,int iStep)
- {
- P_STEP step;
-
- // initialisation
- step = Malloc(STEP,1); // creation de l'etape par allocation memoire
- step->iStep = iStep; // le numero de l'etape
- step->i = i; // coordonnees du cavalier
- step->j = j;
- PushLinkStack(&data->stack,&step->lnkStack); // ajout de l'etape dans la pile des etapes
- data->chessboard[i][j] = iStep; // placement du cavalier sur l'echiquier
-
- InitDblList(&step->lstPos); // initialisation de la liste des positions possibles
- // il y a 8 positions accessibles au maximum par le cavalier
- // le cavalier peut se deplacer en L :
- // .......
- // ..8.1..
- // .7...2.
- // ...C...
- // .6...3.
- // ..5.4..
- // .......
- addPos(data->chessboard,&step->lstPos,i + 1,j + 2); // #1
- addPos(data->chessboard,&step->lstPos,i + 2,j + 1); // #2
- addPos(data->chessboard,&step->lstPos,i + 2,j - 1); // #3
- addPos(data->chessboard,&step->lstPos,i + 1,j - 2); // #4
- addPos(data->chessboard,&step->lstPos,i - 1,j - 2); // #5
- addPos(data->chessboard,&step->lstPos,i - 2,j - 1); // #6
- addPos(data->chessboard,&step->lstPos,i - 2,j + 1); // #7
- addPos(data->chessboard,&step->lstPos,i - 1,j + 2); // #8
- return step;
- } // createStep()
-
- //-------------------------------------------------
- // execution d'une etape de l'algorithme
- // le principe est simple :
- // on prend l'etape courante
- // si la liste des cases possibles est vide
- // alors on remonte, i.e. on a deja visite
- // toutes les possibilites avec ce cavalier sur
- // cette position, donc on passe a une autre position
- // de ce cavalier.
- // sinon la liste n'est pas vide, alors on prend
- // la premiere case de la liste, et on deplace le
- // cavalier sur cette case, et on appelle recursivement
- // l'algorithme sur cette nouvelle case
- void algo(P_DATA_WINDOW data)
- {
- data->bEndOfAlgo = (0 == data->stack.nElem);
-
- if(!data->bEndOfAlgo)
- {
- P_LINK_STACK curLinkStack;
- P_STEP curStep;
-
- data->nbTest ++; // un passage de plus !
-
- // on recupere l'etape courante
- curLinkStack = FirstLinkStack(&data->stack);
- curStep = FROM_TO(STEP,lnkStack,curLinkStack);
- if(curStep->lstPos.nElem > 0) // on teste la position suivante
- {
- P_LINK_DBL_LIST curLinkDblList;
- P_POSITION curPos;
-
- // on recupere le premiere element de la liste
- curLinkDblList = FirstLinkDblList(&curStep->lstPos);
- curPos = FROM_TO(POSITION,link,curLinkDblList);
- // on appelle recursivement l'algorithme, i.e.
- // on ajoute un etape sur cette position, en
- // incrementant le numero de l'etape
- createStep(data,curPos->i,curPos->j,curStep->iStep + 1);
-
- // ici on teste si on trouve (enfin) un solution
- // le teste est simple, si le numero de l'etape
- // est exactement le nombre de case de l'echiquier alors ...
- if(1 + curStep->iStep == SIZE_CHESSBOARD*SIZE_CHESSBOARD)
- {
- P_FILE_UTIL file;
- char name[256];
- int i,j;
-
- data->nbSol ++; // un solution de plus !!! BINGO !!!
- _snprintf(name,COUNT(name),"res\\solution[%d][%d].txt",SIZE_CHESSBOARD,data->nbSol);
- file = FileOpen(name,"wt"); // on ouvre le fichier
- // on ecrit la solution dans le fichier
- for(i=0;i<SIZE_CHESSBOARD;i++)
- {
- for(j=0;j<SIZE_CHESSBOARD;j++)
- {
- FilePrint((file," %2d",data->chessboard[i][j]));
- }
- FilePrint((file,"\n")); // saut de ligne
- }
- FileClose(file); // fermeture du fichier
- }
-
- // on enleve la case de la liste, car on vient de la traiter
- RemoveLinkDblList(&curStep->lstPos,curLinkDblList);
- Free(curPos); // liberation de l'allocation memoire
- }
- else // on remonte car la liste est vide
- {
- CloseDblList(&curStep->lstPos); // on ferme la liste (vide)
- PopLinkStack(&data->stack); // on enleve l'etape
- data->chessboard[curStep->i][curStep->j] = 0; // on efface la position du cavalier
- Free(curStep); // on libere l'allocation memoire
- }
- }
- } // algo()
-
- //-------------------------------------------------
- // WND_PROC
- //-------------------------------------------------
- int WndProc(P_MY_WINDOW myWindow,HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
- {
- P_DATA_WINDOW data;
-
- data = (P_DATA_WINDOW)myWindow->userData;
-
- switch(iMsg)
- {
- // creation de la fenetre
- case WM_CREATE:
- {
-
- // parametres de la fenetre
- myWindow->bResizedWindow = TRUE;
- myWindow->bUseBackBuffer = FALSE;
- myWindow->colorBackGround = RGB_WHITE;
-
- // initialisations de la fenetre
- data->hwnd = hwnd;
- data->bEndOfAlgo = FALSE;
- data->nbSol = 0;
- data->nbTest = 0;
-
- // initialisation de l'algo.
- {
- int i,j;
- for(i=0;i<SIZE_CHESSBOARD;i++)
- {
- for(j=0;j<SIZE_CHESSBOARD;j++)
- {
- // on vide l'echiquier
- data->chessboard[i][j] = 0;
- }
- }
- }
- InitStack(&data->stack);
- createStep(data,0,0,1); // on mets le cheval dans un coin (par exemple)
-
- // initialisation du timer
- SetTimer(hwnd,314,250,NULL);
-
- break;
- }
- case WM_TIMER:
- {
- switch(wParam)
- {
- case 314:
- {
- DWORD t0;
- t0 = GetTickCount();
- while(GetTickCount() < 250 + t0) // on travaille pendant 1/4 de secondes
- {
- algo(data);
- }
- myRepaintWindow(hwnd); // on redessine la fenetre
- break;
- }
- }
- break;
- }
- // les touches
- case WM_KEYDOWN:
- {
- switch((int)wParam)
- {
- /*
- // une etape, manuellement
- case 'A':
- algo(data);
- myRepaintWindow(hwnd);
- break;
- */
- default:
- break;
- }
-
- break;
- }
- // le commandes
- case WM_COMMAND:
- {
- switch(LOWORD(wParam))
- {
- }
- break;
- }
- // on dessine
- case WM_PAINT:
- {
- P_MY_HDC hdc;
- int cx,cy;
-
- cx = myWindow->cx;
- cy = myWindow->cy;
- hdc = (P_MY_HDC)wParam;
-
- SetBkMode(GetHdc(hdc),TRANSPARENT);
-
- if(data->bEndOfAlgo)
- {
- SetTextColor(GetHdc(hdc),RGB_RED);
- myPushFont(hdc,10,20,800,"Courier New");
- myTextOut(hdc,cx/2,0.5,2*cy/5,0.5,"Fin de l'algorithme");
- myTextOut(hdc,cx/2,0.5,3*cy/5,0.5,"%d solutions trouvées",data->nbSol);
- myPopFont(hdc);
- }
- //else
- {
- int cxFont,cyFont,dx,dy;
- int k,i,j;
-
-
- dx = 50;
- dy = 50;
- cxFont = 15;
- cyFont = 30;
-
- myPushFont(hdc,cxFont,cyFont,800,"Courier New");
- // la grille
- myPushPen(hdc,PS_SOLID,0,RGB_LIGHTGRAY);
- for(k=0;k<=SIZE_CHESSBOARD;k++)
- {
- myLine(hdc,k*dx,0,k*dx,SIZE_CHESSBOARD*dy,FALSE);
- myLine(hdc,0,k*dy,SIZE_CHESSBOARD*dx,k*dy,FALSE);
- }
- myPopPen(hdc);
- // les numéros
- SetTextColor(GetHdc(hdc),RGB_BLACK);
- for(i=0;i<SIZE_CHESSBOARD;i++)
- {
- for(j=0;j<SIZE_CHESSBOARD;j++)
- {
- U32 nb;
- nb = data->chessboard[i][j];
- if(0 != nb)
- {
- myTextOut(hdc,(2*i+1)*dx/2,0.5,(2*j+1)*dy/2,0.5,"%d",nb);
- }
- }
- }
- // les informations
- SetTextColor(GetHdc(hdc),RGB_BLACK);
- myTextOut(hdc,0,0.,cy-2*cyFont,1.,"nombre d'essais : %d" ,data->nbTest);
- myTextOut(hdc,0,0.,cy-1*cyFont,1.,"profondeur : %d" ,data->stack.nElem);
- myTextOut(hdc,0,0.,cy-0*cyFont,1.,"%d solutions trouvées" ,data->nbSol);
-
- myPopFont(hdc);
- }
-
- break;
- }
- // destruction de la fenetre
- case WM_DESTROY:
- {
- // on vide la pile
- while(data->stack.nElem > 0)
- {
- P_LINK_STACK linkStack;
- P_STEP step;
- linkStack = PopLinkStack(&data->stack); // on enleve l'element de la liste
- step = FROM_TO(STEP,lnkStack,linkStack); // on recupere <STEP> a partir de <LINK_STACK>
- // on vide la liste de chaque etape de la pile
- while(step->lstPos.nElem > 0)
- {
- P_LINK_DBL_LIST linkDblList;
- P_POSITION pos;
- linkDblList = FirstLinkDblList(&step->lstPos); // on recupere un element de la liste (le premier)
- RemoveLinkDblList(&step->lstPos,linkDblList); // on supprime l'element de la liste
- pos = FROM_TO(POSITION,link,linkDblList); // on recupere <POSITION> a partir de <LINK_DBL_LIST>
- Free(pos); // on libere l'allocation memoire
- }
- CloseDblList(&step->lstPos); // on ferme la liste
- Free(step); // on libere l'allocation memoire
- }
- CloseStack(&data->stack); // on ferme la pile
- PostQuitMessage(0); // see you later ...
- break;
- }
- }
-
-
- return 0;
- } // WndProc()
-
-
- //-------------------------------------------------
- // WIN_MAIN
- //-------------------------------------------------
- int WINAPI WinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpszCmdLine,
- int iCmdShow
- )
- {
- WNDCLASSEX wc;
- RECT rc;
- P_MY_WINDOW myWindow;
- HWND hwnd;
- P_DATA_WINDOW data;
- MSG msg;
-
-
- // ouverture des librairies
- InitLibUtil();
- InitLibWinutil(hInstance);
-
- // initialisation de la classe
- mySetDefaultWindowClass(&wc,hInstance);
- wc.lpszClassName = "JCD_PbCavalier";
- mySetRectWH(&rc,0,0,500,500);
-
- // creation de la fenetre
- myWindow = myCreateWindow(&wc,
- " Problème du cavalier",
- WS_OVERLAPPEDWINDOW,
- &rc,
- TRUE,
- TRUE,
- NULL,
- NULL,
- sizeof(DATA_WINDOW),
- (void*)lpszCmdLine,
- WndProc
- );
-
- data = (P_DATA_WINDOW)myWindow->userData;
- hwnd = myWindow->hwnd;
-
- ShowWindow(hwnd,iCmdShow);
- UpdateWindow(hwnd);
- // boucle de messages
- while(GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- // fermeture des librairies
- CloseLibUtil();
- CloseLibWinutil();
-
- // tout va bien !
- // see you later ...
- return 0 ;
- } // WinMain()
//-------------------------------------------------
// INCLUDES
//-------------------------------------------------
#ifndef _UTIL_H_
#include "util.h"
#endif // _UTIL_H_
#ifndef _MATH_H_
#include "math.h"
#endif // _MATH_H_
#ifndef _DATA_H_
#include "data.h"
#endif // _DATA_H_
#ifndef _WINUTIL_H_
#include "winutil.h"
#endif // _WINUTIL_H_
//-------------------------------------------------
#define SIZE_CHESSBOARD 8
//-------------------------------------------------
// DATA_WINDOW
//-------------------------------------------------
typedef struct tagDATA_WINDOW
{
// handle sur la fenetre
HWND hwnd;
// est-ce-que l'algorithme est fini ou non ? (vraiment utile pour un echiquier de taille < 8*8 ...)
BOOL bEndOfAlgo;
// le damier, ou l'echiquier, une simple matrice d'entier
// 0 -> case vide
// i -> le cheval etait present au i-eme coup
U32 chessboard[SIZE_CHESSBOARD][SIZE_CHESSBOARD];
// quelques informations
int nbSol,nbTest;
// pile des etapes ("STEP")
STACK stack;
}DATA_WINDOW,*P_DATA_WINDOW,**PP_DATA_WINDOW;
//-------------------------------------------------
// permet de representer un couple d'entier
// (une coordonnee dans l'echiquier par exemple)
// qui pourront etre en fait dans une liste de
// couple
typedef struct tagPOSITION
{
LINK_DBL_LIST link; // le lien de la liste
int i,j; // les coordonnees
}POSITION,*P_POSITION,**PP_POSITION;
//-------------------------------------------------
// represente une etape
// le programme possede couramment une pile
// d'etape, une etape represente la position
// du cavalier a la <iStep>-eme etape sur la
// case de coordonnee (i,j)
// on construit a chaque fois la liste des cases
// que le cavalier pourra explorer a partir
// de ca position-ci et bien-sur en fonction
// de la configuration de l'echiquier courant
// (s'il est deja passe par un case par exemple...)
typedef struct tagSTEP
{
DBL_LIST lstPos; // liste des cases a visiter
int iStep; // numero de l'etape
int i,j; // coordonnees
LINK_STACK lnkStack; // lien de la pile
}STEP,*P_STEP,**PP_STEP;
//-------------------------------------------------
// fonction tres stupide, mais tres utile !
// elle permet de rajouter un case a la liste des
// cases q'un cavalier peut aller (dans un etape)
// pour cela on lui fournit l'echiquier, la liste
// et les coordonnees (i,j)
// la valeur ajoutee de cette fonction, c'est que
// c'est elle qui verifie que (i,j) soit bien dans
// l'echiquier (par exemple on pourrait sortir
// du plateau) et que la case est bien vide
void addPos(U32 chessboard[SIZE_CHESSBOARD][SIZE_CHESSBOARD],P_DBL_LIST dblList,int i,int j)
{
if(
// teste de validite de la plage des (i,j)
i >= 0 && i < SIZE_CHESSBOARD && j >=0 && j< SIZE_CHESSBOARD
&&
// teste que la case est bien vide
0 == chessboard[i][j]
)
{
// tout est OK, on ajoute :
P_POSITION pos;
pos = Malloc(POSITION,1); // creation de la structure par allocation memoire
pos->i = i; // initialisation des champs
pos->j = j;
InsertFirstLinkDblList(dblList,&pos->link); // on insert dans la liste ce nouvel element
}
} // addPos()
//-------------------------------------------------
// la creation d'une etape consiste
// a placer le cavalier a la position
// et a construire la liste des cases accessibles
P_STEP createStep(P_DATA_WINDOW data,int i,int j,int iStep)
{
P_STEP step;
// initialisation
step = Malloc(STEP,1); // creation de l'etape par allocation memoire
step->iStep = iStep; // le numero de l'etape
step->i = i; // coordonnees du cavalier
step->j = j;
PushLinkStack(&data->stack,&step->lnkStack); // ajout de l'etape dans la pile des etapes
data->chessboard[i][j] = iStep; // placement du cavalier sur l'echiquier
InitDblList(&step->lstPos); // initialisation de la liste des positions possibles
// il y a 8 positions accessibles au maximum par le cavalier
// le cavalier peut se deplacer en L :
// .......
// ..8.1..
// .7...2.
// ...C...
// .6...3.
// ..5.4..
// .......
addPos(data->chessboard,&step->lstPos,i + 1,j + 2); // #1
addPos(data->chessboard,&step->lstPos,i + 2,j + 1); // #2
addPos(data->chessboard,&step->lstPos,i + 2,j - 1); // #3
addPos(data->chessboard,&step->lstPos,i + 1,j - 2); // #4
addPos(data->chessboard,&step->lstPos,i - 1,j - 2); // #5
addPos(data->chessboard,&step->lstPos,i - 2,j - 1); // #6
addPos(data->chessboard,&step->lstPos,i - 2,j + 1); // #7
addPos(data->chessboard,&step->lstPos,i - 1,j + 2); // #8
return step;
} // createStep()
//-------------------------------------------------
// execution d'une etape de l'algorithme
// le principe est simple :
// on prend l'etape courante
// si la liste des cases possibles est vide
// alors on remonte, i.e. on a deja visite
// toutes les possibilites avec ce cavalier sur
// cette position, donc on passe a une autre position
// de ce cavalier.
// sinon la liste n'est pas vide, alors on prend
// la premiere case de la liste, et on deplace le
// cavalier sur cette case, et on appelle recursivement
// l'algorithme sur cette nouvelle case
void algo(P_DATA_WINDOW data)
{
data->bEndOfAlgo = (0 == data->stack.nElem);
if(!data->bEndOfAlgo)
{
P_LINK_STACK curLinkStack;
P_STEP curStep;
data->nbTest ++; // un passage de plus !
// on recupere l'etape courante
curLinkStack = FirstLinkStack(&data->stack);
curStep = FROM_TO(STEP,lnkStack,curLinkStack);
if(curStep->lstPos.nElem > 0) // on teste la position suivante
{
P_LINK_DBL_LIST curLinkDblList;
P_POSITION curPos;
// on recupere le premiere element de la liste
curLinkDblList = FirstLinkDblList(&curStep->lstPos);
curPos = FROM_TO(POSITION,link,curLinkDblList);
// on appelle recursivement l'algorithme, i.e.
// on ajoute un etape sur cette position, en
// incrementant le numero de l'etape
createStep(data,curPos->i,curPos->j,curStep->iStep + 1);
// ici on teste si on trouve (enfin) un solution
// le teste est simple, si le numero de l'etape
// est exactement le nombre de case de l'echiquier alors ...
if(1 + curStep->iStep == SIZE_CHESSBOARD*SIZE_CHESSBOARD)
{
P_FILE_UTIL file;
char name[256];
int i,j;
data->nbSol ++; // un solution de plus !!! BINGO !!!
_snprintf(name,COUNT(name),"res\\solution[%d][%d].txt",SIZE_CHESSBOARD,data->nbSol);
file = FileOpen(name,"wt"); // on ouvre le fichier
// on ecrit la solution dans le fichier
for(i=0;i<SIZE_CHESSBOARD;i++)
{
for(j=0;j<SIZE_CHESSBOARD;j++)
{
FilePrint((file," %2d",data->chessboard[i][j]));
}
FilePrint((file,"\n")); // saut de ligne
}
FileClose(file); // fermeture du fichier
}
// on enleve la case de la liste, car on vient de la traiter
RemoveLinkDblList(&curStep->lstPos,curLinkDblList);
Free(curPos); // liberation de l'allocation memoire
}
else // on remonte car la liste est vide
{
CloseDblList(&curStep->lstPos); // on ferme la liste (vide)
PopLinkStack(&data->stack); // on enleve l'etape
data->chessboard[curStep->i][curStep->j] = 0; // on efface la position du cavalier
Free(curStep); // on libere l'allocation memoire
}
}
} // algo()
//-------------------------------------------------
// WND_PROC
//-------------------------------------------------
int WndProc(P_MY_WINDOW myWindow,HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
P_DATA_WINDOW data;
data = (P_DATA_WINDOW)myWindow->userData;
switch(iMsg)
{
// creation de la fenetre
case WM_CREATE:
{
// parametres de la fenetre
myWindow->bResizedWindow = TRUE;
myWindow->bUseBackBuffer = FALSE;
myWindow->colorBackGround = RGB_WHITE;
// initialisations de la fenetre
data->hwnd = hwnd;
data->bEndOfAlgo = FALSE;
data->nbSol = 0;
data->nbTest = 0;
// initialisation de l'algo.
{
int i,j;
for(i=0;i<SIZE_CHESSBOARD;i++)
{
for(j=0;j<SIZE_CHESSBOARD;j++)
{
// on vide l'echiquier
data->chessboard[i][j] = 0;
}
}
}
InitStack(&data->stack);
createStep(data,0,0,1); // on mets le cheval dans un coin (par exemple)
// initialisation du timer
SetTimer(hwnd,314,250,NULL);
break;
}
case WM_TIMER:
{
switch(wParam)
{
case 314:
{
DWORD t0;
t0 = GetTickCount();
while(GetTickCount() < 250 + t0) // on travaille pendant 1/4 de secondes
{
algo(data);
}
myRepaintWindow(hwnd); // on redessine la fenetre
break;
}
}
break;
}
// les touches
case WM_KEYDOWN:
{
switch((int)wParam)
{
/*
// une etape, manuellement
case 'A':
algo(data);
myRepaintWindow(hwnd);
break;
*/
default:
break;
}
break;
}
// le commandes
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
}
break;
}
// on dessine
case WM_PAINT:
{
P_MY_HDC hdc;
int cx,cy;
cx = myWindow->cx;
cy = myWindow->cy;
hdc = (P_MY_HDC)wParam;
SetBkMode(GetHdc(hdc),TRANSPARENT);
if(data->bEndOfAlgo)
{
SetTextColor(GetHdc(hdc),RGB_RED);
myPushFont(hdc,10,20,800,"Courier New");
myTextOut(hdc,cx/2,0.5,2*cy/5,0.5,"Fin de l'algorithme");
myTextOut(hdc,cx/2,0.5,3*cy/5,0.5,"%d solutions trouvées",data->nbSol);
myPopFont(hdc);
}
//else
{
int cxFont,cyFont,dx,dy;
int k,i,j;
dx = 50;
dy = 50;
cxFont = 15;
cyFont = 30;
myPushFont(hdc,cxFont,cyFont,800,"Courier New");
// la grille
myPushPen(hdc,PS_SOLID,0,RGB_LIGHTGRAY);
for(k=0;k<=SIZE_CHESSBOARD;k++)
{
myLine(hdc,k*dx,0,k*dx,SIZE_CHESSBOARD*dy,FALSE);
myLine(hdc,0,k*dy,SIZE_CHESSBOARD*dx,k*dy,FALSE);
}
myPopPen(hdc);
// les numéros
SetTextColor(GetHdc(hdc),RGB_BLACK);
for(i=0;i<SIZE_CHESSBOARD;i++)
{
for(j=0;j<SIZE_CHESSBOARD;j++)
{
U32 nb;
nb = data->chessboard[i][j];
if(0 != nb)
{
myTextOut(hdc,(2*i+1)*dx/2,0.5,(2*j+1)*dy/2,0.5,"%d",nb);
}
}
}
// les informations
SetTextColor(GetHdc(hdc),RGB_BLACK);
myTextOut(hdc,0,0.,cy-2*cyFont,1.,"nombre d'essais : %d" ,data->nbTest);
myTextOut(hdc,0,0.,cy-1*cyFont,1.,"profondeur : %d" ,data->stack.nElem);
myTextOut(hdc,0,0.,cy-0*cyFont,1.,"%d solutions trouvées" ,data->nbSol);
myPopFont(hdc);
}
break;
}
// destruction de la fenetre
case WM_DESTROY:
{
// on vide la pile
while(data->stack.nElem > 0)
{
P_LINK_STACK linkStack;
P_STEP step;
linkStack = PopLinkStack(&data->stack); // on enleve l'element de la liste
step = FROM_TO(STEP,lnkStack,linkStack); // on recupere <STEP> a partir de <LINK_STACK>
// on vide la liste de chaque etape de la pile
while(step->lstPos.nElem > 0)
{
P_LINK_DBL_LIST linkDblList;
P_POSITION pos;
linkDblList = FirstLinkDblList(&step->lstPos); // on recupere un element de la liste (le premier)
RemoveLinkDblList(&step->lstPos,linkDblList); // on supprime l'element de la liste
pos = FROM_TO(POSITION,link,linkDblList); // on recupere <POSITION> a partir de <LINK_DBL_LIST>
Free(pos); // on libere l'allocation memoire
}
CloseDblList(&step->lstPos); // on ferme la liste
Free(step); // on libere l'allocation memoire
}
CloseStack(&data->stack); // on ferme la pile
PostQuitMessage(0); // see you later ...
break;
}
}
return 0;
} // WndProc()
//-------------------------------------------------
// WIN_MAIN
//-------------------------------------------------
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int iCmdShow
)
{
WNDCLASSEX wc;
RECT rc;
P_MY_WINDOW myWindow;
HWND hwnd;
P_DATA_WINDOW data;
MSG msg;
// ouverture des librairies
InitLibUtil();
InitLibWinutil(hInstance);
// initialisation de la classe
mySetDefaultWindowClass(&wc,hInstance);
wc.lpszClassName = "JCD_PbCavalier";
mySetRectWH(&rc,0,0,500,500);
// creation de la fenetre
myWindow = myCreateWindow(&wc,
" Problème du cavalier",
WS_OVERLAPPEDWINDOW,
&rc,
TRUE,
TRUE,
NULL,
NULL,
sizeof(DATA_WINDOW),
(void*)lpszCmdLine,
WndProc
);
data = (P_DATA_WINDOW)myWindow->userData;
hwnd = myWindow->hwnd;
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
// boucle de messages
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// fermeture des librairies
CloseLibUtil();
CloseLibWinutil();
// tout va bien !
// see you later ...
return 0 ;
} // WinMain()
Sources du même auteur
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
cavalier d euler [ par didouestia ]
kikou les gens voila j ai un petit projet a faire en c++, le cavalier d euler c est a dire qu'un cavalier doit parcourir tout les cases de l'echequier
Projet C Jeu d'echec [ par Hugo Dam ]
Bonsoir, Je code actuellement un jeu d'echec. Celui ci compile bien mais lors de l'execution il m'affiche erreur de segmentation des lors que je fais
comment programmer un echec ou un echec mat.. [ par moha125 ]
salut les amis javascript:Insert_Emoticon('/imgs2/smile_big.gif'); j'ai decidé de faire un jeu d'echec j'ai tout fait mais il me reste de faire echec
Echec lors de la compilation du code source de TortoiseSVN [ par Subversion ]
Bonjour,J'ai téléchargé tout le code source de TortoiseSVN. (http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/)Ainsi, j'obtiens exactement la même
probleme 8 dames fonction sans prise [ par mehdislim59 ]
bonjour je suis nouvo et je debute en programmation et je voudrais savoir comme resoudre mon petit probleme sur les 8 reines je suis mon enoncé qui me
problème avec le backtracking (sudoku) [ par anoubest ]
Bonjour tt le monde, g a écrire un code pour résoudre un sudoku. on suppose ke la grille en entrée est un tableau de 9*9 chiffres entre 0 et 9 (0 pr l
algorithme jeux d'echec [ par manou06 ]
bonsoir tout le monde, je cherche un bon algorithme pour faire bouger les pièces d'un jeu d'échec çà sera un mini projet pour la semaine prochaine et
Enlever mode sans echec ou faire qu'une aplication ce lance en mode sans echec. [ par jerem3000 ]
Bonjour, Je suis en train de développer une application pour empêcher d’autre personne d’utiliser mon pc et il faudrait que je puisse dés
DIRECTX et interface [ par ELKI ]
je suis en train de concevoir un jeu d'echec et j'aurai voulu savoir comment je pouurai faire pour associer des pièce d'un jeu d'echec avec mon interf
|
Derniers Blogs
SESSION SILVERLIGHT 5 3D : SLIDES ET DEMOSSESSION SILVERLIGHT 5 3D : SLIDES ET DEMOS par Groc
Durant les techdays, j'ai eu le plaisir d'animer une session sur Silverlight 5 et la 3D avec Simon Ferquel. Comme promis, voici nos slides et mes démos (celles avec le viper BSG) ici et là. Pour mémoire, les démos utilisent toutes le viper BSG...
Cliquez pour lire la suite de l'article par Groc [TECHDAYS 2012] SESSION WEBMATRIX 2 : LE COUTEAU SUISSE GRATUIT POUR VOS DéVELOPPEMENTS WEB - SLIDES[TECHDAYS 2012] SESSION WEBMATRIX 2 : LE COUTEAU SUISSE GRATUIT POUR VOS DéVELOPPEMENTS WEB - SLIDES par gpommier
Suite à la session que j'ai présenté sur WebMatrix 2, vous pouvez trouver les slides ici, ainsi que les démos en packages nuget : démos1 et démos2 J'en profite pour remercier chaleureusement tous ceux qui sont venus très nombreux à cette sess...
Cliquez pour lire la suite de l'article par gpommier [SHAREPOINT] LES SESSIONS TECHDAYS 2012.[SHAREPOINT] LES SESSIONS TECHDAYS 2012. par Patrick Guimonet
Voici donc pour ceux qui n'ont pas pu venir, ou ceux qui n'ont pas pu toutes les suivre la liste des sessions SharePoint aux TechDays 2012, que je mettrais à jour dès que les liens des vidéo seront disponibles. Ou ici : http...
Cliquez pour lire la suite de l'article par Patrick Guimonet TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3 par ROMELARD Fabrice
Speaker: Bernard Ourghanlian Cette session est comme chaque jour transmise en live par BrainSonic, et j'ai donc suivi cette troisième pleinière par ce moyen sur mon iPad . Elle est dédiée comme chaque année à la mise en perspective de l'é...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE !MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE ! par Vko
Hier durant une session dédiée aux Techdays 2012, j'ai eu le plaisir d'annoncer la sortie de la Béta 2 de Mishra Reader. C'est quoi ? Pour les utilisateurs, c'est une vraie expérience de lecture de flux RSS sur Windows. Rien à voir avec les produit...
Cliquez pour lire la suite de l'article par Vko
Logiciels
Tribler (2012)TRIBLER (2012)Tribler est un client pair à pair (P2P/Peer-to-Peer) open source avec la capacité de regarder des... Cliquez pour télécharger Tribler OneSwarm (2012)ONESWARM (2012)Le peer-to-peer qui protège votre vie privée, c'est OneSwarm.
Ce logiciel de peer-to-peer crypté... Cliquez pour télécharger OneSwarm PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning
|