Programmer en C sous Linux

Introduction

Cet article n'est pas un cours sur le langage C mais récapitule l'ensemble des paquets à installer sous Linux Ubuntu pour bénéficier d'un environnement de développement performant en langage C, avec compilateur en ligne de commande, accès aux bibliothèques et aux services du système, ainsi que l'utilisation de certaines API particulières (Gtk+, Gnome, OpenGL, etc.).

L'objectif de cette page est d'apporter des solutions et des explications aux différents problèmes rencontrés lors de la compilation d'un code source en C sous Linux. Si vous rencontrez un problème de compilation pas encore mentioné sur cette page vous pouvez m'écrire à l'adresse jc.michel@gecif.net.

Sommaire de cette page

Premier programme en C

Utilisation des librairies dynamiques du système

Utilisation de GDK

Utilisation de GTK+

Utilisation de Gnome

Utilisation de OpenGL

 

Retour en haut de la page

Premier programme en C pour tester le compilateur GCC

Editons un nouveau fichier texte dans Gedit nommé toto.c :

gedit toto.c

Voici le code source en C de ce premier programme qui se contente d'afficher "Bonjour" sur la sortie standard :

#include <stdio.h>

int main()
{
printf("Bonjour\n");
}

Compilons le programme source toto.c en utilisant le copilateur gcc en ligne de commande :

gcc toto.c

Remarques :

Exécutons le programme a.out :

./a.out

 

Retour en haut de la page

Compilation d'un programme en C utilisant une librairie particulière

Voyons comment utiliser les API GDK, GTK+, Gnome et OpenGL. Chacune des ces API est composée d'un ensemble de fichiers de librairies dynamiques (fichiers .so disponibles dans le répertoire /urs/lib) et d'un ensemble de fichiers d'en-tête (fichiers .h disponibles dans le répertoire /usr/include).

