Bonjour,
voila je debute la programation et je tente de faire un snake en langage C. J'ai presque fini a coder le l'orientation du serpent mais je ne sais pas comment faire qu'il avance à l'infini :s pourriez vous me donner des indications
Merci
ps: le tuto de jv.com n'est pas interessant
ps j'ai trouvé comment faire avancer le serpent sans ta méthode mais le nouveau problème sur lequel je dois bucher c'est d'employé les tableaux pour les coordonnées de chaque membre du serpent en sachant qu'il faut ajouter 2 cases des qu'il mange une pomme (c'est surtout ca qui me pose problème) j'ai penser initialiser le début du tableau avec les coordonnées initiales du serpent et mettre toutes les autres cases a -1 tant que le serpent n'a pas manger de pomme mais c'est pas très clair dans ma tête x)
Je pense pas que le tableau évolue en fonction des pommes mangées mais plutôt en fonction de la position de chaque tronçon du serpent. Dans le principe, à chaque mouvement tu remets l'élément du tableau contenant le bout du serpent à false, tandis que tu mets l'élément du tableau contenant la tête à true.
Et quand tu manges une pomme, pendant deux tours de boucle, tu ne mets pas la queue à false, mais tu continue de mettre à tête à true.
hum okay mais comment je me sers de true et false
Quoi ? Un tableau alors que ce serait tellement plus facile avec une liste chainée ? ![]()
Les valeurs true et false sont une notion de c++ (type booléen) ça remplace 1 et 0 pour économiser de la mémoire et gagner en lisibilité. je pense qu'une liste chainée est vraiment l'idéal pour implémenter un snake (et c'est ce qui doit être utilisé d'ailleurs). Parce que sinon, tu dois analyser le tableau tout le temps pour parcourir le serpent et c'est encore plus chiant. ![]()
tableau d'entier.
0 vide
1 pomme
2 vert
3 tete du vert
c'est du case par case donc en tableau ton snake est directement fait. tu peux facilement modifier seulement les case modifier avec l accès direct et pour l affichage juste a faire corespondre un nombre a un .png
0 > case noir
1 > case verte
2 > case rouge
3 > case jaune
Un tableau d'entier? un tableau de caractère évite de gâcher de precieux octets de mémoire vive. ![]()
Vu la taille de nos machines, avons nous réellement besoin d'économiser les octets?
Je pense qu'il faut favoriser dans un premier temps un code qui fonctionne puis un code propre (qui fonctionne toujours) et on optimise que si c'est réellement nécessaire ;)
Je ne peux que recommander le livre "Clean Code / Coder Proprement"
"Un tableau d'entier? un tableau de caractère évite de gâcher de precieux octets de mémoire vive. "
dans ce cas la tu peux encore faire bien mieux. stocker une structure ne contenant que 4 boolean.
et tu passe de 8bit/case à 4bit/case.
et après tu peux encore faire mieux en ne stockant que 2 boolean. puisque avec 2 bolean tu peux compter jusqu a 3
soit passé a 2bit/case
mais sincerement la n'est pas vraiment la question après tout ca c'est très secondaire. et en plus ca n'améliore pas forcément les choses.
Un boleen est stocké sur un octet, tout comme un caractère et ils n'existent pas de base en C. ![]()
comme dit par neofungamer, Ca n'a aucun interet de faire ce genre de chose. On a amplement assez de memoire pour stocker les chses explicitement en memoire. Si jamais on en avait pas assez, alors on ferait un peu plus de compression.
On utiliserai alors peut etre le construct : du C
struct foo
{
int a :1;
int b :1;
int c :1;
int d :1;
};
ici chaque int ne prends qu'un bit et ainsi "sizeof (struct foo) == 1".
Mais comme il a ete remarque plus haut, on peut compresser sur 2 bits par case. On feraait alors de l'indirection et des bit mask pour stocker 4 case par octets.
Mais encore une fois. on ne manque pas de place ici...
Non mais bien sûr qu'on en a rien à faire de perdre un peu de mémoire. J'essayais juste d'embêter acemicka qui continuait à appuyer le modèle du tableau à deux dimension (qui nécessitera des pointeurs de toutes façons), alors que (et c'est purement personnel) je préfère une approche où l'on ne stocke que ce dont on a besoin : la liste des positions du serpent et éventuellement une liste avec les positions des objectifs. Ça évite une analyse de la forme du serpent, ça augmente la vitesse d'affichage (et ça c'est important), ça économise de la mémoire et ça tourne plus vite.
Je suis pas chiant, j'appelle à la réflexion algorithmique et c'est tellement intéressant. ![]()
Et sinon, vu que vous avez tous marché dans mon troll, sachez qu'en C :
-La taille des variables s'exprime en octets et non en bits. Donc godrik, dans ton code avec "int a:1;" tu alloue un octet et non un bit. ![]()
-La taille minimale d'une variable est d'un octet à cause de l'accès à la mémoire qui se fait par groupements de 8bit. Donc un booléen fait un octet.
Vos méthodes d'optimisation "extreme" sont inutiles vu que vous multipliez les variables.
Si vous voulez faire du 1bit/variable, il faut programmer un transcodeur binaire pour stocker et lire 8 "booleen" sur une seule variable d'un octet. ![]()
Après quelques recherches godrik a tout à fait raison, au temps pour moi. ![]()
"Quoi ? Un tableau alors que ce serait tellement plus facile avec une liste chainée ? "
proposer une liste chainer a un débutant bof...
déja niveau perf en lecture c'est super lent.
meme pour des petit jeux.
pas trop de rappel de C mais liste chainé il faut faire très attention au acces ne pas modifier et lire en meme temp la chaine. ca peut etre un probleme quand le serpent devient long et bouge rapidement (rafraichissement toutes les 13ms pour un jeux a 60FPS). surtout en programmation paralele quand l'affichage et le model ne sont pas dans le meme process. le temp de lire un snake en entier peut etre long, et si ce temp est trop long et que d'un coup le serpent mange une pomme et grandi tu te retrouve a lire et modifié ta chaine en meme temp. donc ca rajoute plein de controle et de choses qui complique pour tenter de gagner quelque octect.
alors qu a tableau en 1 heure ton jeux est fait et fonctionnel et tu sais que les perf seront là et surtout ne dépendront pas de la taille du serpent mais seront fix en tout temp.
en plus en tableau lorsque tu sérialize tu peux sauvegarder tout le niveau par exemple imaginer des mur etc. donc faire un editeur de niveau. et meme proposer des interrupteur qui déplace les murs pendant que tu joue pour créé des pieges de facon simple etc. et sauvegarder a n'importe quel momment ton jeux juste en serializant ton tableau dans un fichier.
alors certe un vrai snake sur mobile par exemple devrait utiliser des liste chainée du au contrainte de la plateform mais sur PC c'est ce compliqué pour rien et empécher l'évolution du jeux vers des choses fun en utilisant quelque chose de très limité sur les acces en lecture.
sur mobile tu ferrai une liste chainé pour les pommes et une liste chainé ajout en fin pour le serpent. pour que la tete soit toujour accesible en get(0).
d'ailleur a cause de la colision avec lui meme et plein de test en lecteur on n'utiliserai meme pas de list chainé mais des tableau chainé. les listes seraient bcp trop lente a mon sens.
En attendant, il peut toujours essayer avec un tableau à deux dimensions, mais je soutiens que c'est une mauvaise idée car il va se heurter à un problème assez sournois mais évident et assez dur à contourner... xD
acemicka, qui a parle de programmation parallele ? Et de toute facon que tu accede a un tableau ou a une liste chaine, si tu le fais en parallele, il faut la proteger!
acemicka> Trouve moi un moyen simple (accessible par un débutant) et codable en 1h avec réflexion comprise d'interpréter la position du serpent d'après cette image (après ou avant sauvegarde) : http://lsd4people.org/serpent.png
Et les listes chainées sont accessibles dans des librairies quasi standards comme Boost. Leur utilisation se limite à deux appels de fonction différents. La lecture et l'écriture ne posent donc aucun problème. On ne parles pas ici de programmation en multithreading, loin de là.