Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 2008
-
24 oct. 2004 à 08:24
einalem58
Messages postés2Date d'inscriptionjeudi 12 avril 2007StatutMembreDernière intervention30 juillet 2007
-
2 mai 2007 à 14:13
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
einalem58
Messages postés2Date d'inscriptionjeudi 12 avril 2007StatutMembreDernière intervention30 juillet 2007 2 mai 2007 à 14:13
Moi j'aimerais te contacter si possible pour mieux comprendre ton programme ...
anouka_neandhal@hotmail.com est mon e-mail
merci!
danCHESS
Messages postés11Date d'inscriptionsamedi 30 septembre 2006StatutMembreDernière intervention13 décembre 20061 17 janv. 2007 à 00:30
hello
dans mon prog j'utilise une table étendue int echiquier[119] pour garder les états des cases et des structures pur sauvegarder les coups à chaque niveau recursif de alpha beta :
typedef struct le_COUP
{
int dep; /*n°case depart du coup*/
int arr; /*n° case d'arrivee du coup*/
int piece_jouee; /*piece jouee (roi , pion , etc ....*/
int type; /*type de coup (normal ,prise roque etc...)*/
int ext_type; /*si le coup est une prise qui attaque le roi , ---> = ATTAQUE_ROI*/
int ep; /*case de prise en passant (VIDE ou n°case)*/
int val; /*valeur du coup*/
} COUP;
COUP liste_coups_peres[100];
et
typedef struct la_PARTIE
{
COUP c; /*coup joue*/
int statut; /*coup dans biblio ou non (VRAI ou FAUX*/
int cap; /*si prise cap = etiquette piece*/
int coul; /*couleur piece prise*/
}
PARTIE;
bonsoir!
PARTIE coups[400]; /*garder 400 1/2 coups */
foxbowrnb
Messages postés4Date d'inscriptionvendredi 12 janvier 2007StatutMembreDernière intervention 5 août 2009 12 janv. 2007 à 15:58
dans ton jeu on peut se mettre (le roi) volotairement en situation d'échec, alors que c'est interdit.
sinon bravo
TurboSat
Messages postés11Date d'inscriptionlundi 6 janvier 2003StatutMembreDernière intervention 1 novembre 2004 1 nov. 2004 à 15:44
Mais il n'y a aps d'erreur, tu appliques la méthode qui instancie un maximum de position. C'est tout.
++@++
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 1 nov. 2004 à 11:56
je ne comprends toujours pas mon erreur..
TurboSat
Messages postés11Date d'inscriptionlundi 6 janvier 2003StatutMembreDernière intervention 1 novembre 2004 1 nov. 2004 à 00:44
Et bien en fait on ne peut pas, si on garde une seule représentation, il faut jouer puis défaire les coups joués. Et si on si on ne veut pas faire ça on est obligé d'instancier comme une brute.
Enfin, s'il y a une autre solution je suis preneur car j'y ai pas mal planché il y a quelques temps et je n'en ai pas trouvé.
++@++
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 1 nov. 2004 à 00:09
if (etat(situation2.plateau)!=0){
score= evaluation(situation2);
}else{
t'as ça qui ets en trop mais je ne vois rien d'autres...
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 1 nov. 2004 à 00:08
il l'a expliqué, j'ai trouvé ça clair...
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 1 nov. 2004 à 00:05
explique comment faire mieux stp, je ne comprends pas...
TurboSat
Messages postés11Date d'inscriptionlundi 6 janvier 2003StatutMembreDernière intervention 1 novembre 2004 1 nov. 2004 à 00:00
Je suis d'accord qu'en passant le tableau en paramètre de la fonction récursive c'est mieux que de le garder en global, cependant dans ton exemple tu réinstancies une positon autant de fois que tu évalues de coups différents, donc cet algo est extrèmement lent.
++@++
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 31 oct. 2004 à 19:00
t'as pas vraiment compris ce aue je voulais dire...
si tu mets un tableau global, pour un minimax, tu seras obligé de le jouer normalement, et avant le retour de fonction le jouer à l'envers (anuler le coup)... deux fois au lieu d'une seule...
non, mettre une variable pas pièce, ça parait interessant, mais je ne suis pas convaincu...
Franchement, avec un tableau, ton ia ressemble à ça :
int ab(unsigned char couleur, int profondeur, jeu situation){
signed int long bestscore=MINSCORE, score=0;
signed char coups[NOMBREMAXDECOUPS], i, a, nextcoup=-1;
jeu situation2;
profondeur--;
couleur++;
if (couleur==3){
couleur=1;
bestscore=MAXSCORE;
}
if (profondeur==0){
return (evaluation(situation));
}else{
for (i=0;i<NOMBREMAXDECOUPS;i++){
nextcoup=choisisunnouveaucoup(nextcoup, situation);
coups[i]=nextcoup;
if (nextcoup==-1){
i=8;
}else{
situation2=joue( nextcoup, situation, couleur);
a=etat(situation2.plateau);
if (a==1){
return MINSCORE;
}else if (a==2){
return MAXSCORE;
}
}
}
i=-1;
while (1){
i++;
if (coups[i]==-1 || i>NOMBREMAXDECOUPS){
break;
}else{
situation2=joue( coups[i], situation, couleur);
if (etat(situation2.plateau)!=0){
score= evaluation(situation2);
}else{
score=ab(couleur, profondeur, situation2);
}
if ( couleur == 1 && score < bestscore ){
bestscore=score;
}
if ( couleur == 2 && score > bestscore ){
bestscore=score;
}
}
}
}
return bestscore;
}
globalement avec un minimax classique, ça devrait donner ça, évidement il faut une fonction evaluate, et une liste des coups (et un lanceur car la, il ne renvoi pas le coup mais seulement le meilleur score...) une structure jeu (de votre choix, soi 64 cases, soi des pièces, ici cela ne changes rien) Les coups sont ici des types de bases, aux échecs, il y a au max 16*64 possibilitées (je comptes large, la je fait come si chaque pièce pouvait aller sur chaques cases) donc, 1024 possibilitées, évidement, ça fait pas mal, donc, il faut pas trop abuser sur la foncion d'évaluation, et tout optimiser (cet algo ne l'est probablement pas...)
Si on mets le tableau en globale, il faut alors mettre après chaque retour de fonction, un apel à une fonction qui aura pour paramètre le dèrnier coup joué, et qui "nétoira" ce dèrnier coup (genre historoique) mais je penses que la vitesse s'en resentirais...
TurboSat
Messages postés11Date d'inscriptionlundi 6 janvier 2003StatutMembreDernière intervention 1 novembre 2004 31 oct. 2004 à 18:19
Oui voilà, et jouer le coup à l'envers est beaucoup moins long que de devoit instancer autant de positions que de coups possibles.
On gagne donc en temps et en mémoire, que demander de plus ? :]
++@++
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 31 oct. 2004 à 16:11
", il suffit de déplacer une pièce dans un tableau étant stocké en global." => pour un minimax, la fonction liste tt les ocups, joue puis se rapelle elle même, donc, le tableau stoqué en global sufirait, mais le truc c'est que l'on devrait, dans ce cas jouer, puis après le retour de fonction enlever le coup joué... (dans un algo aussi long a exécuter, toujours privilègier la vitesse a la mémoire...)
TurboSat
Messages postés11Date d'inscriptionlundi 6 janvier 2003StatutMembreDernière intervention 1 novembre 2004 31 oct. 2004 à 16:00
Et bien les promotions sont gérées de la même manière, seule la représentation change.
Au lieu, à chaque branche de l'arbre de recherche, qui correspond donc à un coup différent pouvant être joué dans une position identique, donc à chacunes de ces branches, à la place d'instancier un nouveau tableau 8*8, il suffit de déplacer une pièce dans un tableau étant stocké en global.
Le déplacement de cette pièce correspondra donc au changement de valeur de deux cases : celle de départ et celle d'arrivée. Opération autrement plus rapide qu'instancier un nouveau tableau en mémoire, opération qui je le rappelle est l'une des plus couteuses en cycle d'horloge.
Bien entendu, il faudra donc être capable de jouer le coup à l'envers lorsque l'on dépile la fonction récursive, on joue le coup, on analyse, on note, on défait le coup, on joue un autre coup, etc...
Ainsi on n'utilisera plus qu'un tableau pour les millions de positions analysées ( on gagnera donc des millions d'instanciations, ce qui fait gagner à l'arrivée des millions... de secondes ;-) ).
En plus, le fait de n'utiliser plus qu'un seul tableau peu nous permettre de lui faire stocker autre chose que de simple int, car la mémoire n'est plus l'élément limitant.
On peut donc y stocker des structures plus évoluées comme un type pièce qui pourra contenir autrement plus d'information que le simple type de la pièce. Je pense entre autres au fait qu'elle soit clouée ou non, sa valeur dynamique (en fonction de la position et non plus simplement une valeur absolue définie par défaut quand on joue aux echecs, 9 pour la dame, 5 tour, 3 cavalier et fou et 1 pion), par exemple un pion situé près de la case de promotion vaudra autrement plus qu'un point, de même un fou enfermé sans espace de vie vaudra autrement moins qu'un fous rayonnant sur la grande diagonale, etc...
++@++
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 31 oct. 2004 à 15:15
plus rapide, je ne sais pas, car on ne saurais pas si ne case est inocupée ou pas, pour la fonction arbitre, je ne suis pas sur que le gain de temps serait conséquent...
Sinon, pour la mémoire, il y a 16 pièces par équipes, donc 32 pièces, au lieu de 64 cases, donc que l'on utilises des int ou des char, on divises par deux la mémoire utilisée, mais je dois te demander coment tu assures les promotions... ça t'obliges a faire un pointeur pour chaque type de pièce et d'ajouter le nombre de pices de ce types qui jouent... Soit 12 autres variables... Cela comliquerais les choses je penses plutot que de les simifier...
TurboSat
Messages postés11Date d'inscriptionlundi 6 janvier 2003StatutMembreDernière intervention 1 novembre 2004 31 oct. 2004 à 14:50
En fait il serait beaucoup plus rapide, et ne consommerait absolument pas de mémoire, de garder une représentation unique de l'échiquier et de déplacer les pièces dessus puis d'analyser la position obtenue, plutôt que de réinstancier un tableau à chaque nouveau coup joué, instanciation qui non seulement fait perdre un temps fou mais aussi une place mémoire considérable si à chaque position différente on associe un tableau différent...
++@++
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 21:21
ben çà c'est la freq virtuel ce test montre que c'est faut au moins sur mon ordi . En fait j'ai continuer le test sur 1 sec et clock fait un coup toutes les 15 ms environ et encore c'est aléatoire . Je sais pas si quelqu'un veut faire ce test je fournis le code .
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 29 oct. 2004 à 21:15
je suis pas d'accord avec toi. clock fait CLK_TCK ticks par seconde, et en général ça vaut 1000.
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 21:14
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 20:56
je viens de faire une comparaison QueryPerformanceCounter et clock et je me suis aperçu que en fait clock c'est SUPER MEGA imprécis :
sur un test j'ai obtenu:
clock:0
performance counter:10
PUIS
clock:31
performance counter:31
PUIS
clock:43
performance counter:40
PUIS
clock:43
performance counter:40
PUIS
clock:47
performance counter:59
Donc on voit que clock c'est pas le mieux ^^
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 20:35
sur mon ordi, le résolution du compteur de mon ordi(QueryPerformanceFrequency et QyeryPerformanceCounter) est de:
3'579'545 coups par seconde !!!!!!!!
alors que celle de clock() c'est à ma connaissance de environ
54 coups par seconde !!!!!!!
donc tu imagine la précision
attention c'est quoi 10^18 opération ?? C'est des addition ?
Ensuite pour la taille d'un octets si elle fait pas 8-bit çà pose des pb car les processeur utilise le 8-bit , les mémoire idem(toutes les méoires) donc c'est limité . Je pense que le seul exemple que je connais c'est celui des connection :
Dans la connection i2C, pour transmettre un octets on peut ou non ajouter un 9-ième bit pour vérifier la parité mais on ne peut pas l'utiliser cette octets à part refaire tout le hardware !!!!!!!!!!!
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 29 oct. 2004 à 20:22
Sinon pour le 0ms je pense que c'est kirua qui a raison, mon compilateur doit optimiser le code parceque meme avec 10^18 opérations c'est toujours 0 ms :)
Enfin pour l'assembleur je pense que tu as raison... en fait je ne connais pas du tout l'assembleur... Je répétais juste ce que nous avais dit notre prof qui ne doit pas bien connaitre lui non plus...
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 20:07
Ben quand on compile un prog, si int=4 octets quand on compile, alors int=4 octets quand on l'exécute .
Ensuite, pour 'add' par exemple,
les copilo(asm) regarde les paramètre et compare avec ceux recevable(car toutes instruction ne peut pas prendre tous les paramètre) et (là je suis pas sur) mais un 'add,ax,bx' ne sera pas codé de la même façon que
'add eax,ebx' donc si tu compile en 32-bit alors sur toutes le plateforme il s'exécuetra comme s'il était en 32-bit(même si c'est une plateforme 16-bit => erreur opcode inconnu) . Ca ne peut pas changer à l'exécution, c'est défini à la compilation .
Pour le 0 ms c'est parce que le compteur est imprécis ou alors qu'il y a trop peut d'opération à exécuter(passé les 1 GHertz, on approche du 1 Milliard d'instruction par sec voir plus donc évidemment c'est pas de l'ordre de la ms s'il y a une trentaine d'opération !) . A mon avis il vaut mieux utiliser les compteur de précision dispo sur les processeur actuel(ou Windows : QueryPerformanceCounter) .
Pour les test il faut les faire sur des durée longue(moi je fais sur environ12~20 sec) .
Pour ce qui est de la taille d'un octet j'ai des doutes qu'elle soit variable(ou alors pour des choses très particulière, à la limite pour les connections où elle utiliserfaire 9-bit pour la parité(puis retranscrit en 8-bit sans parité) mais sinon je vois pas) . Un petit exemple ???
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 29 oct. 2004 à 19:51
je voulais dire que ce n'est pas fixe en bits... car 1 byte ne fait pas toujours 8 bits ;)
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 29 oct. 2004 à 19:30
ok que char est toujours 1 byte, donc c'est une taille fixe.
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 29 oct. 2004 à 19:17
d'ailleurs la taille de char aussi n'est pas fixe... mais c'est toujours un byte :)
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 29 oct. 2004 à 19:11
vala, pour le long double j'étais pas certain. mais il me semble que j'avais vu ça sur la MSDN en fait ... ça dépend pê des vesion de VC.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 29 oct. 2004 à 18:52
les types precedes de 'long' comme 'long long' etc... sont dependants du compilo.
Pour info, VS traite 'long double' comme 'double', toujours 64 bits, pour les entiers idem.
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 29 oct. 2004 à 17:58
coucou, la vitesse est expoNentielle, pas expoTentielle, ça n'existe pas.
si tu as 0ms, c'est pê que ton compilo détecte que le programme ne sert à rien et baque les opérations... j'ai compilé avec GCC 3.2 version MingW
la taille des int dépend bien de la machine, ce n'est pas 4 * char, en fait, ce n'est pas standardisé. mais sous Win32 en règle générale on a ça:
char = 8 bits
short int = 16 bits
(long) int = 32 bits (le long est sous entendu)
long long int = 64 bits
float = 32 bits
double = 64 bits
long double = 80 bits (sûr ça ?)
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 29 oct. 2004 à 15:01
1bit != 1octet coucou747...
Sinon Pamaury, comment est-ce que tu as fait pour comparer la vitesse?
Et il me semble que c'est bien la meme instruction asm (add) qui est utilisée pour faire les additions 16bits sur les machines 16bits et 32bits sur les machines 32bits...
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 29 oct. 2004 à 14:18
Donc char vaut mieux ici sauf si tu ne crains pas d'utiliser de la mémoire
bien refaisons mes calculs avec 32 bits pur un int :
64*32*5*2=2048*10 = 20480
bon, ça fait 20 ko de ram pour 5 tours... je ne penses pas que cela soit énorme... Bon évidement il faut ajouter ceraines choses tels que la liste des coups si on fait un AB, mais certains seront automatiquement ignorés (principe de l'AB) Enfin voila, c'est sur que 100 ms c'est négligeable, mais 20ko de nos jours aussi
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 14:05
donc déjà il y a des trucs qui vont pas :
clock() n'est pas précis car cela correspond à une horloge qui s'active toutes 18.3 ms(je crois) donc si le code se fini entre 0ms et 18.3 ms, pour clock c'est 0 !!!
Ensuite, il me semble que la taille d'un int est fixe sinon quand gcc le transforme en assembleur, il fait comment pour savoir quel fonction utiliser ??? Parce qu'il en existe pour le 8-bit, 16-bit et 32-bit(voir 64-bit) donc un int fait 32-bit s'il est compilé pour une platforme 32-bit . Mais à l'exécution çà ne change pas . Donc sur une plateforme 32-bit int=long(long fait toujours 32-bit) . Sur une 16-bit int doit faire 16-bit ...
J'ia fais quelque test et c'est vraiment séré : sur 12 sec, en faisant un test de comparaison, copie de tableau et d'initialisation de tableau, la différence est de 100ms doit une broutille(sur 12 sec) . Donc char vaut mieux ici sauf si tu ne crains pas d'utiliser de la mémoire
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 29 oct. 2004 à 13:58
Sinon kirua ton code me renvoie 0 ms pour les deux, c'est dur à comparer :)
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 29 oct. 2004 à 13:46
En fait, int dépend de la machine utilisée.
C'est 32 bits actuellement dans la majorité des cas, parfois 64 bits. Et je crois que long = int.
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 29 oct. 2004 à 12:57
comme dans une IA la vitesse est expotentielle, il faut apliquer les principes du précalculs (sans faire de précalculs ^^) c'ets a dire privilégier la vitesse plutot que la mémoire...
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 29 oct. 2004 à 12:56
int long = 32 bits
int = 16 bits
je viens encore de le lire dans Le language C de Claudes Delanoy
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 12:45
AHHHHHHHH
int=32-bit
Donc un int=4*char alors que l'utilité d'un char ici est moindre donc tu avec des char tu peux faire une ia plus performante car tu as plus de mémoire dispo . Pour la vitesse vu la différence entre les deux à mon avis ici la priorité c'est les char puis la vitesse . Je vais faire des test plus appronfondies sur la différence de vitesse
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 29 oct. 2004 à 10:18
euh...
L'ai, la vitesse est expotentielle, mais la mémoire afine, ça te dis qqch ??
si tu mets une profondeur de 5, alros pour une ia, minimax ou AB tu utiliseras :
dans le cas des char :
64*2*5=128*5
(deux car il faut garder une copie de l'ancienne position, puis jouer, 5 car la c'ets la profondeur...)
dans le cas des int : (int = 16 bits)
128*2*5=256*5
Enfin voila, ça fait toujours très peu, alors que la vitesse elle est expotentielle en fonction de laprofondeur et que l'on a souvent des milliers de calculs, je penses q'il faut toujours privilègier la vitesse dans un truc aussi gourmand en vitesse...
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 29 oct. 2004 à 08:55
ouais intéressant, mais bon pour une différence si petite, je pense que les char sont un bon choix, parce que si tu fais des tableau d'int çà va bouffer ta mémoire . En plus l'IA utilisera probablement un grand nombre de tableau donc les char c'est mieux à mon avis .
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 29 oct. 2004 à 00:09
bon, je viens de taper ça pour voir, et la différence est très très faible (mais les int sont qd même plus rapides ... mais vrmnt faible, de l'ordre de 30 ms pour un calcul de près de 3s, donc on ne peut pas vrmnt dire, d'autant que parfois le tps est exactement pareil, mais les char ne vont jms plus vite que les int)
#include
#include <ctime>
using namespace std;
int main(int argc, char **argv)
{
int a, b, c;
char d, e, f;
cout << "Benchmark int / char:" << endl;
cin.get();
clock_t tps = clock();
for(int i = 0; i < 1000000000; i++)
c = a + b;
cout << (clock()-tps) << " ms pour les int" << endl;
cin.get();
tps = clock();
for(int i = 0; i < 1000000000; i++)
f = d + e;
cout << (clock()-tps) << " ms pour les char" << endl;
cin.get();
return 0;
}
étant donné la différence, il est probablement plus avantageux de privilégier la place. cependant, si la place est sans limite et le temps crucial, c'est bon à retenir.
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 28 oct. 2004 à 19:37
je ne suis pas d'accord car si tu as deja fait de l'assembleur, on peut directement accédé à la partie basse(8-bit) d'un registre et il existe des instruction en général pour chaque type(8-bit,16-bit,32-bit voir 64-bit), donc le char est aussi rapide que les int et en plus il y économie de mémoire :
char tab[8][8]=64 octets(8*8*1)
int tab[8][8]=256 octets(8*8*4)
Donc niveau rapidité d'exécution çà ne change rien . Donc je te conseille les char car çà bouffera moins de mémoire .
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 28 oct. 2004 à 19:30
en fait, qq part ds le processur d'exécution, toutes les valeurs de plus petite taille qu'un int sont transformée en int puis retransformée en leur type de départ après l'opération. et c'est pr ça que paradoxalement fait une addition de char est plus lent qu'une addition de int.
Tellmarch
Messages postés53Date d'inscriptionsamedi 22 mars 2003StatutMembreDernière intervention27 septembre 2005 28 oct. 2004 à 18:04
gemx, tu es sur qu'il est plus long de travailler avec des char? je croyais que c'était juste des entiers sur 8 bits, donc plus économes en mémoire et aussi rapide...
Au fait tu dit que int[8][8] prendrais 128 octets, mais c'est plutot 256 en général voire 512...
cs_LiBe444
Messages postés220Date d'inscriptiondimanche 7 septembre 2003StatutMembreDernière intervention 7 avril 2007 27 oct. 2004 à 20:08
Bonjour,
hé thymulus, le compilateur n'est pas Dev-Cpp, c'est gcc !
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 27 oct. 2004 à 16:07
pas chevaux cavaliers, sinon, un cheva qui prends une dame, ça fait un peu spé... Un cavalier, ça rapelerais plus lancelot...
Enfin les gouts et les couleurs...
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 27 oct. 2004 à 15:23
dsl, j'avais mal compté, ça fait bien 8*2 + 2*2 = 20, dsl ;)
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 27 oct. 2004 à 15:22
au premir coup tu peux aussi bouger les chevaux ;)
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 27 oct. 2004 à 13:57
oui, je sais, pour les avoir implémenté, je sais comment marche minimax et alpha béta, mais si tu fais une boucle, logiquement, tu ne dépenses pas bcp plus de deux fois l'espace mémoire ou tu plaçais l'échiquier * la profondeur car le tout étant dans des fonctions, les variables après le reotur de fonctions sont suprimés, et l'espace a nouveau disponible, donc, la tu as un échiquier de 64 cases en char , ça te fait 128 * profondeur d'utilisé... évidement pour un AB il faut aussi retenir les coups joués, et la cote...
Ce qui augmente de manière expotentielle, c'ets letemp de calcul pas la mémoire, lma mémoire augmente de fonction afine...
Autrement, pour son IA, il sera obligé de mettre des variables locales et pas globales...
gemx
Messages postés6Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention 8 novembre 2004 27 oct. 2004 à 12:24
En réponse a coucou747 :
Si tu utilise l'algo min-max et alpha-bêta, tu va plus loin qu'un coup de profondeur ... au moins 3 ... Je rappel qu'un coup est composé de deux demi coup (un coup blanc et un coup noir). Sachant que pour le premier demi coup jouer, il ya 20 posibilité donc 64*20=1280 octets, et que ça augmente de manière exponentiel pour le reste... Il existe d'autre maniere tel que les structures variable etc, mais je suis pas assez calé sur le sujet...
néanmoins tu as raison sur un point : un tableau de char en 8*8 prend moin de place qu'un tableau de int en 8*8 (64octets contre 128). Cependant vu le nombre de compartaison qu'il devra faire, il me semble plus judicieux de le faire avec des entier plutot que des char (plus rapide au traitement). Voil pourquoi je lui conseiller ça!
En ce qui concerne la gestion de la mémoir, je suis d'accord avec toi! Je n'ai jamais dit le contraire. Je lui ai juste dit qu'il vaudrait mieux mettre ça en variable local plutot qu'en globale. Surtout si il fait une IA plutard ! ça bouffe bcp de ressource alors c pas la peine de le le reservé pour toute la duré du programme ...
Voila !
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 27 oct. 2004 à 11:57
"- char echiquier[8][8] et encore c pas tres propre ... moi à ta place j'aurais utilisé un int echiquier [8][8] avec des valeur type 1 pour roi blanc, 2 pour roi noir etc ... et 0 pour case vide. (po besoin d'utiliser des lettres ça prend trop de place ... surtout si tu veut faire plus tard une IA ... car dans ce k là tu multiplie les tableaux !)"
Pur l"ia tu es obligé de faire un tableau pour un coup de profondeur non ? Enfin moi je ne vois pas comment faire autrement... Ca fait 64 octets pour un coup de prpofondeur, tu sais pour l'ia, c'ets quand on lui met une mémoire que ça prends pas mal de ram, et ce'ts pas en fonciton de la façon de coder le tableau, avec ta méthode comme avec la sienne, ça fait 64 octets...
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 27 oct. 2004 à 09:01
Est-ce que tu as mis PAINTSTRUCT en global ? Si oui mets-le dans la fonction de dessin et redessine que ce qui est nécessaire(pas toujours facile avec l'API Windows que je trouve nul pour le dessin mais excellente pour le reste) . Et c'est sur que autant de var globales c'est pas génial .
gemx
Messages postés6Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention 8 novembre 2004 27 oct. 2004 à 00:26
Ha oui, un autre ruc ! Tu redessinne tous le tableau et les pions a chaque frois que tu fais un déplacement ! c source de facilité ça non ? redessine la case concerné détruit et recré juste le pion !
gemx
Messages postés6Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention 8 novembre 2004 27 oct. 2004 à 00:21
si je pouvais avoir plus de remarques/suggestions constructives>> je vais essayer de faire court :
De toutes les vairiables globales que tu as utilisé, je pense qu'il n'y en a que quelques une d'utiles :
- char echiquier[8][8] et encore c pas tres propre ... moi à ta place j'aurais utilisé un int echiquier [8][8] avec des valeur type 1 pour roi blanc, 2 pour roi noir etc ... et 0 pour case vide. (po besoin d'utiliser des lettres ça prend trop de place ... surtout si tu veut faire plus tard une IA ... car dans ce k là tu multiplie les tableaux !)
- Un truc con pour connaitre la couleur de la case : tu additionne le X et e Y de ton tableau (int echiquier[X][Y])
si le chifre est paire, donc divisble par 2 sans virgule, la case est blanche et inversement ...
Ensuite, j'ai po annalyser tt ton code, mais toutes les donner type roque, connaitre le joueur, echec et mat ! vire les met les dans des fonctions ! par exemple si y'a eu un roque, n'appel plus la fonction pour savoir si il ya eu le roque etc ...
Bref les seul truc valable : c ton echiquier et encore ... et tout ce qui concerne t "PAINTSTRUCT HINSTANCE HBITMAP HDC" je suis pas assez bon en prog API pour dir si c'est necessaire ou pas, mais franchement je ne suis pas sur.
Pourquoi je te fais chier avec les vairiable global ? Tout simplement parceque elle sont allouer dans la RAM de ton ordi pendant TOUTE la duré du programme ! Certe, t'en as pas beaucoup ici, mais quand tu bossera sur des grosses appli, tu sera dégouter de voir qu'elle utilise 60% de la RAM !
Quelques règles que tu n'as pas utiliser (enfin je ne crois pas) :
-regles des 50 coup, prise en passant etc ...
Voila j'espere que j'ai été explicite !
Sinon je te félicite ! Continu ! moi j'adore la programmation d'échecs! et j'aimerais en voire encore plus !!!!!
Bon courage !
Thymulus
Messages postés3Date d'inscriptionmercredi 29 septembre 2004StatutMembreDernière intervention25 octobre 2004 25 oct. 2004 à 13:05
Je prends en compte vos remarques et chagerai le code pour vous satisfaire. Cependant, si je pouvais avoir plus de remarques/suggestions constructives pour le codes cela me serai en effet très utiles pour pouvoir progresser. Je remercie tout de même ce qui ont déja laisser leurs lettres en commentaire ;)
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 25 oct. 2004 à 11:02
aussi, on doit taper sur le crono avec la main qui a effectué le déplacement, puis noter tout les coups si on ets en longue et pas poussin...
cs_PiX3L
Messages postés102Date d'inscriptiondimanche 27 juillet 2003StatutMembreDernière intervention13 août 20051 25 oct. 2004 à 08:11
Pas mal du tout, pour le déplacement des pièces normalement on a pas le droit c'est vrai mais là on est pas sur plateau, c'est bcp plus pratique, suffit qu'on ait cliqué sans faire attention (alors qu'il est pas possible de prendre une pièce sans le faire exprès :)) et hop un tour de perdu :(
cs_Kirua
Messages postés3006Date d'inscriptiondimanche 14 avril 2002StatutMembreDernière intervention31 décembre 2008 24 oct. 2004 à 13:35
j'ai eu du mal, mais j'ai réussi en jouant tout seul à me mettre échec et mat, je dois être super fort pour mettre autant de temps :D c'est plutôt bien réalisé, bravo :)
Thymulus
Messages postés3Date d'inscriptionmercredi 29 septembre 2004StatutMembreDernière intervention25 octobre 2004 24 oct. 2004 à 10:21
Article 4 : Le déplacement des pièces
4.1 Chaque coup doit être effectué d'une seule main.
4.2 A la condition qu'il exprime son intention (par exemple en disant ??j'adoube?? ou « je rectifie »), le
joueur ayant le trait peut rectifier la position d'une ou de plusieurs pièces sur leur case.
4.3 Sous réserve de l'article 4.2, si le joueur ayant le trait touche délibérément sur l'échiquier :
a) une ou plusieurs de ses propres pièces, il doit bouger la première pièce touchée qui peut être
bougée ou prise, ou
b) une ou plusieurs pièces adverses, il doit capturer la première pièce touchée qui peut l'être.
c) une pièce de chaque couleur, il doit capturer la pièce adverse avec sa pièce ou, si c'est illégal,
bouger ou prendre la première piècetouchée quipeut être bougée ou prise.Si la situation n'est pas claire et
qu'on ne peut établir si c'est la propre pièce du joueur ou celle de l'adversaire qui a été touchée la première,
on considérera que la propre pièce du joueur aura été touchée avant celle de son adversaire.
4.4 a) Si un joueur touche délibérément sa tour et son roi, il doit roquer de ce côté si c'est légal.
b) Si un joueur touche délibérément une tour et ensuite son roi, il n'est pas autorisé à roquer de ce
coté lors de ce coup et l'on réglera alors ce cas selon l'article 4.3 a.
c) Si un joueur ayant l'intention de roquer touche d'abord le roi ou le roi et la tour simultanément, alors
que le roque de ce coté est impossible, il doit choisir soit de roquer de l'autre coté, pour autant que ce roque
soit possible, soit de déplacer le roi. Si le roi ne peut être bougé, le joueur est libre d'effectuer n'importe quel
autre coup possible.
4.5 Si aucune des pièces touchées ne peut être bougée ou prise, le joueur peut alors effectuer n'importe
quel autre coup possible.
4.6 Si l'adversaire enfreint l'article 4.3 ou 4.4, le joueur ne peut réclamer s'il a lui-même délibérément
touché une pièce.
4.7 Quand, lors d'un coup légal ou comme faisant partie d'un coup légal, une pièce a été lâchée sur une
case, elle ne peut être déplacée sur une autre case. On considère le coup exécuté lorsque toutes les
conditions de l'article 3 ont été respectées.
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 24 oct. 2004 à 09:54
rectification:
il me semble que c'est plutôt pièce posée pièce jouée mais si tu la garde en main sans la poser, ce n'est pas jouer .
Thymulus
Messages postés3Date d'inscriptionmercredi 29 septembre 2004StatutMembreDernière intervention25 octobre 2004 24 oct. 2004 à 09:45
La sélection du pion c'est pour respecter le règle échiquienne qui veux qu'une pièce "touché" doit être jouée.
Sinon pour les variables, étant novices, si vous avez des propositions, sinon je verrai pour arranger ca.
Pamaury
Messages postés341Date d'inscriptionjeudi 3 avril 2003StatutMembreDernière intervention17 juin 20083 24 oct. 2004 à 08:24
pas mal du tout mais il y a quelques trucs pénibles : quand on sélectionne un pion, on est obligé de jouer avec lui et on peux pas changer la sélection .
Sinon, je trouve qu'il y a bcp de variables globales, je sais pas si elle servent toutes mais çà fait un paquet .
2 mai 2007 à 14:13
anouka_neandhal@hotmail.com est mon e-mail
merci!
17 janv. 2007 à 00:30
dans mon prog j'utilise une table étendue int echiquier[119] pour garder les états des cases et des structures pur sauvegarder les coups à chaque niveau recursif de alpha beta :
typedef struct le_COUP
{
int dep; /*n°case depart du coup*/
int arr; /*n° case d'arrivee du coup*/
int piece_jouee; /*piece jouee (roi , pion , etc ....*/
int type; /*type de coup (normal ,prise roque etc...)*/
int ext_type; /*si le coup est une prise qui attaque le roi , ---> = ATTAQUE_ROI*/
int ep; /*case de prise en passant (VIDE ou n°case)*/
int val; /*valeur du coup*/
} COUP;
COUP liste_coups_peres[100];
et
typedef struct la_PARTIE
{
COUP c; /*coup joue*/
int statut; /*coup dans biblio ou non (VRAI ou FAUX*/
int cap; /*si prise cap = etiquette piece*/
int coul; /*couleur piece prise*/
}
PARTIE;
bonsoir!
PARTIE coups[400]; /*garder 400 1/2 coups */
12 janv. 2007 à 15:58
sinon bravo
1 nov. 2004 à 15:44
++@++
1 nov. 2004 à 11:56
1 nov. 2004 à 00:44
Enfin, s'il y a une autre solution je suis preneur car j'y ai pas mal planché il y a quelques temps et je n'en ai pas trouvé.
++@++
1 nov. 2004 à 00:09
score= evaluation(situation2);
}else{
t'as ça qui ets en trop mais je ne vois rien d'autres...
1 nov. 2004 à 00:08
1 nov. 2004 à 00:05
1 nov. 2004 à 00:00
++@++
31 oct. 2004 à 19:00
si tu mets un tableau global, pour un minimax, tu seras obligé de le jouer normalement, et avant le retour de fonction le jouer à l'envers (anuler le coup)... deux fois au lieu d'une seule...
non, mettre une variable pas pièce, ça parait interessant, mais je ne suis pas convaincu...
Franchement, avec un tableau, ton ia ressemble à ça :
int ab(unsigned char couleur, int profondeur, jeu situation){
signed int long bestscore=MINSCORE, score=0;
signed char coups[NOMBREMAXDECOUPS], i, a, nextcoup=-1;
jeu situation2;
profondeur--;
couleur++;
if (couleur==3){
couleur=1;
bestscore=MAXSCORE;
}
if (profondeur==0){
return (evaluation(situation));
}else{
for (i=0;i<NOMBREMAXDECOUPS;i++){
nextcoup=choisisunnouveaucoup(nextcoup, situation);
coups[i]=nextcoup;
if (nextcoup==-1){
i=8;
}else{
situation2=joue( nextcoup, situation, couleur);
a=etat(situation2.plateau);
if (a==1){
return MINSCORE;
}else if (a==2){
return MAXSCORE;
}
}
}
i=-1;
while (1){
i++;
if (coups[i]==-1 || i>NOMBREMAXDECOUPS){
break;
}else{
situation2=joue( coups[i], situation, couleur);
if (etat(situation2.plateau)!=0){
score= evaluation(situation2);
}else{
score=ab(couleur, profondeur, situation2);
}
if ( couleur == 1 && score < bestscore ){
bestscore=score;
}
if ( couleur == 2 && score > bestscore ){
bestscore=score;
}
}
}
}
return bestscore;
}
globalement avec un minimax classique, ça devrait donner ça, évidement il faut une fonction evaluate, et une liste des coups (et un lanceur car la, il ne renvoi pas le coup mais seulement le meilleur score...) une structure jeu (de votre choix, soi 64 cases, soi des pièces, ici cela ne changes rien) Les coups sont ici des types de bases, aux échecs, il y a au max 16*64 possibilitées (je comptes large, la je fait come si chaque pièce pouvait aller sur chaques cases) donc, 1024 possibilitées, évidement, ça fait pas mal, donc, il faut pas trop abuser sur la foncion d'évaluation, et tout optimiser (cet algo ne l'est probablement pas...)
Si on mets le tableau en globale, il faut alors mettre après chaque retour de fonction, un apel à une fonction qui aura pour paramètre le dèrnier coup joué, et qui "nétoira" ce dèrnier coup (genre historoique) mais je penses que la vitesse s'en resentirais...
31 oct. 2004 à 18:19
On gagne donc en temps et en mémoire, que demander de plus ? :]
++@++
31 oct. 2004 à 16:11
31 oct. 2004 à 16:00
Au lieu, à chaque branche de l'arbre de recherche, qui correspond donc à un coup différent pouvant être joué dans une position identique, donc à chacunes de ces branches, à la place d'instancier un nouveau tableau 8*8, il suffit de déplacer une pièce dans un tableau étant stocké en global.
Le déplacement de cette pièce correspondra donc au changement de valeur de deux cases : celle de départ et celle d'arrivée. Opération autrement plus rapide qu'instancier un nouveau tableau en mémoire, opération qui je le rappelle est l'une des plus couteuses en cycle d'horloge.
Bien entendu, il faudra donc être capable de jouer le coup à l'envers lorsque l'on dépile la fonction récursive, on joue le coup, on analyse, on note, on défait le coup, on joue un autre coup, etc...
Ainsi on n'utilisera plus qu'un tableau pour les millions de positions analysées ( on gagnera donc des millions d'instanciations, ce qui fait gagner à l'arrivée des millions... de secondes ;-) ).
En plus, le fait de n'utiliser plus qu'un seul tableau peu nous permettre de lui faire stocker autre chose que de simple int, car la mémoire n'est plus l'élément limitant.
On peut donc y stocker des structures plus évoluées comme un type pièce qui pourra contenir autrement plus d'information que le simple type de la pièce. Je pense entre autres au fait qu'elle soit clouée ou non, sa valeur dynamique (en fonction de la position et non plus simplement une valeur absolue définie par défaut quand on joue aux echecs, 9 pour la dame, 5 tour, 3 cavalier et fou et 1 pion), par exemple un pion situé près de la case de promotion vaudra autrement plus qu'un point, de même un fou enfermé sans espace de vie vaudra autrement moins qu'un fous rayonnant sur la grande diagonale, etc...
++@++
31 oct. 2004 à 15:15
Sinon, pour la mémoire, il y a 16 pièces par équipes, donc 32 pièces, au lieu de 64 cases, donc que l'on utilises des int ou des char, on divises par deux la mémoire utilisée, mais je dois te demander coment tu assures les promotions... ça t'obliges a faire un pointeur pour chaque type de pièce et d'ajouter le nombre de pices de ce types qui jouent... Soit 12 autres variables... Cela comliquerais les choses je penses plutot que de les simifier...
31 oct. 2004 à 14:50
++@++
29 oct. 2004 à 21:21
29 oct. 2004 à 21:15
29 oct. 2004 à 21:14
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 0 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 0 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 0 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 0 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 1 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 1 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 1 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 2 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 3 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 4 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 5 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 6 |
+----------------------------+--------+
| clock: | 0 |
| Performance Counter: | 7 |
+----------------------------+--------+
| clock: | 15 |
| Performance Counter: | 9 |
+----------------------------+--------+
| clock: | 15 |
| Performance Counter: | 10 |
+----------------------------+--------+
Je crois que çà suffit pour vous disuader d'utiliser clock un maximum ^^
29 oct. 2004 à 20:56
sur un test j'ai obtenu:
clock:0
performance counter:10
PUIS
clock:31
performance counter:31
PUIS
clock:43
performance counter:40
PUIS
clock:43
performance counter:40
PUIS
clock:47
performance counter:59
Donc on voit que clock c'est pas le mieux ^^
29 oct. 2004 à 20:35
3'579'545 coups par seconde !!!!!!!!
alors que celle de clock() c'est à ma connaissance de environ
54 coups par seconde !!!!!!!
donc tu imagine la précision
attention c'est quoi 10^18 opération ?? C'est des addition ?
Ensuite pour la taille d'un octets si elle fait pas 8-bit çà pose des pb car les processeur utilise le 8-bit , les mémoire idem(toutes les méoires) donc c'est limité . Je pense que le seul exemple que je connais c'est celui des connection :
Dans la connection i2C, pour transmettre un octets on peut ou non ajouter un 9-ième bit pour vérifier la parité mais on ne peut pas l'utiliser cette octets à part refaire tout le hardware !!!!!!!!!!!
29 oct. 2004 à 20:22
Malheuresement je n'ai pas d'exemple, je peux juste donner ma source : http://c.developpez.com/faq/c/?page=types#TYPE_taille_char
Sinon pour le 0ms je pense que c'est kirua qui a raison, mon compilateur doit optimiser le code parceque meme avec 10^18 opérations c'est toujours 0 ms :)
Enfin pour l'assembleur je pense que tu as raison... en fait je ne connais pas du tout l'assembleur... Je répétais juste ce que nous avais dit notre prof qui ne doit pas bien connaitre lui non plus...
29 oct. 2004 à 20:07
Ensuite, pour 'add' par exemple,
les copilo(asm) regarde les paramètre et compare avec ceux recevable(car toutes instruction ne peut pas prendre tous les paramètre) et (là je suis pas sur) mais un 'add,ax,bx' ne sera pas codé de la même façon que
'add eax,ebx' donc si tu compile en 32-bit alors sur toutes le plateforme il s'exécuetra comme s'il était en 32-bit(même si c'est une plateforme 16-bit => erreur opcode inconnu) . Ca ne peut pas changer à l'exécution, c'est défini à la compilation .
Pour le 0 ms c'est parce que le compteur est imprécis ou alors qu'il y a trop peut d'opération à exécuter(passé les 1 GHertz, on approche du 1 Milliard d'instruction par sec voir plus donc évidemment c'est pas de l'ordre de la ms s'il y a une trentaine d'opération !) . A mon avis il vaut mieux utiliser les compteur de précision dispo sur les processeur actuel(ou Windows : QueryPerformanceCounter) .
Pour les test il faut les faire sur des durée longue(moi je fais sur environ12~20 sec) .
Pour ce qui est de la taille d'un octet j'ai des doutes qu'elle soit variable(ou alors pour des choses très particulière, à la limite pour les connections où elle utiliserfaire 9-bit pour la parité(puis retranscrit en 8-bit sans parité) mais sinon je vois pas) . Un petit exemple ???
29 oct. 2004 à 19:51
29 oct. 2004 à 19:30
29 oct. 2004 à 19:17
29 oct. 2004 à 19:11
29 oct. 2004 à 18:52
Pour info, VS traite 'long double' comme 'double', toujours 64 bits, pour les entiers idem.
29 oct. 2004 à 17:58
si tu as 0ms, c'est pê que ton compilo détecte que le programme ne sert à rien et baque les opérations... j'ai compilé avec GCC 3.2 version MingW
la taille des int dépend bien de la machine, ce n'est pas 4 * char, en fait, ce n'est pas standardisé. mais sous Win32 en règle générale on a ça:
char = 8 bits
short int = 16 bits
(long) int = 32 bits (le long est sous entendu)
long long int = 64 bits
float = 32 bits
double = 64 bits
long double = 80 bits (sûr ça ?)
29 oct. 2004 à 15:01
Sinon Pamaury, comment est-ce que tu as fait pour comparer la vitesse?
Et il me semble que c'est bien la meme instruction asm (add) qui est utilisée pour faire les additions 16bits sur les machines 16bits et 32bits sur les machines 32bits...
29 oct. 2004 à 14:18
bien refaisons mes calculs avec 32 bits pur un int :
64*32*5*2=2048*10 = 20480
bon, ça fait 20 ko de ram pour 5 tours... je ne penses pas que cela soit énorme... Bon évidement il faut ajouter ceraines choses tels que la liste des coups si on fait un AB, mais certains seront automatiquement ignorés (principe de l'AB) Enfin voila, c'est sur que 100 ms c'est négligeable, mais 20ko de nos jours aussi
29 oct. 2004 à 14:05
clock() n'est pas précis car cela correspond à une horloge qui s'active toutes 18.3 ms(je crois) donc si le code se fini entre 0ms et 18.3 ms, pour clock c'est 0 !!!
Ensuite, il me semble que la taille d'un int est fixe sinon quand gcc le transforme en assembleur, il fait comment pour savoir quel fonction utiliser ??? Parce qu'il en existe pour le 8-bit, 16-bit et 32-bit(voir 64-bit) donc un int fait 32-bit s'il est compilé pour une platforme 32-bit . Mais à l'exécution çà ne change pas . Donc sur une plateforme 32-bit int=long(long fait toujours 32-bit) . Sur une 16-bit int doit faire 16-bit ...
J'ia fais quelque test et c'est vraiment séré : sur 12 sec, en faisant un test de comparaison, copie de tableau et d'initialisation de tableau, la différence est de 100ms doit une broutille(sur 12 sec) . Donc char vaut mieux ici sauf si tu ne crains pas d'utiliser de la mémoire
29 oct. 2004 à 13:58
29 oct. 2004 à 13:46
C'est 32 bits actuellement dans la majorité des cas, parfois 64 bits. Et je crois que long = int.
29 oct. 2004 à 12:57
29 oct. 2004 à 12:56
int = 16 bits
je viens encore de le lire dans Le language C de Claudes Delanoy
29 oct. 2004 à 12:45
int=32-bit
Donc un int=4*char alors que l'utilité d'un char ici est moindre donc tu avec des char tu peux faire une ia plus performante car tu as plus de mémoire dispo . Pour la vitesse vu la différence entre les deux à mon avis ici la priorité c'est les char puis la vitesse . Je vais faire des test plus appronfondies sur la différence de vitesse
29 oct. 2004 à 10:18
L'ai, la vitesse est expotentielle, mais la mémoire afine, ça te dis qqch ??
si tu mets une profondeur de 5, alros pour une ia, minimax ou AB tu utiliseras :
dans le cas des char :
64*2*5=128*5
(deux car il faut garder une copie de l'ancienne position, puis jouer, 5 car la c'ets la profondeur...)
dans le cas des int : (int = 16 bits)
128*2*5=256*5
Enfin voila, ça fait toujours très peu, alors que la vitesse elle est expotentielle en fonction de laprofondeur et que l'on a souvent des milliers de calculs, je penses q'il faut toujours privilègier la vitesse dans un truc aussi gourmand en vitesse...
29 oct. 2004 à 08:55
29 oct. 2004 à 00:09
#include
#include <ctime>
using namespace std;
int main(int argc, char **argv)
{
int a, b, c;
char d, e, f;
cout << "Benchmark int / char:" << endl;
cin.get();
clock_t tps = clock();
for(int i = 0; i < 1000000000; i++)
c = a + b;
cout << (clock()-tps) << " ms pour les int" << endl;
cin.get();
tps = clock();
for(int i = 0; i < 1000000000; i++)
f = d + e;
cout << (clock()-tps) << " ms pour les char" << endl;
cin.get();
return 0;
}
étant donné la différence, il est probablement plus avantageux de privilégier la place. cependant, si la place est sans limite et le temps crucial, c'est bon à retenir.
28 oct. 2004 à 19:37
char tab[8][8]=64 octets(8*8*1)
int tab[8][8]=256 octets(8*8*4)
Donc niveau rapidité d'exécution çà ne change rien . Donc je te conseille les char car çà bouffera moins de mémoire .
28 oct. 2004 à 19:30
28 oct. 2004 à 18:04
Au fait tu dit que int[8][8] prendrais 128 octets, mais c'est plutot 256 en général voire 512...
27 oct. 2004 à 20:08
hé thymulus, le compilateur n'est pas Dev-Cpp, c'est gcc !
27 oct. 2004 à 16:07
Enfin les gouts et les couleurs...
27 oct. 2004 à 15:23
27 oct. 2004 à 15:22
27 oct. 2004 à 13:57
Ce qui augmente de manière expotentielle, c'ets letemp de calcul pas la mémoire, lma mémoire augmente de fonction afine...
Autrement, pour son IA, il sera obligé de mettre des variables locales et pas globales...
27 oct. 2004 à 12:24
Si tu utilise l'algo min-max et alpha-bêta, tu va plus loin qu'un coup de profondeur ... au moins 3 ... Je rappel qu'un coup est composé de deux demi coup (un coup blanc et un coup noir). Sachant que pour le premier demi coup jouer, il ya 20 posibilité donc 64*20=1280 octets, et que ça augmente de manière exponentiel pour le reste... Il existe d'autre maniere tel que les structures variable etc, mais je suis pas assez calé sur le sujet...
néanmoins tu as raison sur un point : un tableau de char en 8*8 prend moin de place qu'un tableau de int en 8*8 (64octets contre 128). Cependant vu le nombre de compartaison qu'il devra faire, il me semble plus judicieux de le faire avec des entier plutot que des char (plus rapide au traitement). Voil pourquoi je lui conseiller ça!
En ce qui concerne la gestion de la mémoir, je suis d'accord avec toi! Je n'ai jamais dit le contraire. Je lui ai juste dit qu'il vaudrait mieux mettre ça en variable local plutot qu'en globale. Surtout si il fait une IA plutard ! ça bouffe bcp de ressource alors c pas la peine de le le reservé pour toute la duré du programme ...
Voila !
27 oct. 2004 à 11:57
Pur l"ia tu es obligé de faire un tableau pour un coup de profondeur non ? Enfin moi je ne vois pas comment faire autrement... Ca fait 64 octets pour un coup de prpofondeur, tu sais pour l'ia, c'ets quand on lui met une mémoire que ça prends pas mal de ram, et ce'ts pas en fonciton de la façon de coder le tableau, avec ta méthode comme avec la sienne, ça fait 64 octets...
27 oct. 2004 à 09:01
27 oct. 2004 à 00:26
27 oct. 2004 à 00:21
De toutes les vairiables globales que tu as utilisé, je pense qu'il n'y en a que quelques une d'utiles :
- char echiquier[8][8] et encore c pas tres propre ... moi à ta place j'aurais utilisé un int echiquier [8][8] avec des valeur type 1 pour roi blanc, 2 pour roi noir etc ... et 0 pour case vide. (po besoin d'utiliser des lettres ça prend trop de place ... surtout si tu veut faire plus tard une IA ... car dans ce k là tu multiplie les tableaux !)
- Un truc con pour connaitre la couleur de la case : tu additionne le X et e Y de ton tableau (int echiquier[X][Y])
si le chifre est paire, donc divisble par 2 sans virgule, la case est blanche et inversement ...
Ensuite, j'ai po annalyser tt ton code, mais toutes les donner type roque, connaitre le joueur, echec et mat ! vire les met les dans des fonctions ! par exemple si y'a eu un roque, n'appel plus la fonction pour savoir si il ya eu le roque etc ...
Bref les seul truc valable : c ton echiquier et encore ... et tout ce qui concerne t "PAINTSTRUCT HINSTANCE HBITMAP HDC" je suis pas assez bon en prog API pour dir si c'est necessaire ou pas, mais franchement je ne suis pas sur.
Pourquoi je te fais chier avec les vairiable global ? Tout simplement parceque elle sont allouer dans la RAM de ton ordi pendant TOUTE la duré du programme ! Certe, t'en as pas beaucoup ici, mais quand tu bossera sur des grosses appli, tu sera dégouter de voir qu'elle utilise 60% de la RAM !
Quelques règles que tu n'as pas utiliser (enfin je ne crois pas) :
-regles des 50 coup, prise en passant etc ...
Voila j'espere que j'ai été explicite !
Sinon je te félicite ! Continu ! moi j'adore la programmation d'échecs! et j'aimerais en voire encore plus !!!!!
Bon courage !
25 oct. 2004 à 13:05
25 oct. 2004 à 11:02
25 oct. 2004 à 08:11
24 oct. 2004 à 13:35
24 oct. 2004 à 10:21
4.1 Chaque coup doit être effectué d'une seule main.
4.2 A la condition qu'il exprime son intention (par exemple en disant ??j'adoube?? ou « je rectifie »), le
joueur ayant le trait peut rectifier la position d'une ou de plusieurs pièces sur leur case.
4.3 Sous réserve de l'article 4.2, si le joueur ayant le trait touche délibérément sur l'échiquier :
a) une ou plusieurs de ses propres pièces, il doit bouger la première pièce touchée qui peut être
bougée ou prise, ou
b) une ou plusieurs pièces adverses, il doit capturer la première pièce touchée qui peut l'être.
c) une pièce de chaque couleur, il doit capturer la pièce adverse avec sa pièce ou, si c'est illégal,
bouger ou prendre la première piècetouchée quipeut être bougée ou prise.Si la situation n'est pas claire et
qu'on ne peut établir si c'est la propre pièce du joueur ou celle de l'adversaire qui a été touchée la première,
on considérera que la propre pièce du joueur aura été touchée avant celle de son adversaire.
4.4 a) Si un joueur touche délibérément sa tour et son roi, il doit roquer de ce côté si c'est légal.
b) Si un joueur touche délibérément une tour et ensuite son roi, il n'est pas autorisé à roquer de ce
coté lors de ce coup et l'on réglera alors ce cas selon l'article 4.3 a.
c) Si un joueur ayant l'intention de roquer touche d'abord le roi ou le roi et la tour simultanément, alors
que le roque de ce coté est impossible, il doit choisir soit de roquer de l'autre coté, pour autant que ce roque
soit possible, soit de déplacer le roi. Si le roi ne peut être bougé, le joueur est libre d'effectuer n'importe quel
autre coup possible.
4.5 Si aucune des pièces touchées ne peut être bougée ou prise, le joueur peut alors effectuer n'importe
quel autre coup possible.
4.6 Si l'adversaire enfreint l'article 4.3 ou 4.4, le joueur ne peut réclamer s'il a lui-même délibérément
touché une pièce.
4.7 Quand, lors d'un coup légal ou comme faisant partie d'un coup légal, une pièce a été lâchée sur une
case, elle ne peut être déplacée sur une autre case. On considère le coup exécuté lorsque toutes les
conditions de l'article 3 ont été respectées.
24 oct. 2004 à 09:54
il me semble que c'est plutôt pièce posée pièce jouée mais si tu la garde en main sans la poser, ce n'est pas jouer .
24 oct. 2004 à 09:45
Sinon pour les variables, étant novices, si vous avez des propositions, sinon je verrai pour arranger ca.
24 oct. 2004 à 08:24
Sinon, je trouve qu'il y a bcp de variables globales, je sais pas si elle servent toutes mais çà fait un paquet .