Créer un menu avec plusieurs propositions et y répondre


Introduction

Le programme doit présenter un menu avec 2 options (afficher le mot 'pomme' ou afficher le mot 'fraise')
L'utilisateur doit répondre en entrant le numéro d'index de l'un des 2 choix.
En fonction du choix, le programme renvoie le choix fait.
Je rajoute un petit bonus : effacer le shell au début de l'exécution du programme

Plusieurs versions de ce programme sont proposées ici, de la plus basique à la plus complexe (avec boucle en cas d'erreur de l'utilisateur et rupture de boucle)


Version 1 - Menu basique

Ecrivez le programme menu.asm suivant

section .data
 clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
 menu_prompt db '-------------------------', 10
 db '| Menu |', 10
 db '-------------------------', 10
 db 10
 db '| [1] - Afficher 'pomme'', 10
 db '| [2] - Afficher 'fraise'', 10
 db 10
 db '-------------------------', 10
 db '| Faîtes votre choix : ', 0
 menu_prompt_len equ $-menu_prompt
 apple_message db 10
 db 'Vous avez opté pour une pomme', 10
 db 10
 apple_len equ $-apple_message
 strawberry_message db 10
 db 'Vous avez opté pour une fraise', 10
 db 10
 strawberry_len equ $-strawberry_message

section .bss
 user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)

section .text
 global _start

_start:
 ; Effacer l'écran
 mov rax, 4
 mov rdi, 1
 mov rsi, clear_screen
 mov rdx, 4
 syscall

 ; Afficher le menu
 mov rax, 4
 mov rdi, 1
 mov rsi, menu_prompt
 mov rdx, menu_prompt_len
 syscall

 ; Lire le choix de l'utilisateur
 mov rax, 3
 mov rdi, 0
 mov rsi, user_choice
 mov rdx, 2
 syscall

 ; Vérifier le choix de l'utilisateur
 mov al, byte [user_choice]
 cmp al, '1'
 je display_apple
 cmp al, '2'
 je display_strawberry

 ; Si le choix n'est ni '1' ni '2', terminer le programme
 jmp exit

display_apple:
 ; Afficher 'pomme'
 mov rax, 4
 mov rdi, 1
 mov rsi, apple_message
 mov rdx, apple_len
 syscall
 jmp exit

display_strawberry:
 ; Afficher 'fraise'
 mov rax, 4
 mov rdi, 1
 mov rsi, strawberry_message
 mov rdx, strawberry_len
 syscall
 jmp exit

exit:
 ; Terminer le programme
 mov rax, 1
 xor rdi, rdi
 syscall

Assembler

nasm -f elf64 menu.asm

Linker

ld menu.o -o menu

Lancer le programme

./menu

Version 2 - Avec gestion d'erreur simple

Maintenant, comment gérer le fait que l'utilisateur se trompe et entre autre chose que 1 ou 2 ?
Eh bien, pour tout autre choix, il faut que le programme lui réponde qu'il n'a pas compris.
D'abord la version simple : le programme quitte après avoir affiché qu'il n'a pas compris.

section .data
 clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
 menu_prompt db '-------------------------', 10
 db '| Menu |', 10
 db '-------------------------', 10
 db 10
 db '| [1] - Afficher 'pomme'', 10
 db '| [2] - Afficher 'fraise'', 10
 db 10
 db '-------------------------', 10
 db '| Faîtes votre choix : ', 0
 menu_prompt_len equ $-menu_prompt
 apple_message db 10
 db 'Vous avez opté pour une pomme', 10
 db 10
 apple_len equ $-apple_message
 strawberry_message db 10
 db 'Vous avez opté pour une fraise', 10
 db 10
 strawberry_len equ $-strawberry_message
 invalid_choice_message db 10
 db 'Je n'ai pas compris votre choix', 10
 db 10
 invalid_choice_len equ $-invalid_choice_message

section .bss
 user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)

section .text
 global _start

_start:
 ; Effacer l'écran
 mov rax, 4
 mov rdi, 1
 mov rsi, clear_screen
 mov rdx, 4
 syscall

 ; Afficher le menu
 mov rax, 4
 mov rdi, 1
 mov rsi, menu_prompt
 mov rdx, menu_prompt_len
 syscall

 ; Lire le choix de l'utilisateur
 mov rax, 3
 mov rdi, 0
 mov rsi, user_choice
 mov rdx, 2
 syscall

 ; Vérifier le choix de l'utilisateur
 mov al, byte [user_choice]
 cmp al, '1'
 je display_apple
 cmp al, '2'
 je display_strawberry

 ; Si le choix n'est ni '1' ni '2', afficher un message d'erreur
 mov rax, 4
 mov rdi, 1
 mov rsi, invalid_choice_message
 mov rdx, invalid_choice_len
 syscall
 jmp exit

display_apple:
 ; Afficher 'pomme'
 mov rax, 4
 mov rdi, 1
 mov rsi, apple_message
 mov rdx, apple_len
 syscall
 jmp exit

display_strawberry:
 ; Afficher 'fraise'
 mov rax, 4
 mov rdi, 1
 mov rsi, strawberry_message
 mov rdx, strawberry_len
 syscall
 jmp exit

exit:
 ; Terminer le programme
 mov rax, 1
 xor rdi, rdi
 syscall

Version 3 - Avec boucle infinie

Maintenant, il faut pouvoir offrir une seconde (voir troisième) chance à l'utilisateur qui s'est trompé.
Nous allons donc introduire une boucle !