Le programme pkg-config exécutable en ligne de commande sous Linux permet de connaître la configuration de chacune des librairies installées dans le système (version, chemin d'accès au fichiers .so et aux fichier .h, etc.). La commande pkg-config --list-all donne l'ensemble des librairies pouvant être utiliser dans un programme.

API :
GDK
GTK+
Gnome
OpenGL
Fichier d'en-tête :
gdk.h
gtk.h
gnome.h
glut.h
Répertoire du fichier d'en-tête dans /usr/include/ :
/gtk-2.0/gdk/gdk.h
/gtk-2.0/gtk/gtk.h
/libgnomeui-2.0/gnome.h
GL/glut.h
Nom de la librairie à utiliser pour pkg-config :
gdk-2.0
gtk+-2.0
libgnomeui-2.0
gl glu glut
Paquet .deb à installer dans Ubuntu 10.04
libdtk2.0-dev
libdtk2.0-dev
libgnomeui-dev
freeglut3-dev

Procédure à suivre pour utiliser une API particulière :

gcc toto.c $(pkg-config --cflags --libs nom_librairie)

La documentation des différentes librairies est installable grâce aux paquets .deb xxxxxxx-doc et est disponible dans les répertoires /usr/share et /usr/share/doc.

Le tableau suivant indique le nom du paquet .DEB à installer dans Ubuntu afin de pouvoir utiliser une bibliothèque particuilière dans votre environnement de développement en langage C :

Fonction réalisée, bibliothèque ou API :
Fichier d'en-tête :
Paquet .deb à installer dans Ubuntu 10.04
GDK
gdk.h
libdtk2.0-dev
GTK+
gtk.h
libdtk2.0-dev
Gnome
gnome.h
libgnomeui-dev
OpenGL
glut.h
freeglut3-dev
création d'une interface utilisateur en mode texte
ncurses.h
libncurses5-dev
Glib
glib.h
libglib2.0-dev
affichage d'une image jpeg
jpeglib.h
libjpeg62-dev
affichage d'une image tiff
tiffio.h
libtiff4-dev
LibXML2
tree.h
libxml2-dev
Zlib
zlib.h
zlib1g-dev
calcul en haute précision
mpc.h
libmpc-dev
PCRE (Perl Compatible Regular Expressions)
pcre.h
libpcre3-dev
Regex (support d'expressions régulières)
regex.h
libc6-dev
fonctions mathématiques
math.h
libc6-dev
date et heure
time.h
libc6-dev
gestion des chaînes de caractères
string.h
libc6-dev
fonctions standards
stdlib.h
libc6-dev
fonctions d'entrèe/sortie
stdio.h
libc6-dev
fonctions réseau
socket.h
libc6-dev
fonctions réseau
inet.h
libc6-dev
fonctions réseau
in.h
libc6-dev
gestion des erreurs
errno.h
libc6-dev
  gestion des threads, des processus et des mutex
pthread.h
libc6-dev
Communication Inter Processus (IPC)
ipc.h
libc6-dev
envoyer un signal
signal.h
libc6-dev
utilisation des sémaphores
sem.h
libc6-dev
branchements non locaux
setjmp.h
libc6-dev
création d'une table de hachage
search.h
libc6-dev

Le programme apt-file permet de savoir à quel paquet .DEB appartient un fichier donné. Le tableau précédent a été réalisé grâce à une série de commandes sur le modèle suivant :

apt-file search nom_du_fichier_d_en_tete_a_rechercher

Le programme apt-file permet également de connaître l'ensemble des fichiers installé grâce à un paquet donné. Par exemple pour obtenir la liste de tous les fichiers d'en-tête .h installé par la librairies standard libc6-dev la commande est la suivante :

apt-file list libc6-dev | grep \\.h

Et le résultat est une liste de 386 fichiers d'en-tête .h :

libc6-dev: /usr/include/_G_config.h
libc6-dev: /usr/include/a.out.h
libc6-dev: /usr/include/aio.h
libc6-dev: /usr/include/aliases.h
libc6-dev: /usr/include/alloca.h
libc6-dev: /usr/include/ar.h
libc6-dev: /usr/include/argp.h
libc6-dev: /usr/include/argz.h
libc6-dev: /usr/include/arpa/ftp.h
libc6-dev: /usr/include/arpa/inet.h
libc6-dev: /usr/include/arpa/nameser.h
libc6-dev: /usr/include/arpa/nameser_compat.h
libc6-dev: /usr/include/arpa/telnet.h
libc6-dev: /usr/include/arpa/tftp.h
libc6-dev: /usr/include/assert.h
libc6-dev: /usr/include/bits/a.out.h
libc6-dev: /usr/include/bits/byteswap.h
libc6-dev: /usr/include/bits/cmathcalls.h
libc6-dev: /usr/include/bits/confname.h
libc6-dev: /usr/include/bits/dirent.h
libc6-dev: /usr/include/bits/dlfcn.h
libc6-dev: /usr/include/bits/elfclass.h
libc6-dev: /usr/include/bits/endian.h
libc6-dev: /usr/include/bits/environments.h
libc6-dev: /usr/include/bits/errno.h
libc6-dev: /usr/include/bits/error.h
libc6-dev: /usr/include/bits/fcntl.h
libc6-dev: /usr/include/bits/fcntl2.h
libc6-dev: /usr/include/bits/fenv.h
libc6-dev: /usr/include/bits/fenvinline.h
libc6-dev: /usr/include/bits/huge_val.h
libc6-dev: /usr/include/bits/huge_valf.h
libc6-dev: /usr/include/bits/huge_vall.h
libc6-dev: /usr/include/bits/in.h
libc6-dev: /usr/include/bits/inf.h
libc6-dev: /usr/include/bits/initspin.h
libc6-dev: /usr/include/bits/ioctl-types.h
libc6-dev: /usr/include/bits/ioctls.h
libc6-dev: /usr/include/bits/ipc.h
libc6-dev: /usr/include/bits/ipctypes.h
libc6-dev: /usr/include/bits/libc-lock.h
libc6-dev: /usr/include/bits/libio-ldbl.h
libc6-dev: /usr/include/bits/link.h
libc6-dev: /usr/include/bits/local_lim.h
libc6-dev: /usr/include/bits/locale.h
libc6-dev: /usr/include/bits/mathcalls.h
libc6-dev: /usr/include/bits/mathdef.h
libc6-dev: /usr/include/bits/mathinline.h
libc6-dev: /usr/include/bits/mman.h
libc6-dev: /usr/include/bits/monetary-ldbl.h
libc6-dev: /usr/include/bits/mqueue.h
libc6-dev: /usr/include/bits/mqueue2.h
libc6-dev: /usr/include/bits/msq.h
libc6-dev: /usr/include/bits/nan.h
libc6-dev: /usr/include/bits/netdb.h
libc6-dev: /usr/include/bits/poll.h
libc6-dev: /usr/include/bits/posix1_lim.h
libc6-dev: /usr/include/bits/posix2_lim.h
libc6-dev: /usr/include/bits/posix_opt.h
libc6-dev: /usr/include/bits/predefs.h
libc6-dev: /usr/include/bits/printf-ldbl.h
libc6-dev: /usr/include/bits/pthreadtypes.h
libc6-dev: /usr/include/bits/resource.h
libc6-dev: /usr/include/bits/sched.h
libc6-dev: /usr/include/bits/select.h
libc6-dev: /usr/include/bits/sem.h
libc6-dev: /usr/include/bits/semaphore.h
libc6-dev: /usr/include/bits/setjmp.h
libc6-dev: /usr/include/bits/setjmp2.h
libc6-dev: /usr/include/bits/shm.h
libc6-dev: /usr/include/bits/sigaction.h
libc6-dev: /usr/include/bits/sigcontext.h
libc6-dev: /usr/include/bits/siginfo.h
libc6-dev: /usr/include/bits/signum.h
libc6-dev: /usr/include/bits/sigset.h
libc6-dev: /usr/include/bits/sigstack.h
libc6-dev: /usr/include/bits/sigthread.h
libc6-dev: /usr/include/bits/sockaddr.h
libc6-dev: /usr/include/bits/socket.h
libc6-dev: /usr/include/bits/socket2.h
libc6-dev: /usr/include/bits/stat.h
libc6-dev: /usr/include/bits/statfs.h
libc6-dev: /usr/include/bits/statvfs.h
libc6-dev: /usr/include/bits/stdio-ldbl.h
libc6-dev: /usr/include/bits/stdio-lock.h
libc6-dev: /usr/include/bits/stdio.h
libc6-dev: /usr/include/bits/stdio2.h
libc6-dev: /usr/include/bits/stdio_lim.h
libc6-dev: /usr/include/bits/stdlib-ldbl.h
libc6-dev: /usr/include/bits/stdlib.h
libc6-dev: /usr/include/bits/string.h
libc6-dev: /usr/include/bits/string2.h
libc6-dev: /usr/include/bits/string3.h
libc6-dev: /usr/include/bits/stropts.h
libc6-dev: /usr/include/bits/sys_errlist.h
libc6-dev: /usr/include/bits/syscall.h
libc6-dev: /usr/include/bits/syslog-ldbl.h
libc6-dev: /usr/include/bits/syslog-path.h
libc6-dev: /usr/include/bits/syslog.h
libc6-dev: /usr/include/bits/termios.h
libc6-dev: /usr/include/bits/time.h
libc6-dev: /usr/include/bits/types.h
libc6-dev: /usr/include/bits/typesizes.h
libc6-dev: /usr/include/bits/uio.h
libc6-dev: /usr/include/bits/unistd.h
libc6-dev: /usr/include/bits/ustat.h
libc6-dev: /usr/include/bits/utmp.h
libc6-dev: /usr/include/bits/utmpx.h
libc6-dev: /usr/include/bits/utsname.h
libc6-dev: /usr/include/bits/waitflags.h
libc6-dev: /usr/include/bits/waitstatus.h
libc6-dev: /usr/include/bits/wchar-ldbl.h
libc6-dev: /usr/include/bits/wchar.h
libc6-dev: /usr/include/bits/wchar2.h
libc6-dev: /usr/include/bits/wordsize.h
libc6-dev: /usr/include/bits/xopen_lim.h
libc6-dev: /usr/include/bits/xtitypes.h
libc6-dev: /usr/include/byteswap.h
libc6-dev: /usr/include/complex.h
libc6-dev: /usr/include/cpio.h
libc6-dev: /usr/include/crypt.h
libc6-dev: /usr/include/ctype.h
libc6-dev: /usr/include/dirent.h
libc6-dev: /usr/include/dlfcn.h
libc6-dev: /usr/include/elf.h
libc6-dev: /usr/include/endian.h
libc6-dev: /usr/include/envz.h
libc6-dev: /usr/include/err.h
libc6-dev: /usr/include/errno.h
libc6-dev: /usr/include/error.h
libc6-dev: /usr/include/execinfo.h
libc6-dev: /usr/include/fcntl.h
libc6-dev: /usr/include/features.h
libc6-dev: /usr/include/fenv.h
libc6-dev: /usr/include/fmtmsg.h
libc6-dev: /usr/include/fnmatch.h
libc6-dev: /usr/include/fpu_control.h
libc6-dev: /usr/include/fstab.h
libc6-dev: /usr/include/fts.h
libc6-dev: /usr/include/ftw.h
libc6-dev: /usr/include/gconv.h
libc6-dev: /usr/include/getopt.h
libc6-dev: /usr/include/glob.h
libc6-dev: /usr/include/gnu-versions.h
libc6-dev: /usr/include/gnu/lib-names.h
libc6-dev: /usr/include/gnu/libc-version.h
libc6-dev: /usr/include/gnu/option-groups.h
libc6-dev: /usr/include/gnu/stubs-32.h
libc6-dev: /usr/include/gnu/stubs.h
libc6-dev: /usr/include/grp.h
libc6-dev: /usr/include/gshadow.h
libc6-dev: /usr/include/iconv.h
libc6-dev: /usr/include/ieee754.h
libc6-dev: /usr/include/ifaddrs.h
libc6-dev: /usr/include/inttypes.h
libc6-dev: /usr/include/langinfo.h
libc6-dev: /usr/include/lastlog.h
libc6-dev: /usr/include/libgen.h
libc6-dev: /usr/include/libintl.h
libc6-dev: /usr/include/libio.h
libc6-dev: /usr/include/limits.h
libc6-dev: /usr/include/link.h
libc6-dev: /usr/include/locale.h
libc6-dev: /usr/include/malloc.h
libc6-dev: /usr/include/math.h
libc6-dev: /usr/include/mcheck.h
libc6-dev: /usr/include/memory.h
libc6-dev: /usr/include/mntent.h
libc6-dev: /usr/include/monetary.h
libc6-dev: /usr/include/mqueue.h
libc6-dev: /usr/include/net/ethernet.h
libc6-dev: /usr/include/net/if.h
libc6-dev: /usr/include/net/if_arp.h
libc6-dev: /usr/include/net/if_packet.h
libc6-dev: /usr/include/net/if_ppp.h
libc6-dev: /usr/include/net/if_shaper.h
libc6-dev: /usr/include/net/if_slip.h
libc6-dev: /usr/include/net/ppp-comp.h
libc6-dev: /usr/include/net/ppp_defs.h
libc6-dev: /usr/include/net/route.h
libc6-dev: /usr/include/netash/ash.h
libc6-dev: /usr/include/netatalk/at.h
libc6-dev: /usr/include/netax25/ax25.h
libc6-dev: /usr/include/netdb.h
libc6-dev: /usr/include/neteconet/ec.h
libc6-dev: /usr/include/netinet/ether.h
libc6-dev: /usr/include/netinet/icmp6.h
libc6-dev: /usr/include/netinet/if_ether.h
libc6-dev: /usr/include/netinet/if_fddi.h
libc6-dev: /usr/include/netinet/if_tr.h
libc6-dev: /usr/include/netinet/igmp.h
libc6-dev: /usr/include/netinet/in.h
libc6-dev: /usr/include/netinet/in_systm.h

libc6-dev: /usr/include/netinet/ip.h
libc6-dev: /usr/include/netinet/ip6.h
libc6-dev: /usr/include/netinet/ip_icmp.h
libc6-dev: /usr/include/netinet/tcp.h
libc6-dev: /usr/include/netinet/udp.h
libc6-dev: /usr/include/netipx/ipx.h
libc6-dev: /usr/include/netiucv/iucv.h
libc6-dev: /usr/include/netpacket/packet.h
libc6-dev: /usr/include/netrom/netrom.h
libc6-dev: /usr/include/netrose/rose.h
libc6-dev: /usr/include/nfs/nfs.h
libc6-dev: /usr/include/nl_types.h
libc6-dev: /usr/include/nss.h
libc6-dev: /usr/include/obstack.h
libc6-dev: /usr/include/paths.h
libc6-dev: /usr/include/poll.h
libc6-dev: /usr/include/printf.h
libc6-dev: /usr/include/protocols/routed.h
libc6-dev: /usr/include/protocols/rwhod.h
libc6-dev: /usr/include/protocols/talkd.h
libc6-dev: /usr/include/protocols/timed.h
libc6-dev: /usr/include/pthread.h
libc6-dev: /usr/include/pty.h
libc6-dev: /usr/include/pwd.h
libc6-dev: /usr/include/re_comp.h
libc6-dev: /usr/include/regex.h
libc6-dev: /usr/include/regexp.h
libc6-dev: /usr/include/resolv.h
libc6-dev: /usr/include/rpc/auth.h
libc6-dev: /usr/include/rpc/auth_des.h
libc6-dev: /usr/include/rpc/auth_unix.h
libc6-dev: /usr/include/rpc/clnt.h
libc6-dev: /usr/include/rpc/des_crypt.h
libc6-dev: /usr/include/rpc/key_prot.h
libc6-dev: /usr/include/rpc/netdb.h
libc6-dev: /usr/include/rpc/pmap_clnt.h
libc6-dev: /usr/include/rpc/pmap_prot.h
libc6-dev: /usr/include/rpc/pmap_rmt.h
libc6-dev: /usr/include/rpc/rpc.h
libc6-dev: /usr/include/rpc/rpc_des.h
libc6-dev: /usr/include/rpc/rpc_msg.h
libc6-dev: /usr/include/rpc/svc.h
libc6-dev: /usr/include/rpc/svc_auth.h
libc6-dev: /usr/include/rpc/types.h
libc6-dev: /usr/include/rpc/xdr.h
libc6-dev: /usr/include/rpcsvc/bootparam.h
libc6-dev: /usr/include/rpcsvc/bootparam_prot.h
libc6-dev: /usr/include/rpcsvc/key_prot.h
libc6-dev: /usr/include/rpcsvc/klm_prot.h
libc6-dev: /usr/include/rpcsvc/mount.h
libc6-dev: /usr/include/rpcsvc/nfs_prot.h
libc6-dev: /usr/include/rpcsvc/nis.h
libc6-dev: /usr/include/rpcsvc/nis_callback.h
libc6-dev: /usr/include/rpcsvc/nis_tags.h
libc6-dev: /usr/include/rpcsvc/nislib.h
libc6-dev: /usr/include/rpcsvc/nlm_prot.h
libc6-dev: /usr/include/rpcsvc/rex.h
libc6-dev: /usr/include/rpcsvc/rquota.h
libc6-dev: /usr/include/rpcsvc/rstat.h
libc6-dev: /usr/include/rpcsvc/rusers.h
libc6-dev: /usr/include/rpcsvc/sm_inter.h
libc6-dev: /usr/include/rpcsvc/spray.h
libc6-dev: /usr/include/rpcsvc/yp.h
libc6-dev: /usr/include/rpcsvc/yp_prot.h
libc6-dev: /usr/include/rpcsvc/ypclnt.h
libc6-dev: /usr/include/rpcsvc/yppasswd.h
libc6-dev: /usr/include/rpcsvc/ypupd.h
libc6-dev: /usr/include/sched.h
libc6-dev: /usr/include/scsi/scsi.h
libc6-dev: /usr/include/scsi/scsi_ioctl.h
libc6-dev: /usr/include/scsi/sg.h
libc6-dev: /usr/include/search.h
libc6-dev: /usr/include/semaphore.h
libc6-dev: /usr/include/setjmp.h
libc6-dev: /usr/include/sgtty.h
libc6-dev: /usr/include/shadow.h
libc6-dev: /usr/include/signal.h
libc6-dev: /usr/include/spawn.h
libc6-dev: /usr/include/stab.h
libc6-dev: /usr/include/stdint.h
libc6-dev: /usr/include/stdio.h
libc6-dev: /usr/include/stdio_ext.h
libc6-dev: /usr/include/stdlib.h
libc6-dev: /usr/include/string.h
libc6-dev: /usr/include/strings.h
libc6-dev: /usr/include/stropts.h
libc6-dev: /usr/include/sys/acct.h
libc6-dev: /usr/include/sys/bitypes.h
libc6-dev: /usr/include/sys/cdefs.h
libc6-dev: /usr/include/sys/debugreg.h
libc6-dev: /usr/include/sys/dir.h
libc6-dev: /usr/include/sys/elf.h
libc6-dev: /usr/include/sys/epoll.h
libc6-dev: /usr/include/sys/errno.h
libc6-dev: /usr/include/sys/eventfd.h
libc6-dev: /usr/include/sys/fcntl.h
libc6-dev: /usr/include/sys/file.h
libc6-dev: /usr/include/sys/fsuid.h
libc6-dev: /usr/include/sys/gmon.h
libc6-dev: /usr/include/sys/gmon_out.h
libc6-dev: /usr/include/sys/inotify.h
libc6-dev: /usr/include/sys/io.h
libc6-dev: /usr/include/sys/ioctl.h
libc6-dev: /usr/include/sys/ipc.h
libc6-dev: /usr/include/sys/kd.h
libc6-dev: /usr/include/sys/kdaemon.h
libc6-dev: /usr/include/sys/klog.h
libc6-dev: /usr/include/sys/mman.h
libc6-dev: /usr/include/sys/mount.h
libc6-dev: /usr/include/sys/msg.h
libc6-dev: /usr/include/sys/mtio.h
libc6-dev: /usr/include/sys/param.h
libc6-dev: /usr/include/sys/pci.h
libc6-dev: /usr/include/sys/perm.h
libc6-dev: /usr/include/sys/personality.h
libc6-dev: /usr/include/sys/poll.h
libc6-dev: /usr/include/sys/prctl.h
libc6-dev: /usr/include/sys/procfs.h
libc6-dev: /usr/include/sys/profil.h
libc6-dev: /usr/include/sys/ptrace.h
libc6-dev: /usr/include/sys/queue.h
libc6-dev: /usr/include/sys/quota.h
libc6-dev: /usr/include/sys/raw.h
libc6-dev: /usr/include/sys/reboot.h
libc6-dev: /usr/include/sys/reg.h
libc6-dev: /usr/include/sys/resource.h
libc6-dev: /usr/include/sys/select.h
libc6-dev: /usr/include/sys/sem.h
libc6-dev: /usr/include/sys/sendfile.h
libc6-dev: /usr/include/sys/shm.h
libc6-dev: /usr/include/sys/signal.h
libc6-dev: /usr/include/sys/signalfd.h
libc6-dev: /usr/include/sys/socket.h
libc6-dev: /usr/include/sys/socketvar.h
libc6-dev: /usr/include/sys/soundcard.h
libc6-dev: /usr/include/sys/stat.h
libc6-dev: /usr/include/sys/statfs.h
libc6-dev: /usr/include/sys/statvfs.h
libc6-dev: /usr/include/sys/stropts.h
libc6-dev: /usr/include/sys/swap.h
libc6-dev: /usr/include/sys/syscall.h
libc6-dev: /usr/include/sys/sysctl.h
libc6-dev: /usr/include/sys/sysinfo.h
libc6-dev: /usr/include/sys/syslog.h
libc6-dev: /usr/include/sys/sysmacros.h
libc6-dev: /usr/include/sys/termios.h
libc6-dev: /usr/include/sys/time.h
libc6-dev: /usr/include/sys/timeb.h
libc6-dev: /usr/include/sys/timerfd.h
libc6-dev: /usr/include/sys/times.h
libc6-dev: /usr/include/sys/timex.h
libc6-dev: /usr/include/sys/ttychars.h
libc6-dev: /usr/include/sys/ttydefaults.h
libc6-dev: /usr/include/sys/types.h
libc6-dev: /usr/include/sys/ucontext.h
libc6-dev: /usr/include/sys/uio.h
libc6-dev: /usr/include/sys/ultrasound.h
libc6-dev: /usr/include/sys/un.h
libc6-dev: /usr/include/sys/unistd.h
libc6-dev: /usr/include/sys/user.h
libc6-dev: /usr/include/sys/ustat.h
libc6-dev: /usr/include/sys/utsname.h
libc6-dev: /usr/include/sys/vfs.h
libc6-dev: /usr/include/sys/vlimit.h
libc6-dev: /usr/include/sys/vm86.h
libc6-dev: /usr/include/sys/vt.h
libc6-dev: /usr/include/sys/vtimes.h
libc6-dev: /usr/include/sys/wait.h
libc6-dev: /usr/include/sys/xattr.h
libc6-dev: /usr/include/syscall.h
libc6-dev: /usr/include/sysexits.h
libc6-dev: /usr/include/syslog.h
libc6-dev: /usr/include/tar.h
libc6-dev: /usr/include/termio.h
libc6-dev: /usr/include/termios.h
libc6-dev: /usr/include/tgmath.h
libc6-dev: /usr/include/thread_db.h
libc6-dev: /usr/include/time.h
libc6-dev: /usr/include/ttyent.h
libc6-dev: /usr/include/ucontext.h
libc6-dev: /usr/include/ulimit.h
libc6-dev: /usr/include/unistd.h
libc6-dev: /usr/include/ustat.h
libc6-dev: /usr/include/utime.h
libc6-dev: /usr/include/utmp.h
libc6-dev: /usr/include/utmpx.h
libc6-dev: /usr/include/values.h
libc6-dev: /usr/include/wait.h
libc6-dev: /usr/include/wchar.h
libc6-dev: /usr/include/wctype.h
libc6-dev: /usr/include/wordexp.h
libc6-dev: /usr/include/xlocale.h
libc6-dev-amd64: /usr/include/gnu/stubs-64.h

Exemple de programme utilisant la librairie regex.h comme support d'expressions régulières en C :

#include <stdio.h>
#include <sys/types.h>
#include <regex.h>

int match(const char *str, const char *pattern)
{
   int status;
   regex_t re; if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) return 0; status = regexec(&re, str, (size_t) 0, NULL, 0);
   regfree(&re);
   if (status != 0) return 0; return 1;
}

int main()
{
   int i;
   const char *pattern = "([0-9]{1,3}\\.){3}[0-9]{1,3}";
   const char *str1="une IP 335.0.0.1 uhu";
   const char *str2="Pas d'IP 125.0.0. .."; i = match(str1, pattern);
   

   printf("Dans [%s] IP %strouvée.\n", str1, (i==1)?"":"non "); i = match(str2, pattern);
   printf("Dans [%s] IP %strouvée.\n", str2, (i==1)?"":"non ");

   return 0;
}

Exemple de programme utilisant la librairie math.h . Ce programme calcule puis affiche les 10000 premiers nombres premiers et sera compilé avec gcc premier.c -lm :

#include <stdio.h>
#include <math.h>
#define MAX_NB 10000

int main (int argc, char *argv[])
{
   // le tableau des nombres
   int tab[MAX_NB] = { 2, 3, 5, 7 };
   int nb = 11, index = 4, racine, index2, x;

   // remplissage du tableau :
   retour:
   index2 = 0;
   nb += 2;
   racine = (int) sqrt (nb) + 1;
   while (racine >= tab[index2])
      {
      if (!(nb % tab[index2]))
      goto retour;
      index2++;
      }
   if (index < MAX_NB)
      {
      tab[index] = nb;
      index++;
      goto retour;
      }

   // affichage du tableau :
   for (x = 0; x < MAX_NB; x++)
      {
      if (!(x % 11))
         printf("%d\n",tab[x]);
      else
         printf("%d\t",tab[x]);
      }

   return 0;
}

Cliquez ici pour télécharger un programme source en langage C qui calcule Pi en utilisant la librairie math.h.

 

Retour en haut de la page

Utilisation de l'API GDK pour programmer en mode graphique

Notre programme en C utilisant les fonctions de la librairie GDK commence par la ligne suivante :

#include <gdk/gdk.h>

Il faut donc vérifier si le fichier d'en-tête gdk.h est bien présent dans le répertoire /usr/include. Une recherche récurcive grâce à MC nous informe que le fichier gdk.h se trouve précisément dans le répertoire /usr/include/gdk-2.0/gdk/gdk.h.

La commande locate peut aussi permettre de rechercher un fichier dans l'ensemble du système de fichier :

locate gdk.h

Le programme locate nous répond que l'emplacement du fichier gdk.h est /usr/include/gtk-2.0/gdk/gdk.h

Le programme apt-file permet de faire des recherches dans les paquets .DEB, par exemple pour savoir quel paquet .DEB contient un fichier d'en-tête .h particulier. Avant la première utilisation de apt-file il faut mettre à jour la liste des paquets :

apt-file update

Interrogeons le programme apt-file pour savoir quel paquet .DEB a installé le fichier gdk.h :

apt-file search /usr/include/gtk-2.0/gdk/gdk.h

Le programme apt-file nous répond que gdk.h a été installé par le paquet libgtk2.0-dev

En cas de besoin la commande apt-file list libgtk-2.0 nous donne la liste des fichiers contenus dans le paquet libgtk2.0-dev.deb.

Interrogeons le programme pkg-config pour savoir quel est le nom exact de la librairie gdk :

pkg-config --list-all | grep gdk

Nous trouvons dans la liste plusieurs librairies contenant gdk dans leur nom (sous Ubuntu 10.04) dont gdk-x11-2.0 et gdk-2.0. Nous utiliserons la librairie gdk-2.0.

Demandons à pkg-config quelle est le numéro exact de version de gdk actuellement installé dans le système :

pkg-config --modversion gdk-2.0

Pkg-config nous répond 2.20.1

Demandons à pkg-config quel est l'ensemble des librairies dynamiques utilisées par l'éditeur de liens lors de la compilation d'un programme source en C utilisant gdk-2.0 :

pkg-config --libs gdk-2.0

Pkg-config nous donne une liste de 11 librairies.

Demandons à pkg-config quelle est la liste des répertoires dans lesquels il faudra rechercher les fichiers d'en-tête .h lors de la compilation d'un programme source en C utilisant gdk-2.0 :

pkg-config --cflags gdk-2.0

Pkg-config nous donne une liste de 11 répertoires (qui sont soit des sous-répertoires de /usr/include soit des sous-répertoires de /usr/lib).

Voici un premier programme de base qui crée une fenêtre puis qui y dessine un rectangle et un rond grâce aux fonctions de dessin de GDK. Pour utiliser ce code source :

/********************************************************************************************************/
/* Programme de base utilisant GDK                                                                      */
/* Ce programme crée une fenêtre puis y dessinne un rectangle et un rond grâce à GDK                    */
/* Réalisé par Jean-Christophe MICHEL                                                                   */
/* Février 2011                                                                                         */
/* http://www.gecif.net                                                                                 */
/* Compilation en ligne de commande : gcc toto.c -o toto $(pkg-config --libs --cflags gdk-2.0)          */
/********************************************************************************************************/

#include <gdk/gdk.h>

int main(int argc, char *argv[])
{
static GdkGC *gc=NULL;
static GdkColormap *colormap=NULL;
GdkColor couleur;

GdkWindow *Fenetre;
GdkWindowAttr attr;
GdkEvent *ev;
gboolean fini = FALSE;

/* préparation de la fenêtre */
attr.width = 400;
attr.height = 400;
attr.wclass = GDK_INPUT_OUTPUT;
attr.window_type = GDK_WINDOW_TOPLEVEL;
attr.event_mask = GDK_EXPOSURE_MASK |
GDK_BUTTON_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK;

/* initialisation de gdk */
gdk_init(&argc, &argv);

/* Création de la fenêtre */
Fenetre = gdk_window_new(NULL, &attr, 0);

/* Affichage de la fenêtre */
gdk_window_show(Fenetre);

/* Boucle d'attente des événements */
while (!fini)
if (gdk_events_pending())
{
ev = gdk_event_get();
if (ev)
{
switch (ev->type)
{
case GDK_DELETE:
/* Si on recoit l'événement delete,
* on met fin à l'application
*/
fini = TRUE;
break;
case GDK_BUTTON_PRESS:
break;
case GDK_MOTION_NOTIFY:
break;
case GDK_BUTTON_RELEASE:
break;

default:

/* efface la fenêtre */
gdk_window_clear(Fenetre);
gc = gdk_gc_new(Fenetre);
colormap = gdk_colormap_get_system();

/* prépare le contexte graphique pour tracer le rectangle */
couleur.red=0;
couleur.green=30000;
couleur.blue=0;
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc, &couleur);

/* trace le rectangle vert sur le fond de la fenetre */
gdk_draw_rectangle(Fenetre,gc,TRUE,20,40,200,300);

/* prépare le contexte graphique pour tracer le rectangle */
couleur.red=65535;
couleur.green=65535;
couleur.blue=65535;
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc,&couleur);

/* dessine le rond */
gdk_draw_arc(Fenetre, gc, 1,100,100,80,80,0,360*64);

; /* default de case */
} /* switch */
gdk_event_free(ev);
} /* if */
} /* if */
return 0;
} /* main */

Voici maintenant le jeu Othello programmé en C en utilisant GDK. Cette première version d'Othello se joue à deux joueurs : à tour de rôle chaque joueur clique dans la grille, et un piont de couleur alternativement noir et blanc se dessine dans la case visée. Pour utiliser ce code source :

