Ben justement tout dépend. Dans mon cas c'est l'utilisateur qui rentre le nombre donc tous les nombres n'ont pas une équiprobabilité d'apparaître. Une étude de comportementalisme sur l'utilisateur dans ce cas là.
J'adore ! xD
Non je ne pense pas que cela serve à quelque-chose ... Une simple dichtonomie serra suffisant ...
En effet, si on se base sur la psycologie humaine, il faudra considéré que certains nombres ont peu de chance d'apparaitre ... Or si l'utilisateur desside d'utiliser un générateur de nombre aléatoire ou si simplement l'utilisateur choisie un nombre qu'il n'avait que peu de chance de choisir, le pire des cas serra alors certainement pire que par une simple dichotnomie ...
Mais ta remarque est tout simplement awesome ...
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles- ♡ Copying is an act of love.
En fait par IA par apprentissage je voulait faire un truc simple. Simplement pouvoir contrer le fait que l'utilisateur entre un nombre dur à trouver à chaque fois. Ainsi s'il avait entré une suite de nombre répétée plusieurs fois j'aurais été en mesure de deviner la suite. Bien sûr dans les cas où le programme ne voit rien de spécial il fait une simple dichotomie.
<troll>
@@ache (je déteste faire des @machinchose avec toi... ) : Je ne voit pas ton avatar et pourtant mon navigateur est à jour c'est normal docteur ? Ah ? Le 56k joue là dessus ? Ah ? Ma connexion est tellement pourrie que j'ai pas pû charger ton avatar ? </troll>
En fait par IA par apprentissage je voulait faire un truc simple. Simplement pouvoir contrer le fait que l'utilisateur entre un nombre dur à trouver à chaque fois. Ainsi s'il avait entré une suite de nombre répétée plusieurs fois j'aurais été en mesure de deviner la suite. Bien sûr dans les cas où le programme ne voit rien de spécial il fait une simple dichotomie.
:s Je reste quand même sur ma faim niveau interet et complexité ... On y perd plus qu'on ne gagne ... Le gain me semble assez faible ...
Citation : tsunami33
<troll>
@@ache (je déteste faire des @machinchose avec toi... ) : Je ne voit pas ton avatar et pourtant mon navigateur est à jour c'est normal docteur ? Ah ? Le 56k joue là dessus ? Ah ? Ma connexion est tellement pourrie que j'ai pas pû charger ton avatar ? </troll>
Enfait, mon avatar est en svg un format qui n'est pas suporté sur les anciens navigateur ou certains navigateurs peu utilisés ... Si ton navigateur est à jour, je ne vois pas le problème ...
Mon avatar est plus léger que le tien ce n'est donc pas une question de taille
À mon avis, tu n'utilises pas un navigateur courrant ^^"
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles- ♡ Copying is an act of love.
Non mais tsunami ne cherche pas, à part si tu fais des études en psychologie, ton analyse ne me semble pas viable. À la limite, quand tu auras fait une dichotomie qui tourne bien ça sera déjà pas mal (y a pas à chercher plus loin AMHA). Après tu peux toujours t'inspirer des analyses du comportement humain (du genre quand on demande à quelqu'un de mettre des points au hasard dans une surface donnée, la distribution ne sera pas la même qu'un générateur aléatoire).
Mais là c'est plus du tout de la programmation ; ça sort carrément du cadre du plus ou moins, qui a pour objectif de construire un algorithme viable. Si l'utilisateur est idiot et qu'il rentre toujours le même nombre, bah tant pis pour lui quoi. Tu devrais te concentrer sur d'autres parties de ton code en fait.
du genre quand on demande à quelqu'un de mettre des points au hasard dans une surface donnée, la distribution ne sera pas la même qu'un générateur aléatoire
du genre quand on demande à quelqu'un de mettre des points au hasard dans une surface donnée, la distribution ne sera pas la même qu'un générateur aléatoire
notre algo interne jitter le rendu nativement
Désolé, mais j'ai pas compris ta phrase.... ("jitter" = fluctuation d'un signal ?)
C'est un terme en raytracing, quand tu dis que l'homme ne place pas les points comme un ordi etc. bah cette chose que tu as vu sur wikipedia (jl'avais vu aussi, je m'amuse à faire ce test des fois à des amis (et personne ne placera deux points côte à côte)) est utilisé en ray tracing, pour réparpiller des points aléatoirement mais selon une grille.
Si l'IA utilise la dichotomie(et que je suis l'utilisateur le plus méchant), je sais que l'IA commencera toujours par le milieu de l'intervalle où est définis le nombre mystère. En partant de ce principe, l'IA va mettre le plus de coups possibles pour trouver les extrémités de cette intervalle. Voilà comment on peux tricher et battre l'IA à tout les coups.
A mon avis dans le cas de tsunami, il faut savoir switcher entre étude du comportement pour le premier coup de l'IA, au deuxième coup utiliser la dichotomie, au troisième prendre un nombre au hasard dans l'intervalle où se trouve le nombre mystère et par la suite utilisé tout le temps la dichotomie.
Cette méthode peux être plus efficace que la dichotomie pur et dur si ton intervalle est grand.
Je suis un peu crevé. Si ce message est incompréhensible, faites le moi savoir.
-User:"Sais-tu où vont les mails de réclamation ?" -Admin:"/dev/null"
Faut pas abuser non plus, on est en train de parler d’une IA pour un Plus ou Moins. Si vous voulez y intégrer des aspects comportamentaux ultra-compliqués que même les chercheurs en robotique ils bossent encore dessus, allez-y, mais je préfère consacrer mon temps à des choses (relativement) plus utiles.
Et puis, je crois pas que ce soit faisable, en plus (que le comportement soit prévisible). C’est comme au poker, c’est du hasard complet (le programme ne pouvant pas lire sur le visage du joueur).
J’hésite, je me tâte, posté-je mon code ici, ou le déposé-je sur GitHub ? Il fait 10 fichiers de code et 1195 lignes, mais j’ai pas vraiment envie de créer un dépôt pour ça.
@che > C’est pas non plus ditchtonomie. Ni psycologie. Ni desside mais on s’en fout.
tsunami/koloce> Tu veux pas ajouter un module de gestion de vision par ordinateur, histoire de voir quelle tête fait l'utilisateur (sournois, interrogateur ?) aussi ?
#include "zPlus_main.h"
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_ttf.h>
/* Contexte global. */
Context gcontext;
/* Jeu. */
unsigned askTry
(PlayerDatas* player, unsigned min, unsigned max)
{
wprintf(L"[%ls] ", (player) ? player->name : IA_NAME);
/* Demande au joueur. */
if(player)
return askNum(L"Tentez un nombre : ");
/* Intelligence artificielle : dichotomie. */
else {
unsigned try = (min+max) / 2;
/* Un peu de sel, histoire de moins s’emmerder : écart aléatoire d’au
plus 1/5 de l’intervalle. */
try += (int)( rand() % (max-min+1) - (max-min)/2 ) / 5;
/* Parce qu’un type qui répond instantanément, c’est de la concurrence
déloyale. */
fflush(stdout); /* pour afficher le prompt sans attendre le nombre */
SDL_Delay(100 * (rand()%13 + 5));
/* Affichage pour simuler la saisie à l’écran. */
wprintf(L"%u\n", try);
return try;
}
}
void play
(unsigned mode, unsigned lvl, PlayerDatas* playerG, PlayerDatas* playerA)
{
const wchar_t* diffMsg[10] = {
[0]= L"Vous ne voulez pas plutôt jouer au morpion ?",
[1]= L"À petit joueur, petits nombres.",
[2]= L"Bonne partie !",
[3]= L"Vous prenez des risques, dites-donc.",
[4]= L"Vous en voulez encore ?!",
[5]= L"Puisse le hasard être avec vous.",
[6]= L"Je vous offre le café.",
[7]= L"Vous vous ennuyiez ?",
[8]= L"Quand je pense que certains travaillent…",
[9]= L"À l’année prochaine !"
};
unsigned max, ans, try;
unsigned knownMin, knownMax;
unsigned tries, optimaxTries;
Uint32 chrono;
/* Tirage des paramètres. */
max = ( lvl == 0 )
? choose(1, 1000000000, L"Maximum : ")
: _pow(10, lvl);
ans = ( mode == 2 )
? choose(0, max, L"Nombre mystère : ")
: alea(max);
wprintf( L"Le nombre mystère est entre 0 et %u. %ls\n",
max, diffMsg[_log10(max)] );
knownMin = 0;
knownMax = max;
tries = 0;
chrono = SDL_GetTicks();
do {
tries++;
/*wprintf(L"Intervalle : [[%u ; %u]].\n",
knownMin, knownMax);*/
try = askTry(playerG, knownMin, knownMax);
wprintf(
L" -> %u : c'est %ls.\n",
try,
(try < ans)
? L"plus"
: (try > ans)
? L"moins"
: L"ça"
);
if(try < ans && knownMin < try)
knownMin = try;
if(ans < try && try < knownMax)
knownMax = try;
} while(try != ans);
chrono = SDL_GetTicks() - chrono;
optimaxTries = _log2(max) + 1;
/* Affichage des résultats. */
wprintf(
L"La réponse était %u.\n"
L" coups : %u (pas plus de %u si vous êtes malin)\n"
L" score : %+i\n"
L" temps : %.2fs (%.2fs en moyenne par coup).\n\n",
ans,
tries,
optimaxTries, optimaxTries - tries,
chrono / 1000., chrono / 1000. / tries
);
/* Enregistrement et affichage des stats pour le niveau. */
if(playerG) {
playerG->levels[0].played ++;
if(lvl) {
updateLevelStats(playerG, lvl, tries, chrono);
printLevelStats(playerG, lvl);
}
}
}
/* Fonctions de menu : génération, destruction et procédures. */
Menu playerListMenu = {
generateStatMenu, destroyStatMenu, NULL,
L"Liste des joueurs :",
0, .n = 0
};
Menu playerMenu = {
NULL, NULL, &gcontext.mode,
L"Options des joueurs :",
1, 5,
{ { 0, L"Créer un profil", NULL, createPlayerProc },
{ 0, L"Changer de profil", &playerListMenu, NULL },
{ 0, L"Changer de profil (joueur 2)", &playerListMenu, NULL },
{ 0, L"Supprimer un profil", &playerListMenu, NULL },
{ 0, L"Retour au menu principal.", NULL, NULL } }
};
Menu statMenu = {
generateStatMenu, destroyStatMenu, NULL,
L"Statistiques des joueurs :",
0, .n = 0
};
Menu lvlMenu = {
NULL, NULL, NULL,
L"Difficulté :",
0, 6,
{ { 0, L"personnalisée (0 - n)", NULL, playProc },
{ 0, L"facile (0 - 10)", NULL, playProc },
{ 0, L"moyen (0 - 100)", NULL, playProc },
{ 0, L"difficile (0 - 1000)", NULL, playProc },
{ 5, L"de plus en plus fou ! (0 - 10^n)", NULL, playProc },
{ 0, L"Retour au menu principal.", NULL, NULL } }
};
Menu mainMenu = {
NULL, NULL, &gcontext.mode,
L"Menu principal & mode de jeu :",
0, 6,
{ { 0, L"IA (programme / programme)", &lvlMenu, NULL },
{ 0, L"solo (programme / joueur)", &lvlMenu, NULL },
{ 0, L"2 joueurs (joueur / joueur)", &lvlMenu, NULL },
{ 0, L"Statistiques.", &statMenu, NULL },
{ 0, L"Joueurs.", &playerMenu, NULL },
{ 0, L"Quitter le jeu.", NULL, NULL } }
};
void playProc
(unsigned lvl)
{
/* Joueur qui doit deviner (« Guesser »). */
PlayerDatas* playerG = ( gcontext.mode != 0 )
? gcontext.datas->players + gcontext.datas->player1
: NULL;
/* Joueur qui détient la réponse (« Answerer »). */
PlayerDatas* playerA = ( gcontext.mode == 2 )
? gcontext.datas->players + gcontext.datas->player2
: NULL;
play(gcontext.mode, lvl, playerG, playerA);
}
void createPlayerProc
(unsigned foo)
{
wchar_t buf[MAX_PLAYER_NAME+1];
wchar_t* p;
wprintf(L"Nom (max. %u caractères) : ", MAX_PLAYER_NAME);
fgetws(buf, MAX_PLAYER_NAME+1, stdin);
if( (p = wcschr(buf, L'\n')) )
*p = L'\0';
else
clearInput(stdin);
if(!*buf) {
fputws(L"Opération annulée.\n\n", stderr);
return;
}
addPlayer(&gcontext.datas, buf);
switchPlayer1Proc(gcontext.datas->nPlayers - 1);
}
void deletePlayerProc
(unsigned playerID)
{
deletePlayer(&gcontext.datas, playerID);
}
void switchPlayer1Proc
(unsigned playerID)
{
gcontext.datas->player1 = playerID;
wprintf( L"Bonjour %ls ! Vous êtes maintenant le joueur 1. :)\n",
gcontext.datas->players[playerID].name );
}
void switchPlayer2Proc
(unsigned playerID)
{
gcontext.datas->player2 = playerID;
wprintf( L"Bonjour %ls ! Vous êtes maintenant le joueur 2. d8)\n",
gcontext.datas->players[playerID].name );
}
void printPlayerStatsProc
(unsigned playerID)
{
printPlayerStats(gcontext.datas->players + playerID);
}
#define MAX_STATMENU_LABEL_SIZE (5 + MAX_PLAYER_NAME + 4 + 22)
void generateStatMenu
(Menu* m)
{
unsigned i;
for(i = 0; i < gcontext.datas->nPlayers; i++) {
if(!m->entries[i].label)
m->entries[i].label =
malloc((MAX_STATMENU_LABEL_SIZE+1) * sizeof(wchar_t));
if(!m->entries[i].label) {
fputws(L"Erreur mémoire : ", stderr);
perror(NULL);
exit(EXIT_FAILURE);
}
swprintf( m->entries[i].label, MAX_STATMENU_LABEL_SIZE+1,
L"[%lc] %-*ls parties jouées : %u",
(i == gcontext.datas->player1)
? L'1'
: (i == gcontext.datas->player2)
? L'2'
: L' ',
MAX_PLAYER_NAME,
gcontext.datas->players[i].name,
gcontext.datas->players[i].levels[0].played
);
m->entries[i].sub = NULL;
if(m == &statMenu)
m->entries[i].proc = printPlayerStatsProc;
else if(gcontext.mode == 2)
m->entries[i].proc = switchPlayer1Proc;
else if(gcontext.mode == 3)
m->entries[i].proc = switchPlayer2Proc;
else /* gcontext.mode == 4 */
m->entries[i].proc = deletePlayerProc;
}
m->entries[i].label = L"Retour au menu précédent.";
m->entries[i].sub = NULL;
m->entries[i].proc = NULL;
m->n = gcontext.datas->nPlayers + 1;
}
void destroyStatMenu
(Menu* m)
{
m->entries[--m->n].label = NULL;
while(m->n--) {
free(m->entries[m->n].label);
m->entries[m->n].label = NULL;
}
}
/* Main. */
int main
(int ac, char** av)
{
SDL_Thread* extraTh;
/* Initialisations absconses. */
srand(time(NULL));
setlocale(LC_ALL, "");
setConsoleOutputEncoding(1);
SDL_Init(/*SDL_INIT_VIDEO |*/ SDL_INIT_EVENTTHREAD);
//TTF_Init();
SDL_EnableUNICODE(1);
extraTh = SDL_CreateThread(extra, NULL);
if(!extraTh) {
fwprintf(stderr,
L"Erreur à la création du thread bonus."
L" La SDL nous dit (merci la SDL) : %s",
SDL_GetError()
);
}
/* Chargement du fichier de données. */
gcontext.datas = loadDatas();
SDL_WaitThread(extraTh, NULL);
/* Menu principal → déroulement du programme. */
menu(&mainMenu);
/* Fin du programme. */
setConsoleOutputEncoding(0);
//TTF_Quit();
SDL_Quit();
unloadDatas(gcontext.datas);
return EXIT_SUCCESS;
}
datas
#ifndef INCLUDED_ZPLUS_DATAS
#define INCLUDED_ZPLUS_DATAS
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
#include <errno.h>
#include <SDL/SDL.h> /* pour le type Uint32 */
#include "zPlus_utils.h"
#define DATAS_PATH "zPlus_datas.bin"
#define MAX_PLAYERS 9
#define MAX_PLAYER_NAME 31
#define DEFAULT_PLAYER_NAME L"<sans nom>"
#define IA_NAME L"<IA>"
/* Statistiques d’un joueur pour un niveau de difficulté. */
typedef struct {
unsigned played; /* nombre de parties jouées */
struct {
unsigned tries; /* nombre de coups */
Uint32 chrono; /* temps */
} total, /* nombres totaux toutes parties confondues */
min; /* meilleures performances atteintes pour une partie */
} PlayerLevelDatas;
/* Informations sur un joueur. */
typedef struct {
/* nom (ou pseudonyme) du joueur */
wchar_t name[MAX_PLAYER_NAME+1];
/* statistiques pour chaque niveau de difficulté ; la case [0] correspond au
total (et non au niveau « personnalisé »), et seul le nombre total de
parties est utilisé. */
PlayerLevelDatas levels[10];
} PlayerDatas;
/* Données de tous les joueurs. */
typedef struct {
unsigned nPlayers, /* nombre total de joueurs enregistrés */
player1, /* index du joueur 1 */
player2; /* index du joueur 2 */
PlayerDatas players[]; /* tous les joueurs enregitrés */
} Datas;
/* Structure des données dans le fichier binaire :
* [unsigned] nPlayers
* [unsigned] player1 (la dernière fois)
* [unsigned] player2 (la dernière fois)
* [PlayerDatas] players[nPlayers]
* Il doit y avoir au moins un joueur, le premier, le joueur « par défaut ».
*/
#define SIZEOF_DATAS_HEADER \
( sizeof(unsigned) + sizeof(unsigned) + sizeof(unsigned) )
Datas* createDatas
(Datas* old, int newPlayers);
Datas* loadDatas
(void);
void writeDatas
(const Datas* datas);
void unloadDatas
(Datas* datas);
void addPlayer
(Datas** pdatas, const wchar_t* name);
void deletePlayer
(Datas** pdatas, unsigned playerID);
void updateLevelStats
(PlayerDatas* player, unsigned lvl, unsigned tries, Uint32 chrono);
void printLevelStats
(PlayerDatas* player, unsigned lvl);
void printPlayerStats
(PlayerDatas* player);
#endif /* header not included */
#ifndef INCLUDED_ZPLUS_INTERACT
#define INCLUDED_ZPLUS_INTERACT
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include "zPlus_datas.h"
#ifdef _WIN32
#include <windows.h>
#endif
#define MAX_MENU_ENTRIES MAX_PLAYERS+1
void setConsoleOutputEncoding
(int set);
void clearConsole
(void);
void clearInput
(FILE* in);
unsigned askNum
(const wchar_t* msg);
unsigned choose
(unsigned min, unsigned max, const wchar_t* msg);
typedef struct Menu Menu;
/* Type de fonction utilisée pour générer un menu. */
typedef void (*MenuGenerator)(Menu*);
/* Type de fonction utilisée pour détruire un menu. */
typedef void (*MenuDestructor)(Menu*);
/* Type de fonction exécutée par une entrée de menu. */
typedef void (*MenuProc)(unsigned);
/* Menu. */
struct Menu {
MenuGenerator gen; /* (facultatif) fontion pour générer le menu */
MenuDestructor des; /* (facultatif) fontion pour détruire le menu */
unsigned* pchoice; /* (facultatif) adresse où écrire le choix */
wchar_t* title; /* le titre à afficher */
unsigned start; /* premier n° (si on veut démarrer à 1 ou à 0) */
unsigned n; /* le nombre d’entrées */
/* chaque entrée du menu : */
struct {
unsigned extent; /* plage supplémentaire de choix associés */
wchar_t* label; /* le texte affiché */
Menu* sub; /* l’action associée : un sous-menu … */
MenuProc proc; /* … ou une fonction (si `sub` est NULL) */
} entries[MAX_MENU_ENTRIES];
};
void menu
(Menu* menu);
#endif /* header not included */
Comme vous voyez, à la base je prévoyais de faire une version graphique avec SDL et SDL_TTF, mais finalement je garde la console. Mais je garde aussi les headers de la SDL pour utiliser ses threads et ses chronomètres (parce que clock() me donne des temps invraisemblables sous mon Linux).
J’ai fait exprès de faire hurler Lucas-84 (et Mr21 va bien se marrer avec mes fwrite). Dans une version future (le futur c’est pas forcément proche), j’utiliserais un truc plus mieux pour peaufiner l’interface, genre conio/ncurses.
Au programme :
− des bôôô menus, comme promis (mais à cause que c’est pas pratique à utiliser pour faire des croisements et tout et tout, voilà bien un beau plat de spaghettis) ;
− une IA enhanced ;
− le niveau 4 (gestion des profils avec stats et pseudos), manque un classement ;
− un code un peu à l’arrache, avec une organisation douteuse (mais c’est pas ma faute, le cadre d’édition de mon Vim est trop petit, j’arrive pas à avoir une vue d’ensemble).
( J’ai mis le bonus discuté en commentaire, ça tient en une instruction. )
Me reste quelques détails à améliorer (par exemple, la localisation du fichier binaire).
Le binaire pour Linux 32 bits, pour vous éviter de compiler :
Nan, je lol.
Édit : Ah oui, et comme je suis bordélique, il y a des anciens bouts de code en commentaires, des fois que je voudrais y revenir ou pour me faire penser à revoir cette partie. Et il y a aussi des modifications que j’ai commencé d’apporter mais qui ne sont pas finies donc qui ne servent à rien pour l’instant (dans les fonctions d’« interaction »).
Jusque-là, votre programme devrait prendre tout au plus 30 lignes.
Tout juste pour cette première épreuve. Voici son code :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int askNumber(short int random)
{
short int askedNumber;
printf("Quel est le nombre myst\x8Are : ");
scanf("%hd", &askedNumber);
if (askedNumber > random)
printf("C'est moins !\n\n");
else if (askedNumber < random)
printf("C'est plus !\n\n");
else
return 0;
return 1;
}
int main(void)
{
short int random;
srand(time(NULL));
random = rand() % 100;
while (askNumber(random));
printf("Bravo !\n");
return 0;
}
soit dit en passant, mon ordi m'a généré la réponse à la vie pour mon test :
Ici le code avec le bonus 1 (l'IA) :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
short int askNumber(short int random)
{
short int askedNumber = 0;
printf("Quel est le nombre myst\x8Are : ");
scanf("%hd", &askedNumber);
if (askedNumber > random)
printf("C'est moins !\n\n");
else if (askedNumber < random)
printf("C'est plus !\n\n");
else
return 0;
return 1;
}
void askNumberToIA(short int random)
{
short int testedNumber = 50;
short int min = 0, max = 100;
printf("l'ordinateur teste le nombre 50.\n");
while (testedNumber != random)
{
if (testedNumber < random)
{
printf("C'est plus !\n");
min = testedNumber;
testedNumber = (max + min) / 2;
}
else if (testedNumber > random)
{
printf("C'est moins !\n");
max = testedNumber;
testedNumber = (max + min) / 2;
}
printf("l'ordinateur teste le nombre %d.\n", testedNumber);
}
}
int main(void)
{
short int random = -1;
char choice = 0;
srand(time(NULL));
printf("Bienvenue dans plus ou moins.\n");
while (choice != 'a' && choice != 'b')
{
printf("Choisissez le mode de jeu d\x82sir\x82 :\n");
printf("a : C'est vous qui devinez !\n");
printf("b : C'est l'ordinateur qui devine !\n");
choice = getchar();
if (choice != 'a' && choice != 'b')
printf("Veuillez entrer un choix valide.\n");
}
if (choice == 'a')
{
random = rand() % 100;
while (askNumber(random));
printf("Bravo !\n");
}
else
{
printf("Veuillez entrer le nombre que l'ordinateur devra deviner : ");
while (random < 0 || random >= 100)
{
scanf("%hd", &random);
if (random < 0 || random >= 100)
printf("Veuillez entrer un nombre entre 0 et 100.\n");
}
askNumberToIA(random);
printf("L'IA a trouv\x82 le nombre.\n");
}
return 0;
}
Voici maintenant le code lvl 2 (sans le bonus) :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef __WIN32__
#define clear() system("cls")
#else
#define clear() system("clear")
#endif
void playerTry(short int mystery);
void IATry(short int mystery, int max);
int powTen(short int puissance);
short int numberQuery();
char characterQuery();
int main(void)
{
char choice = 0, max = 0;
srand(time(NULL));
printf("Bienvenue dans plus ou moins.\n");
while (choice != 'n')
{
while (choice < 'a' || choice > 'd')
{
printf("Choisissez le mode de jeu d\x82sir\x82 :\n");
printf("a : C'est vous qui devinez !\n");
printf("b : C'est l'ordinateur qui devine !\n");
printf("c : Mode deux joueurs.\n");
printf("d : quitter\n");
choice = characterQuery();
if (choice < 'a' || choice > 'd')
printf("Veuillez entrer un choix valide.\n");
}
if (choice >= 'a' || choice <= 'c')
{
while (max < 'a' || max > 'd')
{
printf("Veuillez entrer un niveau de difficult\x82 :\n");
printf("a : Tr\x8As facile (entre 0 et 9)\n");
printf("b : Facile (entre 0 et 99)\n");
printf("c : Interm%lcdiaire (entre 0 et 999)\n", 130);
printf("d : Difficile (entre 0 et 9999)\n");
max = characterQuery();
if (max < 'a' || max > 'd')
printf("Veuillez entrer un choix valide.\n");
}
}
switch (choice)
{
case 'a':
playerTry(rand() % powTen(max - 'a' + 1));
break;
case 'b':
printf("Veuillez entrer le nombre que l'ordinateur devra deviner : ");
IATry(numberQuery(powTen(max - 'a' + 1)), powTen(max - 'a' + 1));
break;
case 'c':
printf("Veuillez entrer le nombre que le joueur 2 devra deviner : ");
playerTry(numberQuery(powTen(max - 'a' + 1)));
break;
default:
choice = 'n';
break;
}
while (choice != 'o' && choice != 'n')
{
printf("Voulez vous rejouer ? (o/n)\n");
choice = characterQuery();
if (choice != 'o' && choice != 'n')
printf("Veuillez entrer o pour oui ou n pour non.\n");
}
}
return 0;
}
void playerTry(short int mystery)
{
short int askedNumber = 0;
while (askedNumber != mystery)
{
printf("Quel est le nombre myst\x8Are : ");
scanf("%hd", &askedNumber);
if (askedNumber > mystery)
printf("C'est moins !\n\n");
else if (askedNumber < mystery)
printf("C'est plus !\n\n");
}
printf("Bravo !\n\n");
}
void IATry(short int mystery, int max)
{
int testedNumber = max / 2;
int min = 0;
printf("l'ordinateur teste le nombre %d.\n", testedNumber);
while (testedNumber != mystery)
{
if (testedNumber < mystery)
{
printf("C'est plus !\n");
min = testedNumber;
testedNumber = (max + min) / 2;
}
else if (testedNumber > mystery)
{
printf("C'est moins !\n");
max = testedNumber;
testedNumber = (max + min) / 2;
}
printf("l'ordinateur teste le nombre %d.\n", testedNumber);
}
printf("L'IA a trouv\x82 le nombre.\n\n");
}
int powTen(short int puissance)
{
int number;
for (number = 1 ; puissance ; puissance --)
number *= 10;
return number;
}
short int numberQuery(int max)
{
short int number = -1;
while (number < 0 || number >= max)
{
scanf("%hd", &number);
while (getchar() != '\n');
clear();
if (number < 0 || number >= max)
printf("Veuillez entrer un nombre entre 0 et %d.\n", max-1);
}
return number;
}
char characterQuery()
{
char character;
character = getchar();
while (getchar() != '\n');
clear();
return character;
}
Et avec le bonus :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef __WIN32__
#define clear() system("cls")
#else
#define clear() system("clear")
#endif
void playerTry(int mystery);
void IATry(int mystery, int max);
int powTen(int puissance);
int getInterval(int mystery);
int numberQuery();
char characterQuery();
int main(void)
{
char choice = 0, max = 0;
int mystery;
srand(time(NULL));
printf("Bienvenue dans plus ou moins.\n");
while (choice != 'n')
{
while (choice < 'a' || choice > 'd')
{
printf("Choisissez le mode de jeu d\x82sir\x82 :\n");
printf("a : C'est vous qui devinez !\n");
printf("b : C'est l'ordinateur qui devine !\n");
printf("c : Mode deux joueurs.\n");
printf("d : quitter\n");
choice = characterQuery();
if (choice < 'a' || choice > 'd')
printf("Veuillez entrer un choix valide.\n");
}
if (choice == 'a')
{
while (max < 'a' || max > 'd')
{
printf("Veuillez entrer un niveau de difficult\x82 :\n");
printf("a : Tr\x8As facile (entre 0 et 9)\n");
printf("b : Facile (entre 0 et 99)\n");
printf("c : Interm%lcdiaire (entre 0 et 999)\n", 130);
printf("d : Difficile (entre 0 et 9999)\n");
max = characterQuery();
if (max < 'a' || max > 'd')
printf("Veuillez entrer un choix valide.\n");
}
}
switch (choice)
{
case 'a':
playerTry(rand() % powTen(max - 'a' + 1));
break;
case 'b':
printf("Veuillez entrer le nombre que l'ordinateur devra deviner : ");
mystery = numberQuery(10000);
printf("Le nombre \xE0 deviner est entre 0 et %d.\n", getInterval(mystery));
IATry(mystery, getInterval(mystery));
break;
case 'c':
printf("Veuillez entrer le nombre que le joueur 2 devra deviner : ");
mystery = numberQuery(10000);
printf("Le nombre \xE0 deviner est entre 0 et %d.\n", getInterval(mystery));
playerTry(mystery);
break;
default:
choice = 'n';
break;
}
while (choice != 'o' && choice != 'n')
{
printf("Voulez vous rejouer ? (o/n)\n");
choice = characterQuery();
if (choice != 'o' && choice != 'n')
printf("Veuillez entrer o pour oui ou n pour non.\n");
}
}
return 0;
}
void playerTry(int mystery)
{
int askedNumber = 0;
while (askedNumber != mystery)
{
printf("Quel est le nombre myst\x8Are : ");
scanf("%d", &askedNumber);
if (askedNumber > mystery)
printf("C'est moins !\n\n");
else if (askedNumber < mystery)
printf("C'est plus !\n\n");
}
printf("Bravo !\n\n");
}
void IATry(int mystery, int max)
{
int testedNumber = max / 2;
int min = 0;
printf("l'ordinateur teste le nombre %d.\n", testedNumber);
while (testedNumber != mystery)
{
if (testedNumber < mystery)
{
printf("C'est plus !\n");
min = testedNumber;
testedNumber = (max + min) / 2;
}
else if (testedNumber > mystery)
{
printf("C'est moins !\n");
max = testedNumber;
testedNumber = (max + min) / 2;
}
printf("l'ordinateur teste le nombre %d.\n", testedNumber);
}
printf("L'IA a trouv\x82 le nombre.\n\n");
}
int powTen(int puissance)
{
int number;
for (number = 1 ; puissance ; puissance --)
number *= 10;
return number;
}
int getInterval(int mystery)
{
int i;
for (i = 10 ; i < mystery ; i *= 10);
return i;
}
int numberQuery(int max)
{
int number = -1;
while (number < 0 || number >= max)
{
scanf("%d", &number);
while (getchar() != '\n');
clear();
if (number < 0 || number >= max)
printf("Veuillez entrer un nombre entre 0 et %d.\n", max-1);
}
return number;
}
char characterQuery()
{
char character;
character = getchar();
while (getchar() != '\n');
clear();
return character;
}
Tsunami > Ça sert à rien les entiers courts ici, utilise des int, comme tout le monde. Attention que getchar renvoie un int (et que se passe-t-il si la valeur de retour est EOF ?). Tu as pleins de nombres en dur et d'affichage dans tes fonctions. Et puis, bon, je ne vais pas parler de l'EBCDIC, sinon je vais me faire engueuler.
C’est pas ma faute alors, mon programme compilé à moi s’appelle ./zPlus.
Citation : Lucas-84
Tsunami > […] Et puis, bon, je ne vais pas parler de l'EBCDIC, sinon je vais me faire engueuler.
Si si, il faut en parler. Enfin, pas l’EBCDIC, en s’en fout (même moi, c’est dire), mais le coup du "\x82" pour la lettre « é », c’est moisi. Parce que plutôt que d’indiquer au compilo « donne-moi le caractère “é” dans l’encodage du système », tu lui demandes « donne-moi le caractère qui vaut 0x82 dans l’encodage du système ».
Ça change tout parce que le caractère correspondant à ce code peut varier entre deux systèmes. Par exemple, chez toi ça donne le caractère « ‚ » (si si, je t’assure, ton Windows utilise sûrement l’encodage Windows-1252, sauf que la console utilise encore par défaut un encodage plus vieux, CP850, dans lequel 0x82 correspond à « é » — comme tu vois, en fait c’est doublement moisi). Mais sous Linux, ça peut ne rien donner du tout, ce code ne correspondant pas à un caractère (jeu latin-1 ou Unicode).
Si tu avais écrit "é", le compilo aurait traduit (depuis l’encodage de ton fichier source) pour obtenir le même caractère dans l’encodage du système. N’importe quel compilateur un tant soit peu moderne accepte maintenant les accents dans le code source (au moins depuis C99).
Pourquoi jouer avec les overflow dans utils ? Un overflow c'est un undefined behavior.
Tu parles de moi avec mes logarithmes ?
Les dépassements de capacité sont implementation-defined dans le cas des entiers signés, mais pour les non-signés la norme nous garantit le wrap around.
Si tu avais écrit "é", le compilo aurait traduit (depuis l’encodage de ton fichier source) pour obtenir le même caractère dans l’encodage du système. N’importe quel compilateur un tant soit peu moderne accepte maintenant les accents dans le code source (au moins depuis C99).
De manière générale, il vaut mieux ne placer que les caractères du jeu de caractère source de base dans les chaîne littérales. En revanche, il est possible de placer des caractères du jeu étendu dans les chaîne littérales larges si l'on est certains que le jeu de caractère d'exécution large du système les comprends.
Citation : tsunami33
Code Blocks ne le fait pas...
Si MinGW en est capable, il faut juste utiliser les bonnes options de compilation et bien encoder ses fichiers sources
N’importe quel compilateur un tant soit peu moderne accepte maintenant les accents dans le code source (au moins depuis C99).
Code Blocks ne le fait pas...
On a dit "moderne" ...
Si je me souviens bien, le comilo de base de C:B est mingw32 non à jour ...
Ça dépend si tu utilise les nigthly-build ou non. Moi j'ai pris la dernière version et j'ai pleins d'améliorations. Par contre, i lest impossible de mettre des accents, sans doute parce que c'est un logiciel anglophone (j'ai pourtant encodé mes fichiers en UTF-8).
[…]
De manière générale, il vaut mieux ne placer que les caractères du jeu de caractère source de base dans les chaîne littérales. En revanche, il est possible de placer des caractères du jeu étendu dans les chaîne littérales larges si l'on est certains que le jeu de caractère d'exécution largeétendu du système les comprend.
Je ne vois pas pourquoi on ferait cette restriction pour char mais pas pour wchar_t. Après tout, les char* peuvent contenir des caractères multibytes correspondant à certains caractères étendus (lesquels exactement dépend en théorie de la locale). Si on est également certain que le jeu de base contient le caractère qu’on veut, ou qu’il sera associé à une séquence multibyte, on peut aussi l’écrire directement.
Pis de toute façon, si le caractère qu’on veut n’existe pas dans le jeu d’exécution, qu’on l’écrive directement ou pas, ça ne changera rien.
À la rigueur, pour éviter les caractères non-ASCII dans le code source, on peut utiliser la syntaxe \uXXXX pour spécifier le point de code Unicode, mais bon c’est moins lisible et pratique. Et si on encode son code source en UTF-8 (encodage source par défaut pour GCC), on ne devrait pas en avoir besoin.
Citation : informaticienzero
Par contre, il est impossible de mettre des accents, sans doute parce que c'est un logiciel anglophone (j'ai pourtant encodé mes fichiers en UTF-8).
Encore une fois, comment ça c’est impossible ? Rien ne se passe si on appuie sur la touche « é » ?
Citation : Pouet_forever
Maëlan > oé, mais je trouve ça un peu bête de jouer avec les overflow.
C’est pas bête, c’est élégant. Tu comprends rien à l’art.
Effectivement je suis dans un encodage bien pourri : Windows-1252.
Je vais essayer de pouvoir mettre les accents direct dans le code source mais j'aime pas trop ça mettra des ù chez les gens qui n'ont pas réglé leur IDE. Je préfère utiliser le code unicode à la rigueur.
EDIT : Quelqu'un saurait comment régler code blocks pour qu'il compile en C99 ? Parce que là j'ai un warning quand je met \uXXXX :
warning: universal character names are only valid in C++ and C99
en plus ça ne donne même pas l'accent désiré mais un caractère bizarroïde.
Effectivement je suis dans un encodage bien pourri : Windows-1252.
Je vais essayer de pouvoir mettre les accents direct dans le code source mais j'aime pas trop ça mettra des ù chez les gens qui n'ont pas réglé leur IDE. Je préfère utiliser le code unicode à la rigueur.
Non, le problème n’est pas là : avec le code Unicode (U+00E9), tu obtiendras le même résultat puisque le compilo traduit ce caractère dans l’encodage du système, donc Windows-1252 (au passage il a la même valeur en Unicode et en Windows-1252).
Comme je l’ai dit tout à l’heure (comment ça je deviens pédant ?), ce « Ú » vient en fait de ce que la console Windows utilise par défaut un encodage plus vieux et plus pourrite encore, j’ai nommé CP850. Dans cet page de code, 0xE9 est le caractère « Ú », d’où l’affichage moisi.
J’ai bien dit « par défaut ». Heureusement, il y a FindUsSetConsoleOutputCP dans l’API Windows.
Note : À partir de Vista, setlocale(LC_ALL,"") donne le même résultat, cf.ici.
Édit : Pour ton problème de configuration de Code::Blocks, je ne sais pas s’il y a une option exprès pour, mais sinon tu vas dans les options de compilation (les paramètres passés au compilo) et tu rajoutes le paramètre -std=c99 (si ton compilo est MinGW).
Par contre, il est impossible de mettre des accents, sans doute parce que c'est un logiciel anglophone (j'ai pourtant encodé mes fichiers en UTF-8).
Encore une fois, comment ça c’est impossible ? Rien ne se passe si on appuie sur la touche « é » ?
Tu as bien la lettre 'é' qui s'affiche dans ton code source, mais la compilation plante. Je n'ai plus l'erreur en tête car je ne suis pas sous Windows, mais dès que j'y retourne et je teste. Je crois que c'est une erreur du type "invalide UTF-8 sequence".
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles - ♡ Copying is an act of love.