section .data
 clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
 menu_prompt db '-------------------------', 10
 db '| Menu |', 10
 db '-------------------------', 10
 db 10
 db '| [1] - Afficher 'pomme'', 10
 db '| [2] - Afficher 'fraise'', 10
 db 10
 db '-------------------------', 10
 db '| Faîtes votre choix : ', 0
 menu_prompt_len equ $-menu_prompt
 apple_message db 10
 db 'Vous avez opté pour une pomme', 10
 db 10
 apple_len equ $-apple_message
 strawberry_message db 10
 db 'Vous avez opté pour une fraise', 10
 db 10
 strawberry_len equ $-strawberry_message
 invalid_choice_message db 10
 db 'Je n'ai pas compris votre choix', 10
 db 'Veuillez faire un autre essai : ', 0
 invalid_choice_len equ $-invalid_choice_message

section .bss
 user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)

section .text
 global _start

_start:
 ; Effacer l'écran
 mov rax, 4
 mov rdi, 1
 mov rsi, clear_screen
 mov rdx, 4
 syscall

 ; Afficher le menu
 mov rax, 4
 mov rdi, 1
 mov rsi, menu_prompt
 mov rdx, menu_prompt_len
 syscall

loop :
 ; Lire le choix de l'utilisateur
 mov rax, 3
 mov rdi, 0
 mov rsi, user_choice
 mov rdx, 2
 syscall

 ; Vérifier le choix de l'utilisateur
 mov al, byte [user_choice]
 cmp al, '1'
 je display_apple
 cmp al, '2'
 je display_strawberry

 ; Si le choix n'est ni '1' ni '2', afficher un message d'erreur et reboucler
 mov rax, 4
 mov rdi, 1
 mov rsi, invalid_choice_message
 mov rdx, invalid_choice_len
 syscall
 jmp loop

display_apple:
 ; Afficher 'pomme'
 mov rax, 4
 mov rdi, 1
 mov rsi, apple_message
 mov rdx, apple_len
 syscall
 jmp exit

display_strawberry:
 ; Afficher 'fraise'
 mov rax, 4
 mov rdi, 1
 mov rsi, strawberry_message
 mov rdx, strawberry_len
 syscall
 jmp exit

exit:
 ; Terminer le programme
 mov rax, 1
 xor rdi, rdi
 syscall

Version 4 - Avec limite de 3 tentatives

Enfin, la dernière version : si l'utilisateur se trompe 3 fois, le programme doit lui dire Ciao et quitter !

section .data
 clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
 menu_prompt db '-------------------------', 10
 db '| Menu |', 10
 db '-------------------------', 10
 db 10
 db '| [1] - Afficher 'pomme'', 10
 db '| [2] - Afficher 'fraise'', 10
 db 10
 db '-------------------------', 10
 db '| Faîtes votre choix : ', 0
 menu_prompt_len equ $-menu_prompt
 apple_message db 10
 db 'Vous avez opté pour une pomme', 10
 db 10
 apple_len equ $-apple_message
 strawberry_message db 10
 db 'Vous avez opté pour une fraise', 10
 db 10
 strawberry_len equ $-strawberry_message
 invalid_choice_message db 10
 db 'Je n'ai pas compris votre choix', 10
 db 'Veuillez faire un autre essai : ', 0
 invalid_choice_len equ $-invalid_choice_message
 max_attempts_message db 10, 10
 db 'Trop de tentatives invalides. Au revoir !', 10
 db 10
 max_attempts_len equ $-max_attempts_message

section .bss
 user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)
 attempt_count resb 1 ; Réserve 1 octet pour compter le nombre de tentatives invalides

section .text
 global _start

_start:
 mov byte [attempt_count], 0 ; Initialiser le compteur de tentatives invalides à 0

 ; Effacer l'écran
 mov rax, 4
 mov rdi, 1
 mov rsi, clear_screen
 mov rdx, 4
 syscall

 ; Afficher le menu
 mov rax, 4
 mov rdi, 1
 mov rsi, menu_prompt
 mov rdx, menu_prompt_len
 syscall

loop:
 ; Lire le choix de l'utilisateur
 mov rax, 3
 mov rdi, 0
 mov rsi, user_choice
 mov rdx, 2
 syscall

 ; Vérifier le choix de l'utilisateur
 mov al, byte [user_choice]
 cmp al, '1'
 je display_apple
 cmp al, '2'
 je display_strawberry

 ; Si le choix n'est ni '1' ni '2', afficher un message d'erreur et incrémenter le compteur de tentatives
 mov rax, 4
 mov rdi, 1
 mov rsi, invalid_choice_message
 mov rdx, invalid_choice_len
 syscall

 inc byte [attempt_count] ; Incrémenter le compteur de tentatives invalides
 cmp byte [attempt_count], 3 ; Vérifier si le compteur a atteint 3
 je max_attempts_reached ; Sauter à max_attempts_reached si c'est le cas

 jmp loop ; Reboucler si le compteur n'a pas atteint 3

max_attempts_reached:
 ; Afficher le message de tentatives maximales atteintes
 mov rax, 4
 mov rdi, 1
 mov rsi, max_attempts_message
 mov rdx, max_attempts_len
 syscall
 jmp exit ; Quitter le programme

display_apple:
 ; Afficher 'pomme'
 mov rax, 4
 mov rdi, 1
 mov rsi, apple_message
 mov rdx, apple_len
 syscall
 jmp exit

display_strawberry:
 ; Afficher 'fraise'
 mov rax, 4
 mov rdi, 1
 mov rsi, strawberry_message
 mov rdx, strawberry_len
 syscall
 jmp exit

exit:
 ; Terminer le programme
 mov rax, 1
 xor rdi, rdi
 syscall


↑ Haut de page