/********************************************************************************************************/
/* Programme de base utilisant GDK                                                                      */
/* Cette version n'utilise que la librairie de base GDK, et affiche les messages sur la sortie standard */
/* Réalisé par Jean-Christophe MICHEL                                                                   */
/* Février 2011                                                                                         */
/* http://www.gecif.net                                                                                 */
/* Compilation en ligne de commande : gcc othello.c -o othello $(pkg-config --libs --cflags gdk-2.0)    */
/********************************************************************************************************/

#include <gdk/gdk.h>

int tab_grille[9][9]; /* les indices du tableau vont de 0 à 8, mais seuls les indices 1 à 8 sont utilisés */
int prochain_joueur;

/********************************************************************************************************************/
/* Procédure dessiner piont */
/********************************************************************************************************************/
void DessinerPiont(GdkWindow *window,int case_x, int case_y, int couleur_piont)
{
static GdkGC *gc=NULL;
static GdkColormap *colormap=NULL;
GdkColor couleur;
int x,y;

gc=gdk_gc_new(window);

if (couleur_piont==1) {
couleur.red=65535;
couleur.green=65535;
couleur.blue=65535; }
else {
couleur.red=0;
couleur.green=0;
couleur.blue=0; }

colormap=gdk_colormap_get_system();
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc,&couleur);

switch (case_x)
{
case 1 : x=5;
break;
case 2 : x=55;
break;
case 3 : x=105;
break;
case 4 : x=155;
break;
case 5 : x=205;
break;
case 6 : x=255;
break;
case 7 : x=305;
break;
case 8 : x=355;
break;
}

switch (case_y)
{
case 1 : y=5;
break;
case 2 : y=55;
break;
case 3 : y=105;
break;
case 4 : y=155;
break;
case 5 : y=205;
break;
case 6 : y=255;
break;
case 7 : y=305;
break;
case 8 : y=355;
break;
}

/* dessine le piont */
gdk_draw_arc(window, gc,
1,
x , y,
40,40,
0,360*64);

/* met à jour le tableau */
/* 1 = blanc et 2 = noir (0 = case vide) */
tab_grille[case_x][case_y]=couleur_piont;

/* change la couleur du prochain joueur seulement si la case vient d'etre jouee */
if (prochain_joueur==1)
{ prochain_joueur=2;}
else
{ prochain_joueur=1;}
}

/********************************************************************************************************************/
/* Procédure de tracage de la grille */
/*********************************************************************************************************************/

void TracerGrille(GdkEventExpose *ev, gboolean force)
{
GdkGC *gc;
GdkColormap *colormap;
GdkColor couleur;
int i,j;

/* efface la fenêtre */
gdk_window_clear(ev->window);
gc = gdk_gc_new(ev->window);


/* prépare le contexte graphique pour tracer le fond de la fenetre */
colormap = gdk_colormap_get_system();
couleur.red=0;
couleur.green=30000;
couleur.blue=0;
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc, &couleur);

/* trace le rectangle vert sur le fond de la fenetre */
gdk_draw_rectangle(ev->window,gc,TRUE,0,0,400,400);

/* prépare le contexte graphique pour tracer les lignes de la grille */
colormap = gdk_colormap_get_system();
couleur.red=65000;
couleur.green=65000;
couleur.blue=65000;
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc, &couleur);

/* trace les lignes verticales */
for (i=0 ; i<9 ; i++)
gdk_draw_line(ev->window, gc,
50*i, 0,
50*i, 50*8);
/* trace les lignes horizontales */
for (i=0 ; i<9 ; i++)
gdk_draw_line(ev->window, gc,
0,50*i,
50*8,50*i);

/* initialise le tableau à 2 dimentions, image de la grille */
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
tab_grille[i][j]=0;

/* trace les 4 pionts de départ */
/* 1 = blanc et 2 = noir */
DessinerPiont(ev->window,4,4,1);
DessinerPiont(ev->window,4,5,2);
DessinerPiont(ev->window,5,4,2);
DessinerPiont(ev->window,5,5,1);

/* initialise le premier joueur */
prochain_joueur = 1; /* 1=blanc et 2=noir */

gdk_gc_destroy(gc);
}

/********************************************************************************************************************/
/*
* Procédure de traitement des événements
* de type Button Press
*/
/********************************************************************************************************************/
void TraitementButtonPress(GdkEventButton *ev)
{
int x,y;

/* teste dans quelle case le bouton a été enfoncé */
if (ev->x < 50 ) { x=1; }
if ((50 <= ev->x ) && (ev->x < 100)) { x=2; }
if ((100 <= ev->x ) && (ev->x < 150)) { x=3; }
if ((150 <= ev->x ) && (ev->x < 200)) { x=4; }
if ((200 <= ev->x ) && (ev->x < 250)) { x=5; }
if ((250 <= ev->x ) && (ev->x < 300)) { x=6; }
if ((300 <= ev->x ) && (ev->x < 350)) { x=7; }
if ((350 <= ev->x ) && (ev->x < 400)) { x=8; }

if (ev->y < 50 ) { y=1; }
if ((50 <= ev->y ) && (ev->y < 100)) { y=2; }
if ((100 <= ev->y ) && (ev->y < 150)) { y=3; }
if ((150 <= ev->y ) && (ev->y < 200)) { y=4; }
if ((200 <= ev->y ) && (ev->y < 250)) { y=5; }
if ((250 <= ev->y ) && (ev->y < 300)) { y=6; }
if ((300 <= ev->y ) && (ev->y < 350)) { y=7; }
if ((350 <= ev->y ) && (ev->y < 400)) { y=8; }

if (tab_grille[x][y]==0) /* teste si la case est vide avant de dessiner le piont */
{
DessinerPiont(ev->window,x,y,prochain_joueur);
}

}

/********************************************************************************************************************/

int main(int argc, char *argv[])
{
GdkWindow *Fenetre;
GdkWindowAttr attr;
GdkEvent *ev;
gboolean fini = FALSE;

attr.width = 50*8;
attr.height = 50*8;
attr.wclass = GDK_INPUT_OUTPUT;
attr.window_type = GDK_WINDOW_TOPLEVEL;
attr.event_mask = GDK_EXPOSURE_MASK |
GDK_BUTTON_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK;
gdk_init(&argc, &argv);
/* Création de la fenêtre */
Fenetre = gdk_window_new(NULL, &attr, 0);
/* Affichage */
gdk_window_show(Fenetre);

/* Boucle d'attente des événements */
while (!fini)
if (gdk_events_pending())
{
ev = gdk_event_get();
if (ev)
{
switch (ev->type)
{
case GDK_DELETE:
/* Si on recoit l'événement delete,
* on met fin à l'application
*/
fini = TRUE;
break;
case GDK_BUTTON_PRESS:
TraitementButtonPress((GdkEventButton *)ev);
break;
case GDK_MOTION_NOTIFY:
break;

case GDK_BUTTON_RELEASE:
break;

default: TracerGrille((GdkEventExpose *)ev, FALSE);
;
}
gdk_event_free(ev);
}
}
return 0;
}

 

Voici enfin la version complète du jeu Othello que j'ai programmé en C en utilisant GDK. Cette version d'Othello permet à un joueur de jouer contre l'ordinateur. Par défaut le joueur a les points noirs et commence. Pour utiliser ce code source :

/********************************************************************************************************/
/* R E V E R S I Version 1.2 pour Linux
                                                                */
/* Cette version n'utilise que la librairie de base GDK, et affiche les messages sur la sortie standard */
/* Réalisé par Jean-Christophe MICHEL                                                                   */
/* Juillet 2004                                                                                         */
/* http://www.gecif.net                                                                                 */
/* Compilation en ligne de commande : gcc othello.c -o othello $(pkg-config --libs --cflags gdk-2.0)    */
/********************************************************************************************************/

#include <gdk/gdk.h>

int tab_grille[9][9]; /* les indices du tableau vont de 0 à 8, mais seuls les indices 1 à 8 sont utilisés */
int tab_partie[61][9][9]; /* les 60 coups de la partie sont sauvegardés dans tab_partie[0] à tab_partie[59] */
int prochain_joueur,jeu_bloque=0,jeu_fini,index_tab=0,index_max=0,blanc_auto=4,noir_auto=-1,allumer_piont=1;
gboolean fini = FALSE;

GdkWindow *fenetre; /* fenetre principale */

void RedessinerJeu(void);

/********************************************************************************************************************/
/* Procédure dessiner piont */
/********************************************************************************************************************/
void DessinerPiont(int case_x, int case_y, int couleur_piont, int temporisation)
{
static GdkGC *gc=NULL;
static GdkColormap *colormap=NULL;
GdkColor couleur;
int x,y,i;

gc=gdk_gc_new(fenetre);

if (couleur_piont==1) {
couleur.red=65535;
couleur.green=65535;
couleur.blue=65535; }
else {
couleur.red=0;
couleur.green=0;
couleur.blue=0; }

colormap=gdk_colormap_get_system();
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc,&couleur);

switch (case_x)
{
case 1 : x=5;
break;
case 2 : x=55;
break;
case 3 : x=105;
break;
case 4 : x=155;
break;
case 5 : x=205;
break;
case 6 : x=255;
break;
case 7 : x=305;
break;
case 8 : x=355;
break;
}

switch (case_y)
{
case 1 : y=5;
break;
case 2 : y=55;
break;
case 3 : y=105;
break;
case 4 : y=155;
break;
case 5 : y=205;
break;
case 6 : y=255;
break;
case 7 : y=305;
break;
case 8 : y=355;
break;
}

/* dessine le piont */
/* si temporisation == 1 on dessine lentement les pionts */
/* si temporisation == 0 on dessine instantanément les pionts */
if (temporisation==1) {
/* pour ralentir le dessin des pionts on dessine plusieurs fois le même pionts */
for (i=1;i<=5000;i++)
{
gdk_draw_arc(fenetre, gc,
1,
x , y,
40,40,
0,360*64);
}
}
else if (temporisation==2) {

if (allumer_piont==1) {
gdk_draw_arc(fenetre, gc,
1,
x , y,
40,40,
0,360*64);
couleur.red=65535;
couleur.green=0;
couleur.blue=0;
colormap=gdk_colormap_get_system();
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc,&couleur);
for (i=1;i<=15000;i++)
{
gdk_draw_arc(fenetre, gc,
1,
x +10, y+10,
20,20,
0,360*64);
}
}
else
for (i=1;i<=5000;i++)
{
gdk_draw_arc(fenetre, gc,
1,
x, y,
40,40,
0,360*64);
}

}
else
{
gdk_draw_arc(fenetre, gc,
1,
x , y,
40,40,
0,360*64);
}

/* met à jour le tableau */
/* 1 = blanc et 2 = noir (0 = case vide) */
tab_grille[case_x][case_y]=couleur_piont;

}

/********************************************************************************************************************/
/* Procédure de tracage de la grille */
/*********************************************************************************************************************/

void TracerGrille(gboolean raz)
{
GdkGC *gc;
GdkColormap *colormap;
GdkColor couleur;
GdkFont *police;
int i,j;

/* déclaration des messages à afficher */
static gchar message1[]="Raccourcis clavier"; /* tableau de caractères finissant par \x00 */
static gchar message2[]="F1 : BLANCS auto/manuel"; /* tableau de caractères finissant par \x00 */
static gchar message3[]="F2 : NOIRS auto/manuel"; /* tableau de caractères finissant par \x00 */
static gchar message4[]=" B : ordinateur joue pour les BLANCS"; /* tableau de caractères finissant par \x00 */
static gchar message5[]=" N : ordinateur joue pour les NOIRS"; /* tableau de caractères finissant par \x00 */
static gchar message6[]=" R : active/desactive le point rouge"; /* tableau de caractères finissant par \x00 */
static gchar message7[]="Fleche gauche : Annuler dernier coup"; /* tableau de caractères finissant par \x00 */
static gchar message8[]="Fleche droite : Retablir le coup"; /* tableau de caractères finissant par \x00 */
static gchar message9[]="Origine : Recommencer une partie"; /* tableau de caractères finissant par \x00 */
static gchar message10[]="ESC : Quitter"; /* tableau de caractères finissant par \x00 */
static gchar message11[]="Realise par Jean-Christophe MICHEL"; /* tableau de caractères finissant par \x00 */
static gchar message12[]="http://www.gecif.net"; /* tableau de caractères finissant par \x00 */

/* efface la fenêtre */
gdk_window_clear(fenetre);
gc = gdk_gc_new(fenetre);


/* prépare le contexte graphique pour tracer le fond de la fenetre */
colormap = gdk_colormap_get_system();
couleur.red=0;
couleur.green=30000;
couleur.blue=0;
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc, &couleur);

/* trace le rectangle vert sur le fond de la fenetre */
gdk_draw_rectangle(fenetre,gc,TRUE,0,0,400,400);

/* prépare le contexte graphique pour tracer les lignes de la grille */
colormap = gdk_colormap_get_system();
couleur.red=65000;
couleur.green=65000;
couleur.blue=65000;
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc, &couleur);

/* trace les lignes verticales */
for (i=0 ; i<9 ; i++)
gdk_draw_line(fenetre, gc,
50*i, 0,
50*i, 50*8);
/* trace les lignes horizontales */
for (i=0 ; i<9 ; i++)
gdk_draw_line(fenetre, gc,
0,50*i,
50*8,50*i);

/* Affiche le texte dans la zone de droite */

police=gdk_font_load("10x20");

gc=gdk_gc_new(fenetre); /* prépare le contexte graphique */
couleur.red=65000;
couleur.green=65000;
couleur.blue=65000;
colormap=gdk_colormap_get_system();
gdk_color_alloc(colormap,&couleur);
gdk_gc_set_foreground(gc,&couleur);

gdk_draw_string(fenetre,police,gc,500,20,message1);
gdk_draw_string(fenetre,police,gc,410,40,message2);
gdk_draw_string(fenetre,police,gc,410,60,message3);
gdk_draw_string(fenetre,police,gc,410,80,message4);
gdk_draw_string(fenetre,police,gc,410,100,message5);
gdk_draw_string(fenetre,police,gc,410,120,message6);
gdk_draw_string(fenetre,police,gc,410,140,message7);
gdk_draw_string(fenetre,police,gc,410,160,message8);
gdk_draw_string(fenetre,police,gc,410,180,message9);
gdk_draw_string(fenetre,police,gc,410,200,message10);
gdk_draw_string(fenetre,police,gc,430,350,message11);
gdk_draw_string(fenetre,police,gc,490,370,message12);

gdk_font_unref(police);
gdk_gc_destroy(gc);

/* si raz alors on remet à zéro le tableau, en plus de dessiner la grille (début d'une nouvelle partie) */
/* si raz == FALSE alors on se contente de dessiner le fond vert et la grille, dans changer le tableau (déplacement de la fenetre) */
if (raz==TRUE) {

/* prépare une nouvelle partie : */
jeu_bloque=0;
jeu_fini=0;
index_tab=0;
index_max=0;

/* initialise le tableau à 2 dimentions, image de la grille */
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
tab_grille[i][j]=0;

/* trace les 4 pionts de départ */
/* 1 = blanc et 2 = noir */
DessinerPiont(4,4,1,0);
DessinerPiont(4,5,2,0);
DessinerPiont(5,4,2,0);
DessinerPiont(5,5,1,0);

/* initialise le premier joueur */
prochain_joueur = 2; /* 1=blanc et 2=noir */
}

gdk_gc_destroy(gc);
}

/********************************************************************************************************************/
/* Cette procédure teste toutes les cases vide pour savoir si le joueur peut jouer ou doit passer sont tour */
/*********************************************************************************************************************/

void TesterJoueur(void)
{

int x,y,i,j,adversaire,case_correcte=0,chemin_correct,case_x,case_y;
jeu_fini=1;

/* détermine la couleur de l'adversaire */
if (prochain_joueur==1)
{ adversaire=2;}
else
{ adversaire=1;}

/* recherche et teste les cases vides */
for (case_x=1;case_x<=8;case_x++)
for (case_y=1;case_y<=8;case_y++)
{

if (tab_grille[case_x][case_y]==0) /* si la case est vide, alors on teste si elle est jouable */
{
jeu_fini=0; /* jeu_fini indique que les 64 cases sont pleines */

/* teste les 64 cases une par une */
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
{

if ((tab_grille[x][y] == prochain_joueur) && ((abs(case_x-x) > 1) || (abs(case_y-y) > 1)))
{ /* on a trouvé une case de même couleur que le joueur courant, et non-adjacente à la case testée. */
/* on va maintenant tester le chemin reliant les 2 cases pour savoir s'il est uniformément de la couleur adverse */
/* il y a 8 directions possibles: les 8 cas sont testés réparément. C'est parti ! :-) */
chemin_correct=1;
/* cas 1 */
if ((case_x>x) && (case_y>y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<case_x-x;i++) /* parcourt le chemin */
{
/* on teste si le chemin est correct, */
/* c'est à dire s'il est composé essenciellement de couleur adverse */
if (tab_grille[x+i][y+i]!=adversaire)
{
chemin_correct=0;
}

}
}
/* cas 2 */
else if ((case_x<x) && (case_y>y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<x-case_x;i++)
{

if (tab_grille[case_x+i][case_y-i]!=adversaire)
{
chemin_correct=0;
}
}

}

/* cas 3 */
else if ((case_x>x) && (case_y<y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<case_x-x;i++)
{
if (tab_grille[case_x-i][case_y+i]!=adversaire)
{
chemin_correct=0;
}
}

}

/* cas 4 */
else if ((case_x<x) && (case_y<y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<x-case_x;i++)
{
if (tab_grille[case_x+i][case_y+i]!=adversaire)
{
chemin_correct=0;
}
}

}
/* cas 5 */
else if ((case_x==x) && (case_y>y))
{
for (i=1;i<case_y-y;i++)
{
if (tab_grille[x][y+i]!=adversaire)
{
chemin_correct=0;
}
}

}

/* cas 6 */
else if ((case_x==x) && (case_y<y))
{
for (i=1;i<y-case_y;i++)
{
if (tab_grille[x][case_y+i]!=adversaire)
{
chemin_correct=0;
}
}

}

/* cas 7 */
else if ((case_x>x) && (case_y==y))
{
for (i=1;i<case_x-x;i++)
{
if (tab_grille[x+i][y]!=adversaire)
{
chemin_correct=0;
}
}

}

/* cas 8 */
else if ((case_x<x) && (case_y==y))
{
for (i=1;i<x-case_x;i++)
{
if (tab_grille[case_x+i][y]!=adversaire)
{
chemin_correct=0;
}
}

}

else
{
/* on teste une case isolée */
chemin_correct=0; }

/* la case est considérée jouable a partir du moment ou au moins 1 chemin correct a été trouvé */
if (chemin_correct==1) {
case_correcte=1;
}
} /* if */
} /* for y */
} /* if case vide */
} /* for case_y */

if (jeu_fini==1)
{

/* la partie est finie, on compte le nombre de pionts BLANCS et de pionts NOIRS */
i=0;
j=0;
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
{
if (tab_grille[x][y]==1) { i++; }
if (tab_grille[x][y]==2) { j++; }
}
printf("Les 64 cases sont pleines, la partie est finie\n");
printf("Nombre de pionts BLANCS : %i\n",i);
printf("Nombre de pionts NOIRS : %i\n",j);
if (i>j) { printf("Les BLANCS ont gagne !\n"); }
if (i<j) { printf("Les NOIRS ont gagne !\n"); }
if (i==j) { printf("Egalite entre les BLANCS et les NOIRS.\n"); }

}

/* si case_correcte==1 alors il y a au moins une case jouable pour le prochain joueur */
/* si case_correcte==0 alors il n'y a aucune case jouable : le prochain joueur doit passer son tour */

else if (case_correcte==0) {

/* le joueur doit passer son tour */
if (prochain_joueur==1)
{
printf("Le joueur BLANC doit passer son tour.C est a NOIR a rejouer.\n");
prochain_joueur=2;}
else
{
printf("Le joueur NOIR doit passer son tour.C est a BLANC a rejouer.\n");
prochain_joueur=1;
}
/* si jeu_bloqué == 1 cela signifie que l'autre joueur vient aussi de passer son tour : la partie est fini */
if (jeu_bloque==1)
{
printf("Le jeu est bloque, la partie est finie.\n");
jeu_fini=1;
}
else {
jeu_bloque=1;
}
}
else
{
jeu_bloque=0;
}
}

/********************************************************************************************************************/
/* Procédure de test de la case jouée */
/*********************************************************************************************************************/

void TesterCase(int case_x, int case_y)
{

int x,y,i,j,adversaire,case_correcte=0,chemin_correct;

/* si la case n'est pas vide, on sort immédiatement de TesterCase */
if (tab_grille[case_x][case_y]==0)
{

/* détermine la couleur de l'adversaire */
if (prochain_joueur==1)
{ adversaire=2;}
else
{ adversaire=1;}

/* teste les 64 cases une par une */
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
{

if ((tab_grille[x][y] == prochain_joueur) && ((abs(case_x-x) > 1) || (abs(case_y-y) > 1)))
{ /* on a trouvé une case de même couleur que la case jouée, et non-adjacente */
/* on va maintenant tester le chemin reliant les 2 cases pour savoir s'il est uniformément de la couleur adverse */
/* il y a 8 direction possibles: les 8 cas sont testés réparément. C'est parti ! :-) */
chemin_correct=1;
/* cas 1 */
if ((case_x>x) && (case_y>y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<case_x-x;i++) /* parcourt le chemin */
{
/* on teste en un premier temps si le chemin est correct, */
/* c'est à dire s'il est composé essenciellement de couleur adverse */
if (tab_grille[x+i][y+i]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct==1) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
/* et si le chemin est correct alors on retourne tous les pionts sur ce chemin */
for (i=1;i<case_x-x;i++)
{
DessinerPiont(case_x-i,case_y-i,prochain_joueur,1);
}
}
}
/* cas 2 */
else if ((case_x<x) && (case_y>y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<x-case_x;i++)
{

if (tab_grille[case_x+i][case_y-i]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct==1) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<x-case_x;i++)
{
DessinerPiont(case_x+i,case_y-i,prochain_joueur,1);
}
}
}

/* cas 3 */
else if ((case_x>x) && (case_y<y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<case_x-x;i++)
{
if (tab_grille[case_x-i][case_y+i]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct==1) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<case_x-x;i++)
{
DessinerPiont(case_x-i,case_y+i,prochain_joueur,1);
}
}
}

/* cas 4 */
else if ((case_x<x) && (case_y<y) && (abs(case_x-x)==abs(case_y-y)))
{

for (i=1;i<x-case_x;i++)
{
if (tab_grille[case_x+i][case_y+i]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct==1) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<x-case_x;i++)
{
DessinerPiont(case_x+i,case_y+i,prochain_joueur,1);
}
}
}
/* cas 5 */
else if ((case_x==x) && (case_y>y))
{
for (i=1;i<case_y-y;i++)
{
if (tab_grille[x][y+i]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<case_y-y;i++)
{
DessinerPiont(x,case_y-i,prochain_joueur,1);
}
}
}

/* cas 6 */
else if ((case_x==x) && (case_y<y))
{
for (i=1;i<y-case_y;i++)
{
if (tab_grille[x][case_y+i]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<y-case_y;i++)
{
DessinerPiont(x,case_y+i,prochain_joueur,1);
}
}
}

/* cas 7 */
else if ((case_x>x) && (case_y==y))
{
for (i=1;i<case_x-x;i++)
{
if (tab_grille[x+i][y]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<case_x-x;i++)
{
DessinerPiont(case_x-i,y,prochain_joueur,1);
}
}
}

/* cas 8 */
else if ((case_x<x) && (case_y==y))
{
for (i=1;i<x-case_x;i++)
{
if (tab_grille[case_x+i][y]!=adversaire)
{
chemin_correct=0;
}
}

if (chemin_correct) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,2);
for (i=1;i<x-case_x;i++)
{
DessinerPiont(case_x+i,y,prochain_joueur,1);
}
}
}

else
{
/* on a cliqué sur une case isolée */
chemin_correct=0; }

/* la case est considérée jouable a partir du moment ou au moins 1 chemin correct a été trouvé */
if (chemin_correct==1) {
case_correcte=1;
}
}
}

if (case_correcte==1) {
/* dessine le piont joué */
DessinerPiont(case_x,case_y,prochain_joueur,1);


/* change la couleur du prochain joueur seulement si la case vient d'etre jouee */
if (prochain_joueur==1)
{ prochain_joueur=2;}
else
{ prochain_joueur=1;}

/* sauvegarde l'état des 64 cases de la nouvelles grille dans le tableau tab_partie à 3 dimensions */
index_tab++;
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
tab_partie[index_tab][x][y]=tab_grille[x][y];
index_max=index_tab;

/* on teste maintenant si le prochain joueur peut jouer ou s'il doit passer son tour */
/* on appelle 2 fois testerJoueur, afin de tester le nouveau joueur si jamais le premier appel a changer le prochain joueur */
TesterJoueur();
TesterJoueur();

/* tempo artificielle entre 2 joueurs */
// for (i=0;i<50000;i++)
// for (j=0;j<1000;j++);

}
else
{
// printf("La case choisie n'est pas jouable, recommencez.\n");
}
} /* if (tab_grille[x][y]==0) */

//printf("Case testee : x=%i y=%i Joueur = %i\n",case_x,case_y,prochain_joueur);

} /* fin de la fonction TESTER_CASE() */

 

/********************************************************************************************************************/
/* Procédure de reconstruction du jeu après un déplacement de la fenetre */
/********************************************************************************************************************/

void RedessinerJeu(void)
{
int x,y;

/* redessine la grille et le fond vert sant toucher au tableau */
TracerGrille(FALSE);

/* redessine les piont sur les 64 cases une par une */
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
{
if (tab_grille[x][y]==1) { DessinerPiont(x,y,1,0); }
if (tab_grille[x][y]==2) { DessinerPiont(x,y,2,0); }
/* on ne fait rien si la case est vide : tab_grille[x][y]==0 */
}

}

/********************************************************************************************************************/
/*
* Procédure de traitement des événements
* de type Button Press
*/
/********************************************************************************************************************/
void TraitementButtonPress(GdkEventButton *ev)
{
int x=-1,y=-1;

/* teste dans quelle case le bouton a été enfoncé */
if (ev->x < 50 ) { x=1; }
if ((50 <= ev->x ) && (ev->x < 100)) { x=2; }
if ((100 <= ev->x ) && (ev->x < 150)) { x=3; }
if ((150 <= ev->x ) && (ev->x < 200)) { x=4; }
if ((200 <= ev->x ) && (ev->x < 250)) { x=5; }
if ((250 <= ev->x ) && (ev->x < 300)) { x=6; }
if ((300 <= ev->x ) && (ev->x < 350)) { x=7; }
if ((350 <= ev->x ) && (ev->x < 400)) { x=8; }

if (ev->y < 50 ) { y=1; }
if ((50 <= ev->y ) && (ev->y < 100)) { y=2; }
if ((100 <= ev->y ) && (ev->y < 150)) { y=3; }
if ((150 <= ev->y ) && (ev->y < 200)) { y=4; }
if ((200 <= ev->y ) && (ev->y < 250)) { y=5; }
if ((250 <= ev->y ) && (ev->y < 300)) { y=6; }
if ((300 <= ev->y ) && (ev->y < 350)) { y=7; }
if ((350 <= ev->y ) && (ev->y < 400)) { y=8; }

if ((x!=-1) && (y!=-1) && (tab_grille[x][y]==0))
{
TesterCase(x,y);
}

}

/********************************************************************************************************************/
/* Procédure de réflexion qui joue dans une case */
/********************************************************************************************************************/

void OrdinateurJoue(int niveau, int joueur)
/* le paramètre niveau indique le niveau de jeu parmi les suivants :
niveau 0 : l'ordinateur joue au hasard dans une case vide
niveau 1 : l'ordinateur joue en priorité les cases stratégiques (coins, bords) et en dernier recourt les
cases adjencentes au coin. Dans ce niveau 1 l'ordinateur n'anticipe absolument pas les coups suivants.
niveau 2 : L'ordinateur joue en priorité dans les cases stratégiques, en regardant si certaines cases lui appartiennent déjà
niveau 3 : comme le niveau 2 + balayage de la moitiè du jeu à partir d'un coin possédé
*/
{
int x,y,i,j,adversaire;

if (joueur==1) { adversaire=2; }
else adversaire=1;

switch (niveau)
{

/* -------------------------- NIVEAU 0 ------------------------------------------------------------------*/

case 0: /* L'ordinateur joue au hasard */
while ((prochain_joueur==joueur) && (jeu_fini==0))
{
/* donne une valeur aléatoire comrise entre 1 et 8 à x et à y */
x=(rand() % 8)+1;
y=(rand() % 8)+1;
TesterCase(x,y);
} /* while */
break;

/* -------------------------- NIVEAU 1 ------------------------------------------------------------------*/

case 1:
/* L'ordinateur joue en priorité dans les cases stratégiques, dans un ordre précis, sans anticiper. */

/* Tant que (prochain_joueur==joueur) l'ordinateur n'a pas encore joué : on teste alors une nouvelle case */

/* teste les 4 coins : */
if (prochain_joueur==joueur) TesterCase(1,1);
if (prochain_joueur==joueur) TesterCase(8,1);
if (prochain_joueur==joueur) TesterCase(1,8);
if (prochain_joueur==joueur) TesterCase(8,8);

/* teste les bords non adjacents aux coins : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,1);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,8);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(1,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(8,i);

/* teste les cases centrales : */
for (i=3;i<=6;i++)
for (j=3;j<=6;j++)
if (prochain_joueur==joueur) TesterCase(i,j);

/* teste les cases lignes 2 et 7 et colonnes 2 et 7 : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(7,i);

/* en dernier recourt, teste les cases adjacentes aux coins */
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(8,7);

if (prochain_joueur==joueur) TesterCase(2,2);
if (prochain_joueur==joueur) TesterCase(7,2);
if (prochain_joueur==joueur) TesterCase(2,7);
if (prochain_joueur==joueur) TesterCase(7,7);

break;

/* -------------------------- NIVEAU 2 ------------------------------------------------------------------*/

case 2:
/* L'ordinateur joue en priorité dans les cases stratégiques, en regardant si certaines cases lui appartiennent déjà. */

/* Tant que (prochain_joueur==joueur) l'ordinateur n'a pas encore joué : on teste alors une nouvelle case */

/* teste les 4 coins : */
if (prochain_joueur==joueur) TesterCase(1,1);
if (prochain_joueur==joueur) TesterCase(8,1);
if (prochain_joueur==joueur) TesterCase(1,8);
if (prochain_joueur==joueur) TesterCase(8,8);

/************** Tests de cases conditionnels **********************/

/* si un coin est déjà pris par l'ordinateur, il teste les 3 cases adjacentes à ce coin */
if (tab_grille[1][1]==joueur)
{
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(2,2);
}
if (tab_grille[1][8]==joueur)
{
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(2,7);
}
if (tab_grille[8][1]==joueur)
{
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(7,2);
}
if (tab_grille[8][8]==joueur)
{
if (prochain_joueur==joueur) TesterCase(8,7);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(7,7);
}

/* teste les bords non adjacents aux coins si l'ordinateur possède déjà un coin : */
for (i=3;i<=6;i++)
if (((tab_grille[1][1]==joueur) || (tab_grille[8][1]==joueur)) && (prochain_joueur==joueur)) TesterCase(i,1);

for (i=3;i<=6;i++)
if (((tab_grille[8][8]==joueur) || (tab_grille[8][8]==joueur)) && (prochain_joueur==joueur)) TesterCase(i,8);

for (i=3;i<=6;i++)
if (((tab_grille[1][1]==joueur) || (tab_grille[1][8]==joueur)) && (prochain_joueur==joueur)) TesterCase(1,i);

for (i=3;i<=6;i++)
if (((tab_grille[8][1]==joueur) || (tab_grille[8][8]==joueur)) && (prochain_joueur==joueur)) TesterCase(8,i);

/* teste les bords non adjacents aux coins si l'adversaire ne possède pas un coin de ce bord : */
for (i=3;i<=6;i++)
if ((tab_grille[1][1]!=adversaire) && (tab_grille[8][1]!=adversaire) && (prochain_joueur==joueur)) TesterCase(i,1);

for (i=3;i<=6;i++)
if ((tab_grille[8][8]!=adversaire) && (tab_grille[8][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(i,8);

for (i=3;i<=6;i++)
if ((tab_grille[1][1]!=adversaire) && (tab_grille[1][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(1,i);

for (i=3;i<=6;i++)
if ((tab_grille[8][1]!=adversaire) && (tab_grille[8][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(8,i);

/* teste les cases lignes 2 et 7 et colonnes 2 et 7 si l'ordinateur possède déjà un coin : */
for (i=3;i<=6;i++) if (((tab_grille[1][1]==joueur) || (tab_grille[8][1]==joueur)) && (prochain_joueur==joueur)) TesterCase(i,2);
for (i=3;i<=6;i++) if (((tab_grille[1][8]==joueur) || (tab_grille[8][8]==joueur)) && (prochain_joueur==joueur)) TesterCase(i,7);
for (i=3;i<=6;i++) if (((tab_grille[1][1]==joueur) || (tab_grille[1][8]==joueur)) && (prochain_joueur==joueur)) TesterCase(2,i);
for (i=3;i<=6;i++) if (((tab_grille[8][1]==joueur) || (tab_grille[8][8]==joueur)) && (prochain_joueur==joueur)) TesterCase(7,i);

/************** Tests de cases inconditionnels (comme pour le niveau 1) **********************/

/* teste les cases centrales : */
for (i=3;i<=6;i++)
for (j=3;j<=6;j++)
if (prochain_joueur==joueur) TesterCase(i,j);

/* teste les bords non adjacents aux coins : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,1);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,8);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(1,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(8,i);

/* teste les cases lignes 2 et 7 et colonnes 2 et 7 : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(7,i);

/* en dernier recourt, teste les cases adjacentes aux coins */
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(8,7);

if (prochain_joueur==joueur) TesterCase(2,2);
if (prochain_joueur==joueur) TesterCase(7,2);
if (prochain_joueur==joueur) TesterCase(2,7);
if (prochain_joueur==joueur) TesterCase(7,7);

break;

/* -------------------------- NIVEAU 3 ------------------------------------------------------------------*/

case 3:
/* L'ordinateur joue en priorité dans les cases stratégiques, en regardant si certaines cases lui appartiennent déjà. */
/* Si un coin lui appartient, il fait tout pour envahir le jeu à partir de ce coin */

/* Tant que (prochain_joueur==joueur) l'ordinateur n'a pas encore joué : on teste alors une nouvelle case */

/* teste les 4 coins : */
if (prochain_joueur==joueur) TesterCase(1,1);
if (prochain_joueur==joueur) TesterCase(8,1);
if (prochain_joueur==joueur) TesterCase(1,8);
if (prochain_joueur==joueur) TesterCase(8,8);

/************** Balayage de la moitiè du jeu si l'ordinateur possède un coin **********************/

/* si un coin est déjà pris par l'ordinateur, il teste les 27 cases les plus proches du coin */
/* On commence par tester les 3 cases adjacentes au coin (comme au niveau 2) : */

if (tab_grille[1][1]==joueur)
{
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(2,2);
}
if (tab_grille[1][8]==joueur)
{
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(2,7);
}
if (tab_grille[8][1]==joueur)
{
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(7,2);
}
if (tab_grille[8][8]==joueur)
{
if (prochain_joueur==joueur) TesterCase(8,7);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(7,7);
}

/* puis on teste les 24 autres cases "par balayage" du damier */

if (tab_grille[1][1]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(i,4-i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(i,5-i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(i,6-i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7-i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(i,8-i); /* 7 cases en diagonales */
}
if (tab_grille[1][8]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(i,5+i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(i,4+i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(i,3+i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2+i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(i,1+i); /* 7 cases en diagonales */
}
if (tab_grille[8][1]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(5+i,i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(4+i,i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(3+i,i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2+i,i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(1+i,i); /* 7 cases en diagonales */
}
if (tab_grille[8][8]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(5+i,9-i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(4+i,9-i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(3+i,9-i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2+i,9-i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(1+i,9-i); /* 7 cases en diagonales */
}

/************** Tests de cases conditionnels (comme au niveau 2) **********************/

/* teste les bords non adjacents aux coins si l'adversaire ne possède pas un coin de ce bord : */
for (i=3;i<=6;i++)
if ((tab_grille[1][1]!=adversaire) && (tab_grille[8][1]!=adversaire) && (prochain_joueur==joueur)) TesterCase(i,1);

for (i=3;i<=6;i++)
if ((tab_grille[8][8]!=adversaire) && (tab_grille[8][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(i,8);

for (i=3;i<=6;i++)
if ((tab_grille[1][1]!=adversaire) && (tab_grille[1][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(1,i);

for (i=3;i<=6;i++)
if ((tab_grille[8][1]!=adversaire) && (tab_grille[8][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(8,i);

/************** Tests de cases inconditionnels (comme pour le niveau 1) **********************/

/* teste les cases centrales : */
for (i=3;i<=6;i++)
for (j=3;j<=6;j++)
if (prochain_joueur==joueur) TesterCase(i,j);

/* teste les bords non adjacents aux coins : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,1);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,8);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(1,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(8,i);

/* teste les cases lignes 2 et 7 et colonnes 2 et 7 : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(7,i);

/* en dernier recourt, teste les cases adjacentes aux coins */
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(8,7);

if (prochain_joueur==joueur) TesterCase(2,2);
if (prochain_joueur==joueur) TesterCase(7,2);
if (prochain_joueur==joueur) TesterCase(2,7);
if (prochain_joueur==joueur) TesterCase(7,7);

break;

/* -------------------------- NIVEAU 4 ------------------------------------------------------------------*/

case 4:
/* teste les 4 coins : */
if (prochain_joueur==joueur) TesterCase(1,1);
if (prochain_joueur==joueur) TesterCase(8,1);
if (prochain_joueur==joueur) TesterCase(1,8);
if (prochain_joueur==joueur) TesterCase(8,8);

/* Le niveau 4 est comme le niveau 3 avec en plus :

On teste la case T si les 2 cases A sont occupées par l'adersaire, et si le coin V est vide (idem pour chaque coin) :
Ainsi, on est sûr d'avoir le coin au prochain coup :

-------------------------------------------------
| | | | | | | | |
| V | A | T | A | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| A | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| T | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| A | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | | | | | | | |
| | | | | | | | |
-------------------------------------------------
*/

/* tests horizontaux dans les 4 coins : */
if ((tab_grille[1][1]==0) && (tab_grille[2][1]==adversaire) && (tab_grille[3][1]==0) && (tab_grille[4][1]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(3,1);
}
if ((tab_grille[8][1]==0) && (tab_grille[7][1]==adversaire) && (tab_grille[6][1]==0) && (tab_grille[5][1]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(6,1);
}
if ((tab_grille[1][8]==0) && (tab_grille[2][8]==adversaire) && (tab_grille[3][8]==0) && (tab_grille[4][8]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(3,8);
}
if ((tab_grille[8][8]==0) && (tab_grille[7][8]==adversaire) && (tab_grille[6][8]==0) && (tab_grille[5][8]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(6,8);
}

/* tests verticaux dans les 4 coins : */
if ((tab_grille[1][1]==0) && (tab_grille[1][2]==adversaire) && (tab_grille[1][3]==0) && (tab_grille[1][4]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(1,3);
}
if ((tab_grille[1][8]==0) && (tab_grille[1][7]==adversaire) && (tab_grille[1][6]==0) && (tab_grille[1][5]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(1,6);
}
if ((tab_grille[8][1]==0) && (tab_grille[8][2]==adversaire) && (tab_grille[8][3]==0) && (tab_grille[8][4]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(8,3);
}
if ((tab_grille[8][8]==0) && (tab_grille[8][7]==adversaire) && (tab_grille[8][6]==0) && (tab_grille[8][5]==adversaire))
{
if (prochain_joueur==joueur) TesterCase(8,6);
}

/* Si le coin V est vide, et que la case J contient la couleur du joueur alors que la case A contient la couleur de l'adversaire,
il faut absolument jouer dans la case T pour éviter que l'adversaire ne prenne le coin au prochain tour (idem pour chaque coin) :
Remarque : si dans la case à droite de T il y a aussi l'adversaire, il prendra quand même le coin au prochain tour ...

-------------------------------------------------
| | | | | | | | |
| V | J | A | T | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| T | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| A | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| J | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | | | | | | | |
| | | | | | | | |
-------------------------------------------------
*/

/* tests horizontaux dans les 4 coins : */
if ((tab_grille[1][1]==0) && (tab_grille[2][1]==joueur) && (tab_grille[3][1]==adversaire) && (tab_grille[4][1]==0))
{
if (prochain_joueur==joueur) TesterCase(4,1);
}
if ((tab_grille[8][1]==0) && (tab_grille[5][1]==joueur) && (tab_grille[6][1]==adversaire) && (tab_grille[5][1]==0))
{
if (prochain_joueur==joueur) TesterCase(6,1);
}
if ((tab_grille[1][8]==0) && (tab_grille[4][8]==joueur) && (tab_grille[3][8]==adversaire) && (tab_grille[4][8]==0))
{
if (prochain_joueur==joueur) TesterCase(3,8);
}
if ((tab_grille[8][8]==0) && (tab_grille[5][8]==joueur) && (tab_grille[6][8]==adversaire) && (tab_grille[5][8]==0))
{
if (prochain_joueur==joueur) TesterCase(6,8);
}

/* tests verticaux dans les 4 coins : */
if ((tab_grille[1][1]==0) && (tab_grille[1][2]==joueur) && (tab_grille[1][3]==adversaire) && (tab_grille[1][4]==0))
{
if (prochain_joueur==joueur) TesterCase(1,4);
}
if ((tab_grille[1][8]==0) && (tab_grille[1][7]==joueur) && (tab_grille[1][6]==adversaire) && (tab_grille[1][5]==0))
{
if (prochain_joueur==joueur) TesterCase(1,5);
}
if ((tab_grille[8][1]==0) && (tab_grille[8][2]==joueur) && (tab_grille[8][3]==adversaire) && (tab_grille[8][4]==0))
{
if (prochain_joueur==joueur) TesterCase(8,4);
}
if ((tab_grille[8][8]==0) && (tab_grille[8][7]==joueur) && (tab_grille[8][6]==adversaire) && (tab_grille[8][5]==0))
{
if (prochain_joueur==joueur) TesterCase(8,5);
}

 

/* On teste les cases T si les 4 cases V sont vides (idem pour chaque coin) :

-------------------------------------------------
| | | | | | | | |
| V | T | V | | | V | T | V |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| T | V | | | | | V | T |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | | | | | | | V |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | | | | | | | V |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| T | V | | | | | V | T |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | T | V | | | V | T | V |
| | | | | | | | |
-------------------------------------------------
*/

/* test des 2 cases T si les 4 cases V sont vides (pour chaque coin) */

if ((tab_grille[1][1]==0) && (tab_grille[2][2]==0) && (tab_grille[3][1]==0) && (tab_grille[1][3]==0))
{
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
}

if ((tab_grille[8][1]==0) && (tab_grille[7][2]==0) && (tab_grille[6][1]==0) && (tab_grille[8][3]==0))
{
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(8,2);
}

if ((tab_grille[1][8]==0) && (tab_grille[2][7]==0) && (tab_grille[1][6]==0) && (tab_grille[3][8]==0))
{
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(2,8);
}

if ((tab_grille[8][8]==0) && (tab_grille[7][7]==0) && (tab_grille[8][6]==0) && (tab_grille[6][8]==0))
{
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(8,7);
}

 

/************** Balayage de la moitiè du jeu si l'ordinateur possède un coin (comme au niveau 3) **********************/

/* si un coin est déjà pris par l'ordinateur, il teste les 27 cases les plus proches du coin */
/* On commence par tester les 3 cases adjacentes au coin (comme au niveau 2) : */

if (tab_grille[1][1]==joueur)
{
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(2,2);
}
if (tab_grille[1][8]==joueur)
{
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(2,7);
}
if (tab_grille[8][1]==joueur)
{
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(7,2);
}
if (tab_grille[8][8]==joueur)
{
if (prochain_joueur==joueur) TesterCase(8,7);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(7,7);
}

/* puis on teste les 24 autres cases "par balayage" du damier */

if (tab_grille[1][1]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(i,4-i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(i,5-i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(i,6-i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7-i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(i,8-i); /* 7 cases en diagonales */
}
if (tab_grille[1][8]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(i,5+i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(i,4+i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(i,3+i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2+i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(i,1+i); /* 7 cases en diagonales */
}
if (tab_grille[8][1]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(5+i,i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(4+i,i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(3+i,i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2+i,i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(1+i,i); /* 7 cases en diagonales */
}
if (tab_grille[8][8]==joueur)
{
for (i=1;i<=3;i++) if (prochain_joueur==joueur) TesterCase(5+i,9-i); /* 3 cases en diagonales */
for (i=1;i<=4;i++) if (prochain_joueur==joueur) TesterCase(4+i,9-i); /* 4 cases en diagonales */
for (i=1;i<=5;i++) if (prochain_joueur==joueur) TesterCase(3+i,9-i); /* 5 cases en diagonales */
for (i=1;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2+i,9-i); /* 6 cases en diagonales */
for (i=1;i<=7;i++) if (prochain_joueur==joueur) TesterCase(1+i,9-i); /* 7 cases en diagonales */
}

/* Si les cases V sont vides, et si la case J contient la couleur du joueur alors IL NE FAUT PAS JOUER DANS LA CASE 4
(sinon l'adversaire aura le coin au prochain coup). Dans ce cas on teste toutes les cases centrale et les autres bords.

-------------------------------------------------
| | | | | | | | |
| V | J | V | 4 | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| 4 | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| J | | | | | | | |
| | | | | | | | |
-------------------------------------------------
| | | | | | | | |
| V | | | | | | | |
| | | | | | | | |
-------------------------------------------------
*/

/* si l'ordinateur possède une case 2, il ne teste pas les cases de ce bord, mais teste les autres bords en priorité : */

/* teste les bords non adjacents aux coins si l'ordinateur NE POSSEDE PAS une case 2 sur ce bord : */
if (!((tab_grille[1][1]==0) && (tab_grille[2][1]==joueur) && (tab_grille[3][1]==0) && (tab_grille[4][1]==0) ||
(tab_grille[8][1]==0) && (tab_grille[7][1]==joueur) && (tab_grille[6][1]==0) && (tab_grille[5][1]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,1);
}
if (!((tab_grille[1][8]==0) && (tab_grille[2][8]==joueur) && (tab_grille[3][8]==0) && (tab_grille[4][8]==0) ||
(tab_grille[8][8]==0) && (tab_grille[7][8]==joueur) && (tab_grille[6][8]==0) && (tab_grille[5][8]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,8);
}

if (!((tab_grille[1][1]==0) && (tab_grille[1][2]==joueur) && (tab_grille[1][3]==0) && (tab_grille[1][4]==0) ||
(tab_grille[1][8]==0) && (tab_grille[1][7]==joueur) && (tab_grille[1][6]==0) && (tab_grille[1][5]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(1,i);
}

if (!((tab_grille[8][1]==0) && (tab_grille[8][2]==joueur) && (tab_grille[8][3]==0) && (tab_grille[8][4]==0) ||
(tab_grille[8][8]==0) && (tab_grille[8][7]==joueur) && (tab_grille[8][6]==0) && (tab_grille[8][5]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(8,i);
}

/* si l'ordinateur possède une case 2 il teste les cases centrales */
if ((tab_grille[1][1]==0) && (tab_grille[2][1]==joueur) && (tab_grille[3][1]==0) && (tab_grille[4][1]==0) ||
(tab_grille[8][1]==0) && (tab_grille[7][1]==joueur) && (tab_grille[6][1]==0) && (tab_grille[5][1]==0) ||
(tab_grille[1][8]==0) && (tab_grille[2][8]==joueur) && (tab_grille[3][8]==0) && (tab_grille[4][8]==0) ||
(tab_grille[8][8]==0) && (tab_grille[7][8]==joueur) && (tab_grille[6][8]==0) && (tab_grille[5][8]==0) ||
(tab_grille[1][1]==0) && (tab_grille[1][2]==joueur) && (tab_grille[1][3]==0) && (tab_grille[1][4]==0) ||
(tab_grille[1][8]==0) && (tab_grille[1][7]==joueur) && (tab_grille[1][6]==0) && (tab_grille[1][5]==0) ||
(tab_grille[8][1]==0) && (tab_grille[8][2]==joueur) && (tab_grille[8][3]==0) && (tab_grille[8][4]==0) ||
(tab_grille[8][8]==0) && (tab_grille[8][7]==joueur) && (tab_grille[8][6]==0) && (tab_grille[8][5]==0))
{
/* teste les cases centrales : */
for (i=3;i<=6;i++)
for (j=3;j<=6;j++)
if (prochain_joueur==joueur) TesterCase(i,j);
}

/* teste les lignes 2 et 7 si l'ordinateur NE POSSEDE PAS une case 2 sir ce bord : */
if (!((tab_grille[1][1]==0) && (tab_grille[2][1]==joueur) && (tab_grille[3][1]==0) && (tab_grille[4][1]==0) ||
(tab_grille[8][1]==0) && (tab_grille[7][1]==joueur) && (tab_grille[6][1]==0) && (tab_grille[5][1]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2);
}
if (!((tab_grille[1][8]==0) && (tab_grille[2][8]==joueur) && (tab_grille[3][8]==0) && (tab_grille[4][8]==0) ||
(tab_grille[8][8]==0) && (tab_grille[7][8]==joueur) && (tab_grille[6][8]==0) && (tab_grille[5][8]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7);
}

if (!((tab_grille[1][1]==0) && (tab_grille[1][2]==joueur) && (tab_grille[1][3]==0) && (tab_grille[1][4]==0) ||
(tab_grille[1][8]==0) && (tab_grille[1][7]==joueur) && (tab_grille[1][6]==0) && (tab_grille[1][5]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2,i);
}

if (!((tab_grille[8][1]==0) && (tab_grille[8][2]==joueur) && (tab_grille[8][3]==0) && (tab_grille[8][4]==0) ||
(tab_grille[8][8]==0) && (tab_grille[8][7]==joueur) && (tab_grille[8][6]==0) && (tab_grille[8][5]==0)))
{
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(7,i);
}

/************** Tests de cases conditionnels (comme au niveau 2) **********************/

/* teste les bords non adjacents aux coins si l'adversaire ne possède pas un coin de ce bord : */
for (i=3;i<=6;i++)
if ((tab_grille[1][1]!=adversaire) && (tab_grille[8][1]!=adversaire) && (prochain_joueur==joueur)) TesterCase(i,1);

for (i=3;i<=6;i++)
if ((tab_grille[8][8]!=adversaire) && (tab_grille[8][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(i,8);

for (i=3;i<=6;i++)
if ((tab_grille[1][1]!=adversaire) && (tab_grille[1][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(1,i);

for (i=3;i<=6;i++)
if ((tab_grille[8][1]!=adversaire) && (tab_grille[8][8]!=adversaire) && (prochain_joueur==joueur)) TesterCase(8,i);

/************** Tests de cases inconditionnels (comme pour le niveau 1) **********************/

/* teste les cases centrales : */
for (i=3;i<=6;i++)
for (j=3;j<=6;j++)
if (prochain_joueur==joueur) TesterCase(i,j);

/* teste les bords non adjacents aux coins : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,1);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,8);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(1,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(8,i);

/* teste les cases lignes 2 et 7 et colonnes 2 et 7 : */
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,2);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(i,7);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(2,i);
for (i=3;i<=6;i++) if (prochain_joueur==joueur) TesterCase(7,i);

/* en dernier recourt, teste les cases adjacentes aux coins */
if (prochain_joueur==joueur) TesterCase(2,1);
if (prochain_joueur==joueur) TesterCase(1,2);
if (prochain_joueur==joueur) TesterCase(7,1);
if (prochain_joueur==joueur) TesterCase(1,7);
if (prochain_joueur==joueur) TesterCase(8,2);
if (prochain_joueur==joueur) TesterCase(2,8);
if (prochain_joueur==joueur) TesterCase(7,8);
if (prochain_joueur==joueur) TesterCase(8,7);

if (prochain_joueur==joueur) TesterCase(2,2);
if (prochain_joueur==joueur) TesterCase(7,2);
if (prochain_joueur==joueur) TesterCase(2,7);
if (prochain_joueur==joueur) TesterCase(7,7);

break;

/* -------------------------- FIN DES NIVEAUX ------------------------------------------------------------------*/

} /* switch */

}

/********************************************************************************************************************/
/* Gestionnaire de touches enfoncées */
/********************************************************************************************************************/

void TraitementTouche(GdkEvent *ev)
{
int x,y;

switch (ev->key.keyval)
{
//-------------------------------------------------------------------------------------------------------------------

case 65360 : /* touche origine : on recommence une nouvelle partie */
TracerGrille(TRUE);
break;

//-------------------------------------------------------------------------------------------------------------------

case 98 : /* touche B : l'ordinateur joue pour les BLANCS */
OrdinateurJoue(4,1); /* OrdinateurJoue(Fenetre,niveau,joueur) */
break;

//-------------------------------------------------------------------------------------------------------------------

case 110 : /* touche N : l'ordinateur joue pour les NOIRS */
OrdinateurJoue(4,2); /* OrdinateurJoue(Fenetre,niveau,joueur) */
break;

//-------------------------------------------------------------------------------------------------------------------

case 65361 : /* touche flèche GAUCHE : on annule la dernière action */
/* on ne fait rien si index_tab==0 */
if (index_tab>1)
{
index_tab--;
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
tab_grille[x][y]=tab_partie[index_tab][x][y];
RedessinerJeu();
/* change la couleur du prochain joueur */
if (prochain_joueur==1)
{
prochain_joueur=2;
noir_auto=-1; /* les noirs jouent en manuel */
}
else
{ prochain_joueur=1;}
blanc_auto=-1; /* les blancs jouent en manuel */

}
else if (index_tab==1)
{
TracerGrille(FALSE);
/* trace les 4 pionts de départ */
/* 1 = blanc et 2 = noir */
DessinerPiont(4,4,1,0);
DessinerPiont(4,5,2,0);
DessinerPiont(5,4,2,0);
DessinerPiont(5,5,1,0);
prochain_joueur=2;
index_tab=0;
}
break;

//-------------------------------------------------------------------------------------------------------------------

case 65363 : /* touche flèche DROITE : on rectifie la dernière action annulée */
if (index_tab<index_max)
{
index_tab++;
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
tab_grille[x][y]=tab_partie[index_tab][x][y];
RedessinerJeu();
}
/* change la couleur du prochain joueur */
if (prochain_joueur==1)
{ prochain_joueur=2;}
else
{ prochain_joueur=1;}

break;

//-------------------------------------------------------------------------------------------------------------------

case 65470 : /* touche F1 : on bascule les blancs entre le mode manuel et le mode automatique */
if (blanc_auto==-1) blanc_auto=4;
else blanc_auto=-1;
break;

//-------------------------------------------------------------------------------------------------------------------

case 65471 : /* touche F2 : on bascule les noirs entre le mode manuel et le mode automatique */
if (noir_auto==-1) noir_auto=4;
else noir_auto=-1;
break;

//-------------------------------------------------------------------------------------------------------------------

case 65307 : /* touche ESC : on quitte le jeu */
fini=TRUE;
break;

//-------------------------------------------------------------------------------------------------------------------

case 114 : /* touche R : on active ou désactive l'allumage de la lumière rouge sur le piont joué */
if (allumer_piont==1) allumer_piont=0; else allumer_piont=1;
break;

//-------------------------------------------------------------------------------------------------------------------

} /* switch */

}

/********************************************************************************************************************/
/* Programme principal */
/********************************************************************************************************************/

int main(int argc, char *argv[])
{

GdkWindowAttr attr;
GdkEvent *ev;

int debut_jeu=1;

attr.width = 50*8+400;
attr.height = 50*8;
attr.wclass = GDK_INPUT_OUTPUT;
attr.window_type = GDK_WINDOW_TOPLEVEL;

/* liste des évènements pris en charge par le gestionnaire d'évènements ci-dessous (la boucle while) */
attr.event_mask =
GDK_BUTTON_PRESS_MASK |
GDK_KEY_PRESS_MASK;

gdk_init(&argc, &argv);

/* Création de la fenêtre */
fenetre = gdk_window_new(NULL, &attr, 0);

/* Affichage de la fenetre */
gdk_window_show(fenetre);

 

/* Boucle d'attente principale des événements */
while (!fini)
{
if (gdk_events_pending())
{
ev = gdk_event_get();
if (ev)
{
switch (ev->type)
{
case GDK_DELETE:
/* Si on recoit l'événement delete,
* on met fin à l'application
*/
fini = TRUE;
break;
case GDK_BUTTON_PRESS:
TraitementButtonPress((GdkEventButton *)ev);
break;

case GDK_KEY_PRESS:
TraitementTouche(ev);
break;

default:
{
if (debut_jeu)
{ TracerGrille(TRUE);
debut_jeu=0;
}
RedessinerJeu();
}
}
gdk_event_free(ev);
}
}

/* pendant l'attente d'un joueur, le programme tourne dans cette boucle principale */

/* si blanc_auto == -1 alors les blancs jouent en manuel */
/* si blanc_auto != -1 alors l'ordinateur joue pour les blancs, et blanc_auto contient le niveau des BLANCS */
if ((blanc_auto!=-1) && (prochain_joueur==1) && (jeu_fini==0))
{
OrdinateurJoue(blanc_auto,1);
}


/* si noir_auto == -1 alors les noirs jouent en manuel */
/* si noir_auto != -1 alors l'ordinateur joue pour les noirs, et noir_auto contient le niveau des NOIRS */
if ((noir_auto!=-1) && (prochain_joueur==2) && (jeu_fini==0))
{
OrdinateurJoue(noir_auto,2);
}

}
return 0;
}

Si vous avez testé le jeu reversi (ou othello, au choix ...) ci-dessus vous avez pu constater que l'ordinateur est très fort : il arrive toujours à s'emparer des coins sans que vous ne puissiez l'en empêcher. Voici une solution pour gagner contre l'ordinateur (en prenant notamment les 4 coins) : 60 pionts NOIRS (vous) contre 4 pionts BLANCS (l'ordinateur) en fin de partie ! Cette grille (qui n'est ni unique ni la meilleure solution) vous indique l'ordre des cases dans lequel vous devez jouer le piont NOIR :

32
 
 
31
10
 
26
23
11
30
9
 
 
 
28
 
 
29
 
 
25
 
20
21
3
 
1
 
 
 
19
 
 
13
 
 
 
2
 
16
4
5
 
6
12
17
 
18
 
 
 
 
 
 
27
 
22
8
 
7
14
 
15
24

 

Retour en haut de la page

Utilisation de l'API GTK+ pour programmer en mode graphique

Notre programme en C utilisant les fonctions de la librairie GDK commence par la ligne suivante :

#include <gtk/gtk.h>

Il faut donc vérifier si le fichier d'en-tête gtk.h est bien présent dans le répertoire /usr/include :

locate gtk.h

Le programme locate nous répond que l'emplacement du fichier gtk.h est /usr/include/gtk-2.0/gtk/gtk.h

Interrogeons le programme apt-file pour savoir quel paquet .DEB a installé le fichier gtk.h :

apt-file search /usr/include/gtk-2.0/gtk/gtk.h

Le programme apt-file nous répond que le fichier gtk.h a été installé par le paquet libgtk2.0-dev

Interrogeons le programme pkg-config pour savoir quel est le nom exact de la librairie gdk :

pkg-config --list-all | grep gtk

Nous trouvons dans la liste plusieurs librairies contenant gtk dans leur nom (sous Ubuntu 10.04) dont gtk+-x11-2.0 et gtk+-2.0. Nous utiliserons la librairie gtk+-2.0.

Demandons à pkg-config quelle est le numéro exact de version de gtk+-2.0 actuellement installé dans le système :

pkg-config --modversion gtk+-2.0

Pkg-config nous répond 2.20.1

Demandons à pkg-config quel est l'ensemble des librairies dynamiques utilisées par l'éditeur de liens lors de la compilation d'un programme source en C utilisant gtk+-2.0 :

pkg-config --libs gtk+-2.0

Pkg-config nous donne une liste de 17 librairies.

Demandons à pkg-config quelle est la liste des répertoires dans lesquels il faudra rechercher les fichiers d'en-tête .h lors de la compilation d'un programme source en C utilisant gtk+-2.0 :

pkg-config --cflags gtk+-2.0

Pkg-config nous donne une liste de 12 répertoires (qui sont soit des sous-répertoires de /usr/include soit des sous-répertoires de /usr/lib) dont le répertoire /usr/include/gtk-2.0/. Comme le fichier d'entête gtk.h se trouve dans le sous-répertoire gtk du répertoire /usr/include/gtk-2.0/, et que le répertoire /usr/include/gtk-2.0/gtk/ ne fait pas partie de la liste donnée par pkg-config --cflags, il faudra alors mettre la ligne #include <gtk/gtk.h> dans le programme source et non simplement #include <gtk.h>.

Voici un exemple de programme utilisant GTK+. Ce programme dessine l'ensemble de Mandelbrot dans une fenêtre GTK+. Pour utiliser ce code source :

/*****************************************************************************/
/*
                     Programme de base en GTK                             */
/*****************************************************************************/

#include <gtk/gtk.h>

/*****************************************************************************/
/* Déclaration des variables globales */
/*****************************************************************************/

GtkWidget *Fenetre,*boite_dialog_h,*boite_dialog_v,*ZoneDessin,*bouton;

struct complexe
{
float x, y;
}
;

struct complexe z1, z2, z;

float x_min=-2.0, x_max=2.0, y_min=-2.0, y_max=2.0, nouveau_x_min, nouveau_x_max, nouveau_y_min,
nouveau_y_max;

/**************************************************************************/

void
somme (struct complexe z1, struct complexe z2)
{
z.x = z1.x + z2.x;
z.y = z1.y + z2.y;

}

/**************************************************************************/

void
produit (struct complexe z1, struct complexe z2)
{
z.x = z1.x * z2.x - z1.y * z2.y;
z.y = z1.x * z2.y + z1.y * z2.x;

}

/*****************************************************************************/
/* Prototypes des fonctions */
/*****************************************************************************/

void CreerInterface();
gboolean Dessine(GtkWidget *ZoneDessin, GdkEventExpose *ev);

/*****************************************************************************/
/* P R O G R A M M E P R I N C I P A L */
/*****************************************************************************/

int main(int argc, char *argv[])
{

/* Initialisation des bibliothèques */
gtk_init(&argc, &argv);

/*Création de l'interface */
CreerInterface();

/* On affiche l'interface */
gtk_widget_show_all(Fenetre);

/* La boucle principale */
gtk_main();
return 0;
}

/*****************************************************************************/
/* Définition des fonctions */
/*****************************************************************************/

 

/*****************************************************************************/
/* Cette fonction crée la fenetre principale et tous ses éléments */
/*****************************************************************************/

void CreerInterface()
{
// La fenetre principale :
/* Création de la fenêtre */
Fenetre = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(Fenetre),
"Test de GTK");
/* Définition de la taille initiale de la fenêtre : */
gtk_widget_set_usize(Fenetre, 600, 500);

/* Connexion des signaux "delete" et "destroy" */
gtk_signal_connect(GTK_OBJECT(Fenetre), "delete_event",
(GtkSignalFunc)gtk_exit, NULL);
gtk_signal_connect(GTK_OBJECT(Fenetre), "destroy",
(GtkSignalFunc)gtk_exit, NULL);

//--------------------------------------------------------------------
// La boite de dialogue horizontale :
boite_dialog_h=gtk_hbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(Fenetre),boite_dialog_h);

//--------------------------------------------------------------------
// La zone de dessin :

/* Création et attachement de la zone de
* dessin dans la fenêtre */
ZoneDessin = gtk_drawing_area_new();

gtk_box_pack_start(GTK_BOX(boite_dialog_h),ZoneDessin,FALSE,FALSE,0);

gtk_drawing_area_size(GTK_DRAWING_AREA(ZoneDessin),
500, 500);
/* Connexion du signal "expose_event" */
gtk_signal_connect(GTK_OBJECT(ZoneDessin), "expose_event",
(GtkSignalFunc)Dessine, NULL);

//--------------------------------------------------------------------
// La boite de dialogue verticale :
boite_dialog_v=gtk_vbox_new(FALSE,0);
gtk_box_pack_end(GTK_BOX(boite_dialog_h),boite_dialog_v,FALSE,FALSE,0);

/* Définition de la taille initiale de la boite : */
gtk_widget_set_usize(boite_dialog_v, 100, 500);

bouton=gtk_check_button_new_with_label("Bouton 1");
gtk_box_pack_start(GTK_BOX(boite_dialog_v),bouton,FALSE,FALSE,0);

bouton=gtk_check_button_new_with_label("Bouton 2");
gtk_box_pack_start(GTK_BOX(boite_dialog_v),bouton,FALSE,FALSE,0);

bouton=gtk_button_new_with_label("Bouton 3");
gtk_box_pack_start(GTK_BOX(boite_dialog_v),bouton,FALSE,FALSE,0);

bouton=gtk_button_new_with_label("Bouton 4");
gtk_box_pack_start(GTK_BOX(boite_dialog_v),bouton,FALSE,FALSE,0);

bouton=gtk_button_new_with_label("Quitter");
gtk_box_pack_end(GTK_BOX(boite_dialog_v),bouton,FALSE,FALSE,0);
gtk_signal_connect(GTK_OBJECT(bouton),"clicked",GTK_SIGNAL_FUNC(gtk_main_quit),NULL);

}

/*****************************************************************************/
/* Cette fonction dessine dans la zonee de dessin */
/*****************************************************************************/

gboolean Dessine(GtkWidget *ZoneDessin, GdkEventExpose *ev)
{
GdkColor gdk_color;
GdkColormap *colormap;
GdkGC *gc;
int i,x,y;
gint couleur;

/* On récupère la colormap de la zone de dessin */
colormap = gdk_window_get_colormap(ZoneDessin->window);
/* On crée la couleur blanche */
gdk_color.red = 65535;
gdk_color.green = 65535;
gdk_color.blue = 65535;
gdk_color_alloc(colormap, &gdk_color);
/* On rend le fond de la fenêtre blanc */
gdk_window_set_background(ZoneDessin->window, &gdk_color);

/* On récupère le GC par défaut de la fenêtre */
gc = gdk_gc_new(ZoneDessin->window);

/* On alloue la couleur bleue */
gdk_color.red = 0;
gdk_color.green = 0;
gdk_color.blue = 65535;
gdk_color_alloc(colormap, &gdk_color);
/* La couleur bleue nous servira pour dessiner */
gdk_gc_set_foreground(gc, &gdk_color);

/* On récupère le GC par défaut de la fenêtre */
gc = gdk_gc_new(ZoneDessin->window);

for (x = 0; x < 500; x++)
for (y = 0; y < 500; y++)
{
couleur = 0;
z1.x = x * (x_max - x_min) / 499 + x_min;
z1.y = y * (y_max - y_min) / 499 + y_min;
z2 = z1;
while ((z1.x * z1.x + z1.y * z2.y < 4) && (couleur < 650))
{
produit (z1, z1);
somme (z, z2);
z1 = z;
couleur++;
}


/* On alloue la couleur */
gdk_color.red = 0;
gdk_color.green = couleur*100;
gdk_color.blue = couleur*100;
gdk_color_alloc(colormap, &gdk_color);
/* La couleur nous servira pour dessiner */
gdk_gc_set_foreground(gc, &gdk_color);

gdk_draw_point(ZoneDessin->window, gc,x,y);
}

/* On détruit le GC dont on n'a plus besoin */
gdk_gc_destroy(gc);
return TRUE;
}

 

Voyons maintenant comment concevoir rapidement une interface graphique GTK+ avec Glade et comment l'intégrer dans un programme en C.

Il faut avant tout savoir que :

Installation de Glade et de libglade sous Ubuntu : il faut installer les paquets glade et libglade2-0.

Vérification de l'installation :

Procédure pour obtenir un programma exécutable utilisant l'interface graphique créée dans Glade 3.6.7 :

/********************************************************************************/
/* Ce programme toto.c appelle une interface graphique au format libglade       */
/* toto.glade a été réalisée dans Glade 3.6.7 sous Ubuntu 10.04                 */
/*                                                                              */
/* Compilation : gcc toto.c $(pkg-config --libs --cflags gtk+-2.0 libglade-2.0) */
/*                                                                              */
/*               Programme réalisé par Jean-Christophe MICHEL                   */
/*                            Février 2011                                      */
/*                            www.gecif.net                                     */
/********************************************************************************/

#include <gtk/gtk.h>
#include <glade/glade.h>

int main(int argc,char **argv)
{
     gtk_init(&argc,&argv);
     GtkWidget* ptr; /* pointeur vers un Widget */
     GladeXML *xml;

     xml = glade_xml_new("toto.glade",NULL,NULL);
     ptr = glade_xml_get_widget(xml,"window1"); /* crée un pointeur vers la fenêtre */

     gtk_widget_show_all(ptr); /* appelle la fenêtre */
     gtk_main();
     return 0;
}

Important : le nom du widget appelé par la fonction glade_xml_get_widget dans le code C doit être le même que le nom entré dans Glade lors de la conception de l'interface grpahique.

Pour l'instant ce tutoriel rapide ne dit pas encore comment récupérer dans le programme en C les évènements venant de l'interface utilisateur (état des boutons, des cases à cocher, ligne de saisie, affichage d'un message, etc ...). Le but principal est ici de donner la procédure de conversion Glade --> langage C et la ligne de commande de la compilation.

 

Retour en haut de la page

Utilisation de l'API Gnome pour programmer en mode graphique

Notre programme en C utilisant les fonctions de la librairie GNOME commence par la ligne suivante :

#include <gnome.h>

Il faut donc vérifier si le fichier d'en-tête gnome.h est bien présent dans le répertoire /usr/include :

locate gnome.h

Le programme locate nous répond que l'emplacement du fichier gnome.h est /usr/include/libgnomeui-2.0/gnome.h

Interrogeons le programme apt-file pour savoir quel paquet .DEB a installé le fichier gnome.h :

apt-file search /usr/include/libgnomeui-2.0/gnome.h

Le programme apt-file nous répond que le fichier gnome.h a été installé par le paquet libgnomeui-dev

Interrogeons le programme pkg-config pour savoir quel est le nom exact de la librairie gnome :

pkg-config --list-all | grep gnome

Nous trouvons dans la liste plusieurs librairies contenant gnome dans leur nom (sous Ubuntu 10.04) dont libgnome-2.0 et libgnomeui-2.0. Nous utiliserons la librairie libgnomeui-2.0.

Demandons à pkg-config quelle est le numéro exact de version de libgnomeui-2.0 actuellement installé dans le système :

pkg-config --modversion libgnomeui-2.0

Pkg-config nous répond 2.24.3

Demandons à pkg-config quel est l'ensemble des librairies dynamiques utilisées par l'éditeur de liens lors de la compilation d'un programme source en C utilisant libgnomeui-2.0 :

pkg-config --libs libgnomeui-2.0

Pkg-config nous donne une liste de plus de 30 librairies.

Demandons à pkg-config quelle est la liste des répertoires dans lesquels il faudra rechercher les fichiers d'en-tête .h lors de la compilation d'un programme source en C utilisant libgnomeui-2.0 :

pkg-config --cflags libgnomeui-2.0

Pkg-config nous donne une liste de plus de 30 répertoires (qui sont soit des sous-répertoires de /usr/include soit des sous-répertoires de /usr/lib).

Voici un exemple de programme utilisant Gnome. Ce programme dessine une mire de couleur en colorisant chaque pixel de la fenêtre avec une couleur différente. Pour utiliser ce code source :

/******************************************************************************************/
/*
                                                                                       */
/* Ce programme allume chaque pixel d'une aire de dessin un par un, en leur donnant une   */
/* couleur différente. Il montre ainsi comment utiliser le contexte graphique sous GNOME  */
/*                                                                                     
    */
/* Programme réalisé par Jean-Christophe MICHEL le 02 Janvier 2003                        */
/*                                                                                     
    */
/******************************************************************************************/

#include <gnome.h>

/* Interfaces des 3 fonctions définies plus bas : */

gint dessiner_les_pixels(gpointer data);
gint eventDelete(GtkWidget *widget,
GdkEvent *event,gpointer data);
gint eventDestroy(GtkWidget *widget,
GdkEvent *event,gpointer data);

#define WIDTH 655
#define HEIGHT 655

/******************************************************************************************/
/* Fonction MAIN */
/******************************************************************************************/

int main(int argc,char *argv[])
{
GtkWidget *app;
GtkWidget *area;

gnome_init("couleur","1.0",argc,argv);
app = gnome_app_new("mandelbrot","Colorisation des pixels");
gtk_signal_connect(GTK_OBJECT(app),"delete_event",
GTK_SIGNAL_FUNC(eventDelete),NULL);
gtk_signal_connect(GTK_OBJECT(app),"destroy",
GTK_SIGNAL_FUNC(eventDestroy),NULL);

area = gtk_drawing_area_new();
gtk_widget_set_usize(area,WIDTH,HEIGHT);
gnome_app_set_contents(GNOME_APP(app),area);

gtk_signal_connect(GTK_OBJECT(area),"event",
GTK_SIGNAL_FUNC(dessiner_les_pixels),NULL);

gtk_widget_show_all(app);
gtk_main();
exit(0);
}

/******************************************************************************************/
/* Fonction dessiner_les_pixels */
/******************************************************************************************/

gint dessiner_les_pixels(gpointer data) {

/* Déclaration des variables locales : */
gint x,y;
static GdkGC *gc=NULL;
static GdkColormap *colormap=NULL;
GdkColor color;
GtkWidget *widget=GTK_WIDGET(data);

if (colormap==NULL) {
/* la table de correspondance de couleurs du système est retrouvée par */
/* l'appel à la fonction gdk_colormap_get_system() : */
colormap=gdk_colormap_get_system();

/* création d'un nouveau contexte graphique permettant de dessiner */
/* dans la fenêtre spécifiée : */
gc=gdk_gc_new(widget->window);
}

/* On allume tous les pixels de la fenêtre un par un : */

for(x=0; x<WIDTH; x++) {
for(y=0; y<HEIGHT; y++) {

/* réglage de la couleur absolue du pixel, en 3 */
/* composantes RVB de 16 bits chacune : */
color.red=x*100;
color.green=y*100;
color.blue=(WIDTH-x)*100;

/* rend la couleur disponible : */
gdk_color_alloc(colormap,&color);

/* insère l'objet GdkColor (variable color) dans le contexte graphique */
/* graphique GdkGC (variable gc) en tant que couleur de premier plan : */
gdk_gc_set_foreground(gc,&color);

/* allume le pixel de coordonnées x et y en utilisant le contexte */
/* graphique gc : */
gdk_draw_point(widget->window,
gc,
x,
y);
}
}

return(0);
}

/******************************************************************************************/
/* Fonction eventDelete */
/******************************************************************************************/

gint eventDelete(GtkWidget *widget,
GdkEvent *event,gpointer data) {
return(FALSE);
}

/******************************************************************************************/
/* Fonction eventDestroy */
/******************************************************************************************/

gint eventDestroy(GtkWidget *widget,
GdkEvent *event,gpointer data) {
gtk_main_quit();
return(0);
}

 

Retour en haut de la page

Utilisation de l'API OpenGL pour programmer en mode graphique et en 3D

Notre programme en C utilisant les fonctions de l'interface OpenGL commence par la ligne suivante :

#include <GL/glut.h>

Il faut donc vérifier si le fichier d'en-tête glut.h est bien présent dans le répertoire /usr/include.

locate glut.h

La commande locate nous indique que le chemin exact du fichier d'en-tête est /urs/include/GL/glut.h

Interrogeons le programme apt-file pour savoir quel paquet .DEB a installé le fichier glut.h :

apt-file search /usr/include/GL/glut.h

Le programme apt-file nous répond que le fichier glut.h a été installé par le paquet freeglut3-dev

Interrogeons le programme pkg-config pour savoir quel est le nom exact de la librairie glut :

pkg-config --list-all | grep glut

Et là surprise : glut n'existe pas pour pkg-config. En effet, pkg-config ne connaît pas toutes les librairies du système mais seulement celles qui ont installé un fichier .pc dans le répertoire /usr/lib/pkgconfig lors de leur installation.

En allant voir le répertoire /usr/lib/pkgconfig on y trouve un fichier gl.pc et un fichier glu.pc (mais pas glut.pc).

En consultant ces deux fichiers .pc ou en demandant à pkg-config on constate que les seules librairies utiles lors de l'édition de liens sont GL et GLU (en majuscule).

L'utilisation de pkg-config n'est donc pas justifié pour OpenGL et les librairies utilisées seront indiquées "à la main" sur la ligne de commande de gcc lors de la compilation :

gcc toto.c -lGL -lGLU -lglut

Voici un exemple de base de programme en C qui utilise OpenGL. Pour utiliser ce code source :

/**************************************/
/* Programme de base en OpenGL        */
/* Réalisé par Jean-Christophe MICHEL */
/* Février 2011                       */
/* www.gecif.net                      */
/**************************************/

#include <GL/glut.h>

/********************************************************************************************************/
/* La fonction dessiner sera appelée chaque fois que GLUT détermine que la fenêtre doit être actualisée */
/********************************************************************************************************/

void dessiner(void)
{
 glClearColor(0,0,0,0);
/* définit la couleur de fond de la fenêtre */
 glClear(GL_COLOR_BUFFER_BIT); /* efface la fenêtre en utilisant la couleur de fond */

 glColor3f(0.2, 0.8, 1.0); /* définit la couleur RVB des objets */

/* glVertex3f crée un nouveau sommet dans l'espace */
/* Le point de coordonnées 0,0,0 est le centre de l'écran */
/* Les coordonnées vont de -1.0 à 1.0 en valeurs réelles */
/* Le système de coordonnées à 3 réels (3f) peut être considéré comme un système
de coordonnée relatives par rapport au centre de l'écran et non absolue dans
la fenêtre : si on redimentionne la fenêtre l'objet sera redimensionné */

 glBegin(GL_POLYGON); /* prépare dans le tampon un objet tracé sommet par sommet (ici un polygone) */
   glVertex3f(-0.25, 0.25, 0.0);
 
  glVertex3f(0.75, 0.25, 0.0);
   glVertex3f(0.75, 0.75, 0.0);
   glVertex3f(-0.25, 0.75, 0.0);

 glEnd();
/* fin de l'objet */

 glFlush(); /* vide le tampon dans la fenêtre en y ajoutant tous les objets préparés */
}

/*************************************************************************************************/
/*                          P R O G R A M M E         P R I N C I P A L                          */
/*************************************************************************************************/

int main(int argc, char **argv)
{

 glutInit(&argc, argv); /* initialise GLUT (Open GL Utility Toolkit) */

 /* prépare la fenêtre */
 glutInitDisplayMode(GLUT_RGB);
 glutInitWindowSize(600,600);
 glutInitWindowPosition(10,10);
 glutCreateWindow("Mon premier programme OpenGL");
 glutDisplayFunc(dessiner);
/* connecte la fonction de dessin */

 glutMainLoop(); /* affiche à l'écran toutes les fenêtres préparées */
 return 0; /* la norme C ANSI exige que la fonction main retourne un entier */
}

/*************************************************************************************************/
/*                            F I N      D U      P R O G R A M M E                              */
/*************************************************************************************************/


Remarques :

L'exemple suivant montre comment lire l'état des boutons de la souris et modifier en conséquence l'objet tracé à l'écran. Dans cet exemple :

/********************************************/
/* Programme de base en OpenGL              */
/* utilisant GLUT (Open GL Utility Toolkit) */
/* Réalisé par Jean-Christophe MICHEL       */
/* Février 2011                             */
/* www.gecif.net                            */
/********************************************/

/********************************************************************************************************/
/* Ce programme montre comment lire l'état des boutons de la souris grâce à GLUT. Dans cet exemple :    */
/*   - un clic gauche change la couleur de l'objet à l'écran                                            */
/*   - un clic droit change la forme de l'objet à l'écran                                               */
/********************************************************************************************************/

#include <GL/glut.h>

static GLfloat r,v,b,x1,y1; /* variables globales modifiées par les boutons de la souris */

/********************************************************************************************************/
/* La fonction dessiner sera appelée chaque fois que GLUT détermine que la fenêtre doit être actualisée */
/********************************************************************************************************/

void dessiner(void)
{

glClearColor(0,0,0,0); /* définit la couleur de fond de la fenêtre */
glClear(GL_COLOR_BUFFER_BIT); /* efface la fenêtre en utilisant la couleur de fond */

glColor3f(r, v, b); /* définit la couleur RVB des objets */

glBegin(GL_POLYGON); /* trace un objet sommet par sommet (ici un polygone) */
          glVertex3f(x1, y1, 0.0);
          glVertex3f(0.75, y1, 0.0);
          glVertex3f(0.75, 0.75, 0.0);
          glVertex3f(-0.25, 0.75, 0.0);
glEnd(); /* fin de l'objet */

glFlush(); /* vide le tampon dans la fenêtre en y ajoutant tous les objets préparés */

} /* dessiner */

/***************************************************************************************************/
/* La fonction traiter_souris sera appelée chaque fois que GLUT détecte un évènement sur la souris */
/***************************************************************************************************/

void traiter_souris(int bouton, int etat, int x, int y)
{

switch(bouton) {
case GLUT_LEFT_BUTTON:
/* détecte le bouton gauche */
          if (etat==GLUT_DOWN) /* détecte l'état "enfoncé" du bouton */
          {
                    if (v==0.0) v=1.0;
                    else if (v==1.0) v=0.5;
                    else if (v==0.5) v=0.0;
                    dessiner(); /* redessine l'objet avec les nouveaux paramètres */
          } /* if */
          break;
case GLUT_RIGHT_BUTTON:
/* détecte le bouton droit */
          if (etat==GLUT_UP) /* détecte l'état "relâché" du bouton */
          {
                    if (x1==-0.25) { x1=0.0; y1=0.9; }
                    else if (x1==0.0) { x1=0.5; y1=0.0; }
                    else if (x1==0.5) { x1=-0.25; y1=0.25; }
                    dessiner(); /* redessine l'objet avec les nouveaux paramètres */
          } /* if */
          break;
default:
          break;
}
/* switch */

} /* traiter_souris */

/*************************************************************************************************/
/*           P R O G R A M M E           P R I N C I P A L                                       */
/*************************************************************************************************/

int main(int argc, char **argv)
{

glutInit(&argc, argv); /* initialise GLUT */
r=1.0;
v=0.0;
b=0.0;
x1=-0.25;
y1=0.25;

/* prépare la fenêtre */
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(600,600);
glutInitWindowPosition(10,10);
glutCreateWindow("Cliquez dans la fenetre ! ");
glutMouseFunc(traiter_souris);
/* connecte la fonction de traitement des évènement souris */
glutDisplayFunc(dessiner); /* connecte la fonction de dessin */

glutMainLoop(); /* affiche à l'écran toutes les fenêtres préparées */
return 0; /* la norme C ANSI exige que la fonction main retourne un entier */

} /* main */

/*************************************************************************************************/
/*           F I N           D U           P R O G R A M M E                                     */
/*************************************************************************************************/

L'exemple suivant montre comment prendre en compte les évènements clavier avec GLUT. Dans cet exemple :

/********************************************/
/* Programme de base en OpenGL              */
/* utilisant GLUT (Open GL Utility Toolkit) */
/* Réalisé par Jean-Christophe MICHEL       */
/* Février 2011                             */
/* www.gecif.net                            */
/********************************************/

/***************************************************************************************/
/* Ce programme montre comment lire l'état du clavier grâce à GLUT. Dans cet exemple : */
/* - l'appuie sur la touche A change la couleur de l'objet à l'écran                   */
/* - l'appuie sur la touche B change la forme de l'objet à l'écran                     */
/* - l'appuie sur la touche Echap quitte le programme                                  */
/***************************************************************************************/

#include <GL/glut.h>

static GLfloat r,v,b,x1,y1; /* variables globales modifiées par les boutons de la souris */

/********************************************************************************************************/
/* La fonction dessiner sera appelée chaque fois que GLUT détermine que la fenêtre doit être actualisée */
/********************************************************************************************************/

void dessiner(void)
{

glClearColor(0,0,0,0); /* définit la couleur de fond de la fenêtre */
glClear(GL_COLOR_BUFFER_BIT); /* efface la fenêtre en utilisant la couleur de fond */

glColor3f(r, v, b); /* définit la couleur RVB des objets */

glBegin(GL_POLYGON); /* trace un objet sommet par sommet (ici un polygone) */
          glVertex3f(x1, y1, 0.0);
          glVertex3f(0.75, y1, 0.0);
          glVertex3f(0.75, 0.75, 0.0);
          glVertex3f(-0.25, 0.75, 0.0);
glEnd();
/* fin de l'objet */

glFlush(); /* vide le tampon dans la fenêtre en y ajoutant tous les objets préparés */

} /* dessiner */

/**********************************************************************************************/
/* La fonction traiter_clavier sera appelée chaque fois qu'une touche du clavier est enfoncée */
/**********************************************************************************************/

void traiter_clavier(unsigned char touche, int x, int y)
{


switch(touche) {
case 'a':
/* détecte la touche a */
case 'A':
          if (v==0.0) v=1.0;
          else if (v==1.0) v=0.5;
          else if (v==0.5) v=0.0;
          dessiner();
/* redessine l'objet avec les nouveaux paramètres */
          break;
case 'b':
/* détecte la touche b */
case 'B':
          if (x1==-0.25) { x1=0.0; y1=0.9; }
          else if (x1==0.0) { x1=0.5; y1=0.0; }
          else if (x1==0.5) { x1=-0.25; y1=0.25; }
          dessiner();
/* redessine l'objet avec les nouveaux paramètres */
          break;
case 27:
/* détecte la touche ESC */
          exit(0); /* quitte le programme */
          break;
default:
          break;
}
/* switch */

} /* traiter_clavier */

/*************************************************************************************************/
/*           P R O G R A M M E           P R I N C I P A L                                       */
/*************************************************************************************************/

int main(int argc, char **argv)
{

glutInit(&argc, argv); /* initialise GLUT */
r=1.0;
v=0.0;
b=0.0;
x1=-0.25;
y1=0.25;

/* prépare la fenêtre */
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(600,600);
glutInitWindowPosition(10,10);
glutCreateWindow("Mon premier programme OpenGL");
glutKeyboardFunc(traiter_clavier);
/*connecte la fonction de traitement des évènements clavier*/
glutDisplayFunc(dessiner); /* connecte la fonction de dessin */

glutMainLoop(); /* affiche à l'écran toutes les fenêtres préparées */
return 0; /* la norme C ANSI exige que la fonction main retourne un entier */

} /* main */

/*************************************************************************************************/
/*           F I N           D U           P R O G R A M M E                                     */
/*************************************************************************************************/

Le programme suivant montre comment réaliser la rotation dans l'espace d'un solide 3D toujours grâce à glut. Dans cet exemple :

/********************************************/
/* Rotation d'un solide 3D en OpenGL        */
/* Utilise GLUT (Open GL Utility Toolkit)   */
/* Réalisé par Jean-Christophe MICHEL       */
/* Février 2011                             */
/* www.gecif.net                            */
/********************************************/

#include <GL/glut.h>

typedef int BOOL;
#define TRUE 1
#define FALSE 0

static GLfloat angle = 0.0;
static BOOL Button1Down = FALSE, b_rotation=TRUE;
static GLfloat lx=0;
static GLfloat ly=0;
static int xclick=0;
static int yclick=0;
static int frame=0;
static int time=0;
static int timebase=0;
static GLfloat s=0;

/***************************************************************************************************/
/* La fonction traiter_souris sera appelée chaque fois que GLUT détecte un évènement sur la souris */
/***************************************************************************************************/

void traiter_souris(int bouton, int etat, int x, int y)
{

if (bouton == GLUT_LEFT_BUTTON)
{
Button1Down = (etat == GLUT_DOWN) ? TRUE : FALSE;
xclick = x;
yclick = y;

}
if (bouton == GLUT_RIGHT_BUTTON)
{
if (etat==GLUT_DOWN)
{
if (b_rotation) { b_rotation=FALSE; }
else { b_rotation=TRUE; }
}

}

}

/***************************************************************************************************/
/* La fonction mouvement_souris sera appelée lorsque la souris est déplacée en cliquant            */
/***************************************************************************************************/

void mouvement_souris(int x, int y)
{

if (Button1Down)
{
if (x>xclick){
              ly=ly+(xclick-x)*.5;
              xclick=x;}
if (x<xclick){
              ly=ly+(xclick-x)*.5;
              xclick=x;}
if (y>yclick){
              lx=lx+(yclick-y)*.5;
              yclick=y;}
if (y<yclick){
              lx=lx+(yclick-y)*.5;
              yclick=y;}
glutPostRedisplay();
}

}

/********************************************************************************************************/
/* La fonction dessiner sera appelée chaque fois que GLUT détermine que la fenêtre doit être actualisée */
/********************************************************************************************************/

void dessiner(void)
{

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0);
glClear (GL_COLOR_BUFFER_BIT);
glPushMatrix();

glColor3f(0,0,1);
glRotated(lx,1,0,0);
/* lx est l'angle de rotation en degré */
glRotated(ly,0,1,0); /* ly est l'angle de rotation en degré */
glRotated(angle,0,0,1);
glRotated((angle+5),1,1,0);

glTranslated(0,0,0);

glColor3f(0,0,1);
glutSolidCube(.5);
glColor3f(0,1,0);
glutWireCube(.5);

glTranslated(.5,0,0);

glColor3f(0,0,1);
glutSolidCube(.5);
glColor3f(0,1,0);
glutWireCube(.5);

glTranslated(-1,0,0);

glColor3f(0,0,1);
glutSolidCube(.5);
glColor3f(0,1,0);
glutWireCube(.5);

glTranslated(.5,.5,0);

glColor3f(0,0,1);
glutSolidCube(.5);
glColor3f(0,1,0);
glutWireCube(.5);

glTranslated(0,-.5,.5);

glColor3f(0,0,1);
glutSolidCube(.5);
glColor3f(0,1,0);
glutWireCube(.5);

glPopMatrix();
glPushMatrix();
glColor3f(1,1,1);
glTranslated(0,0,0);

glPopMatrix();
glEnd();

glFlush();
glutSwapBuffers();

}

/********************************************************************************************************/
/* La fonction animer sera appelée dès que le programme est en attende (aucun évènement détecté)        */
/********************************************************************************************************/

void animer (void)
{

if (b_rotation)
{
angle+=0.1;
if (angle>360.00f){
angle = 0.0;}


frame++;
time=glutGet(GLUT_ELAPSED_TIME);
if (time - timebase > 1000) {
s=(frame*1000.0/(time-timebase));
timebase = time;
frame = 0;
}
glutPostRedisplay();
}

}

/*************************************************************************************************/
/*                           P R O G R A M M E              P R I N C I P A L                    */
/*************************************************************************************************/

int main(int argc, char** argv)
{

glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Objet 3D avec GLUT !");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutDisplayFunc(dessiner);
glutMouseFunc (traiter_souris);
glutMotionFunc (mouvement_souris);
glutIdleFunc (animer);
/* définit la fonction qui sera exécutée en arrière plan */
glutMainLoop();
return 0;
/* la norme C ANSI exige que la fonction main retourne un entier */

}

/*************************************************************************************************/
/*                           F I N            D U           P R O G R A M M E                    */
/*************************************************************************************************/

Enfin le dernier exemple suivant montre une démonstration des différents objets 3D prédéfinis dans GLUT (cube, sphère, théière, dodécaèdre, tore, cone, etc.). Dans cet exemple :

/***********************************************/
/* Exemple de programme avec OpenGL            */
/* Objets 3D de GLUT (Open GL Utility Toolkit) */
/* Réalisé par Jean-Christophe MICHEL          */
/* Février 2011                                */
/* www.gecif.net                               */
/***********************************************/

/*****************************************************/
/* Action des touches du clavier pour ce programme : */
/*           s : change de solide                    */
/*           c : change de couleur                   */
/*           + : augmente le zoom                    */
/*           - : diminue le zoom                     */
/*           ESC : quitter                           */
/*                                                   */
/* Action de la souris pour ce programme :           */
/*     clic gauche : rotation manuelle               */
/*     clic droit : rotation automatique             */
/*****************************************************/

#include <GL/glut.h>

typedef int BOOL;
#define TRUE 1
#define FALSE 0

static GLfloat angle = 0.0;
static BOOL Button1Down = FALSE, b_rotation=FALSE;
static GLfloat lx=0;
static GLfloat ly=0;
static int xclick=0;
static int yclick=0;
static int frame=0;
static int time=0;
static int timebase=0;
static GLfloat s=0;
static int couleur=0;
static int solide=0;
static GLfloat zoom=0.5;

/***************************************************************************************************/
/* La fonction traiter_souris sera appelée chaque fois que GLUT détecte un évènement sur la souris */
/***************************************************************************************************/

void traiter_souris(int bouton, int etat, int x, int y)
{

if (bouton == GLUT_LEFT_BUTTON)
          {
          Button1Down = (etat == GLUT_DOWN) ? TRUE : FALSE;
          xclick = x;
          yclick = y;

          }
          if (bouton == GLUT_RIGHT_BUTTON)
          {
          if (etat==GLUT_DOWN) /* détecte l'état "enfoncé" du bouton */
                    {
                    if (b_rotation) { b_rotation=FALSE; }
                    else { b_rotation=TRUE; }
                    }

          }
}

/***************************************************************************************************/
/* La fonction mouvement_souris sera appelée lorsque la souris est déplacée en cliquant            */
/***************************************************************************************************/

void mouvement_souris(int x, int y)
{

if (Button1Down)
          {
          if (x>xclick){
                    ly=ly+(xclick-x)*.5;
                    xclick=x;}
          if (x<xclick){
                    ly=ly+(xclick-x)*.5;
                    xclick=x;}
          if (y>yclick){
                    lx=lx+(yclick-y)*.5;
                    yclick=y;}
          if (y<yclick){
                    lx=lx+(yclick-y)*.5;
                    yclick=y;}
          glutPostRedisplay();
          }
}

/********************************************************************************************************/
/* La fonction dessiner sera appelée chaque fois que GLUT détermine que la fenêtre doit être actualisée */
/********************************************************************************************************/

void dessiner(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0);
glClear (GL_COLOR_BUFFER_BIT);
glPushMatrix();

/* rotation manuelle : */
glRotated(lx,1,0,0); /* lx est l'angle de rotation en degré */
glRotated(ly,0,1,0); /* ly est l'angle de rotation en degré */

/* rotation automatique : */
glRotated(angle,0,0,1);
glRotated((angle+5),1,1,0);

switch(couleur) {
          case 0 : glColor3f(1,1,1);;
                    break;
          case 1 : glColor3f(0,0,1);;
                    break;
          case 2 : glColor3f(1,0,0);;
                    break;
          case 3 : glColor3f(0,1,1);;
                    break;
          case 4 : glColor3f(1,0,1);;
                    break;
          case 5 : glColor3f(1,1,0);;
                    break;
          case 6 : glColor3f(0,1,0);;
                    break;
          default :
                    break;
} /* switch */

switch(solide) {
          case 0 : glutWireTeapot(zoom);
                    break;
          case 1 : glutSolidTeapot(zoom);
                    break;
          case 2 : glutWireCube(zoom);
                    break;
          case 3 : glutSolidCube(zoom);
                    break;
          case 4 : glScalef(zoom,zoom,zoom) ;
                    glutWireOctahedron();
                    break;
          case 5 : glScalef(zoom,zoom,zoom) ;
                    glutSolidOctahedron();
                    break;
          case 6 : glScalef(zoom,zoom,zoom) ;
                    glutWireTetrahedron();
                    break;
          case 7 : glScalef(zoom,zoom,zoom) ;
                    glutSolidTetrahedron();
                    break;
          case 8 : glScalef(zoom,zoom,zoom) ;
                    glutWireIcosahedron();
                    break;
          case 9 : glScalef(zoom,zoom,zoom) ;
                    glutSolidIcosahedron();
                    break;
          case 10 : glutWireTorus(zoom/2,0.6,20,20);
                    break;
          case 11: glutSolidTorus(zoom/2,0.6,20,20);
                    break;
          case 12 : glutWireCone(zoom/2,1,20,20);
                    break;
          case 13 : glutSolidCone(zoom/2,1,20,20);
                    break;
          case 14 : glutWireSphere(zoom,20,20);
                    break;
          case 15 : glutSolidSphere(zoom,20,20);
                    break;
          case 16 : glScalef(zoom/2,zoom/2,zoom/2) ;
                    glutWireDodecahedron();
                    break;
          case 17 : glScalef(zoom/2,zoom/2,zoom/2) ;
                    glutSolidDodecahedron();
                    break;
          default :
                    break;
} /* switch */
glEnd();

glFlush();
glutSwapBuffers();
}

/********************************************************************************************************/
/* La fonction animer sera appelée dès que le programme est en attende (aucun évènement détecté)        */
/********************************************************************************************************/

void animer (void)
{
if (b_rotation)
          {
          /* rotation automatique : */
          angle+=0.1;
          if (angle>360.00f){
          angle = 0.0;}

          frame++;
          time=glutGet(GLUT_ELAPSED_TIME);
          if (time - timebase > 1000) {
          s=(frame*1000.0/(time-timebase));
          timebase = time;
          frame = 0;
          }
glutPostRedisplay();
}
}

/**********************************************************************************************/
/* La fonction traiter_clavier sera appelée chaque fois qu'une touche du clavier est enfoncée */
/**********************************************************************************************/

void traiter_clavier(unsigned char touche, int x, int y)
{

switch(touche) {
          case 's': /* change de solide */
          case 'S':
                    solide++;
                    if (solide>17) { solide=0; }
                    dessiner(); /* redessine l'objet avec les nouveaux paramètres */
                    break;
          case 'c': /* change de couleur */
          case 'C':
                    couleur++;
                    if (couleur>6) { couleur=0; }
                    dessiner(); /* redessine l'objet avec les nouveaux paramètres */
                    break;
          case '+': /* augmente le zoom */
                    if (zoom<1) { zoom=zoom+0.1; }
                    dessiner(); /* redessine l'objet avec les nouveaux paramètres */
                    break;
          case '-': /* diminue le zoom */
                    if (zoom>0.1) { zoom=zoom-0.1; }
                    dessiner(); /* redessine l'objet avec les nouveaux paramètres */
                    break;
          case 27: /* détecte la touche ESC */
                    exit(0); /* quitte le programme */
                    break;
          default:
                    break;
} /* switch */

} /* traiter_clavier */

/*************************************************************************************************/
/*           P R O G R A M M E           P R I N C I P A L                                       */
/*************************************************************************************************/

int main(int argc, char** argv)
{

glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Objets 3D avec GLUT !");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutDisplayFunc(dessiner);
glutMouseFunc (traiter_souris);
glutMotionFunc (mouvement_souris);
glutKeyboardFunc (traiter_clavier);
glutIdleFunc (animer); /* définit la fonction qui sera exécutée en arrière plan lorsqu'aucun évènement n'est détecté */
glutMainLoop();
return 0; /* la norme C ANSI exige que la fonction main retourne un entier */
}

/*************************************************************************************************/
/*           F I N           D U           P R O G R A M M E                                     */
/*************************************************************************************************/

 

Autres exemples de code source en C utilisant OpenGL :

Petite ballade dans un monde en 3D

Création d'un menu interactif et affichage d'un message textuel

Détection que la souris est sur un objet

Modification de la lumière

 

D'autres programmes source utilisant glut sont disponibles en exemple sur les sites suivants :

http://www.opengl.org/resources/code/samples/glut_examples/

http://zavie.free.fr/opengl/

http://raphaello.univ-fcomte.fr/ig/opengl/Glut.htm

Retour en haut de la page

Conclusion

Cette page vous a donné tous les éléments de base pour commencer à programmer en C sous Linux, mais surtout tous les outils pour analyser votre système, explorer les libraires, et faire évoluer votre environnement de développement C.