Skip to content

SpaceGames : Décollage de l’Astronef

15 décembre 2014


SpaceGames

Billet du 26 novembre 2012.
Édité le 15 décembre 2014 pour ajouter la version Python.

Je viens de retomber sur un livre de jeux en BASIC de mon enfance qui traînait avec mes vieux bouquins. C’est avec ce genre de petits programmes recopiés de livres ou de magazines que j’ai commencé mon apprentissage de la programmation sur ZX81.

Je me suis dit qu’il pourrait être intéressant de faire revivre ces petits programmes. Les débutants en programmation sont souvent plus intéressés quand on leur propose de créer des jeux plutôt que de résoudre des problèmes mathématiques ennuyeux.

C’est pourquoi j’ai repris le premier programme de ce livre, qui est très simple et s’appelle « Décollage d’astronef ». Après avoir examiné le programme en BASIC, je l’ai réécrit en C puis en Pascal puis (2 ans après :-) en Python.

Présentation

Voici la présentation donnée dans le livre :

Décollage d’astronef

Vous êtes le commandant d’un astronef qui s’est écrasé sur une planète étrangère et vous devez repartir au plus vite dans l’engin extra-terrestre que vous venez de capturer.
L’ordinateur de bord du vaisseau vous indique la gravité de la planète. Il vous reste à deviner la poussée nécessaire au décollage. Si vous l’avez sous-estimée, le mécanisme de sécurité du vaisseau empêchera que vous ne soyez réduit en cendres. Si, après dix essais, vous êtes toujours sur la planète, les extra-terrestres vous captureront.

Elle pourra être affichée à l’utilisateur au début de l’exécution.

Organigramme

Observez l’organigramme de ce jeu :

organigramme

Simple, non ? Essayez de le programmer avant de voir la solution.

Programme en Pascal

Program Astronef ;
(* Décollage de l'Astronef
 * =======================
 * Par Amine "nh2" Brikci-N, d'après D. Isaaman et J. Tyler
 * "Jeux électroniques Spacegames pour ZX Spectrum, ZX81, BBC, TRS-80,
 * Apple, VIC et PET" éd. Hachette Jeunesse 1983.
 *)
 
Const
    GRAVITE_MAX = 20 ;
    MASSE_MAX = 40 ;
    CHANCES = 10 ;
Var
    gravite,        (* gravité de la planète *)
    masse,          (* masse du vaisseau *) 
    poids, poussee, essai : integer;
    rep   : char;

Procedure Explications;
begin
 writeln('Vous êtes commandant d''un astronef qui s''est écrasé sur  ');
 writeln('une planète étrangère et vous devez repartir au plus vite  ');
 writeln('dans l''engin extra-terrestre que vous venez de capturer.  ');
 writeln('L''ordinateur de bord du vaisseau indique la gravité de    ');
 writeln('la planète. Il vous reste à deviner la poussée nécessaire  '); 
 writeln('au décollage. Si vous l''avez sous-estimée, le mécanisme de');
 writeln('sécurité du vaisseau empêchera que vous ne soyez réduit en ');
 writeln('cendres. Si, après dix essais, vous êtes toujours sur la   '); 
 writeln('planète, les extra-terrestres vous captureront.            ');
end;

Begin
    writeln('DÉCOLLAGE DE L''ASTRONEF');
    write('Des explications [O/n] ? ');
    readln(rep);
    if not((rep='n') or (rep='N')) then Explications;
    randomize;
    gravite := random(GRAVITE_MAX)+1 ;
    masse := random(MASSE_MAX)+1 ;
    poids := masse * gravite ;
    writeln('Gravité = ',gravite);
    write('Tapez la poussée : ');
    for essai := 1 to CHANCES do
    begin
        readln(poussee);
        if poussee = poids then
        begin
            writeln('C''est bon, decollez.');
            break
        end;
        if poussee > poids then
            writeln('Trop grand !')
        else
            writeln('Trop petit !');
        if essai < CHANCES then
            write('Essayez à nouveau : ')
        else
        begin
            writeln('Vous avez echoué.');
            writeln('Les extra-terrestres vous ont eu !')
        end
    end;
    writeln('La poussée nécessaire était ', poids);
End.

Des instructions if … then … else, une boucle for, rien de bien compliqué.

Les seules instructions particulières sont celles qui utilisent la procédure système Randomize et la fonction Random. Elles sont nécessaires pour générer des nombres « au hasard » (pseudo-aléatoires). Randomize initialise le générateur avec une « graine aléatoire » donnée par l’horloge système, pour que Random(n) puisse retourner un nombre entier qui ait l’air de vraiment être tiré au hasard entre 0 et n (n non compris).

La procédure Explications est appelée si l’utilisateur le désire. Elle ne fait qu’afficher la présentation.

Programme en C

/* Décollage de l'Astronef
 * =======================
 *   
 * Par Amine "nh2" Brikci-N, d'après D. Isaaman et J. Tyler
 * "Jeux électroniques Spacegames pour ZX Spectrum, ZX81, BBC, TRS-80,
 * Apple, VIC et PET" éd. Hachette Jeunesse 1983.
 * 
 * Fichier source : astronef.c
 * Compiler avec:
 * gcc -Wall astronef.c -o astronef -std=c99
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

void explications(void){
    puts("Vous êtes le commandant d'un astronef qui s'est écrasé sur ");
    puts("une planète étrangère et vous devez repartir au plus vite  ");
    puts("dans l'engin extra-terrestre que vous venez de capturer.   ");
    puts("L'ordinateur de bord du vaisseau vous indique la gravité de");
    puts("la planète. Il vous reste à deviner la poussée nécessaire  "); 
    puts("au décollage. Si vous l'avez sous-estimée, le mécanisme de ");
    puts("sécurité du vaisseau empêchera que vous ne soyez réduit en ");
    puts("cendres. Si, après dix essais, vous êtes toujours sur la   "); 
    puts("planète, les extra-terrestres vous captureront.            ");
}

#define GRAVITE_MAX 20
#define MASSE_MAX 40
#define CHANCES 10

/* rand_initialisee : indique si le générateur de nombres pseudo-
 * aléatoires été initialisé (1) ou pas (0)
 */
int rand_initialisee = 0; 

/* aleatoire : génère un nombre entier "au hasard" (pseudo-aléatoire)
 * Paramètres :
 *  -  min : valeur minimale
 *  -  max : valeur maximale
 * Si ce n'est pas encore fait, initialise le générateur de nombres
 * aléatoires et met à jour la variable globale rand_initialisee 
 */ 
int aleatoire(int min, int max){
    if (!rand_initialisee){
        srand(time(NULL)); // utilise l'horloge système pour la "graine"
        rand_initialisee = 1;
    }
    return (int) (min + (max - min) * 1.0 * rand() / RAND_MAX);
}

int main(void){
    puts("DÉCOLLAGE DE L'ASTRONEF\n");

    printf("Des explications [O/n] ? ");
    if (tolower(getchar())!='n')
        explications();

    int gravite = aleatoire(1, GRAVITE_MAX) ; // gravité de la planète
    int masse = aleatoire(1, MASSE_MAX) ;     // masse du vaisseau
    int poids = masse * gravite ;
    printf("\nGravité = %d\n", gravite);
    printf("Tapez la poussée : ");
    int poussee = 0;
    for (int essai=1 ; essai <= CHANCES && poussee != poids ; ++essai) {
        scanf("%d", &poussee);
        if (poussee > poids)
            puts("Trop grand !");
        else if (poussee < poids)
            puts("Trop petit !");
        else puts("C'est bon, décollez.");
        if (poussee != poids) {
            if (essai < CHANCES)
                printf("Essayez à nouveau : ");
            else {
                puts("Vous avez échoué.");
                puts("Les extra-terrestres vous ont eu !");
            }    
        }
    }
    printf("\nLa poussée nécessaire était %d.\n", poids);
    return EXIT_SUCCESS;
}

Là aussi, c’est simple. La boucle for du C est plus flexible ; j’en ai profité pour y mettre non seulement la condition qui teste le compteur mais aussi celle qui teste si le joueur a bien répondu. Ça évite d’utiliser l’instruction break comme je l’ai fait en Pascal.

Cette fois j’ai caché la fonction rand() (qui génère un nombre aléatoire en C) dans une fonction plus simple à utiliser. La fonction qui initialise le générateur aléatoire est srand(). Contrairement à Randomize du Pascal, elle n’utilise pas directement l’horloge, il faut lui donner la graine. Pour cela, on utilise toujours le résultat de la fonction time(), déclarée dans <time.h>, qui est le nombre de secondes passées depuis le 1er janvier 1970. N’hésitez pas à lancer les commandes man srand et man 3 time pour mieux comprendre comment cela fonctionne.

Programme en Python 3

# Décollage de l'Astronef
# =======================
# Par Amine "nh2" Brikci-N, d'après D. Isaaman et J. Tyler
# "Jeux électroniques Spacegames pour ZX Spectrum, ZX81, BBC, TRS-80,
# Apple, VIC et PET" éd. Hachette Jeunesse 1983.

# "constantes" : (pas de vraies constantes en Python)
GRAVITE_MAX = 20
MASSE_MAX = 40
CHANCES = 10

def explications():
    print("Vous êtes commandant d'un astronef qui s'est écrasé sur    ")
    print("une planète étrangère et vous devez repartir au plus vite  ")
    print("dans l'engin extra-terrestre que vous venez de capturer.   ")
    print("L'ordinateur de bord du vaisseau indique la gravité de     ")
    print("la planète. Il vous reste à deviner la poussée nécessaire  ") 
    print("au décollage. Si vous l'avez sous-estimée, le mécanisme de ")
    print("sécurité du vaisseau empêchera que vous ne soyez réduit en ")
    print("cendres. Si, après dix essais, vous êtes toujours sur la   ") 
    print("planète, les extra-terrestres vous captureront.            ")

print("DÉCOLLAGE DE L'ASTRONEF")
rep = input('Des explications [O/n] ? ')
if not((rep == 'n') or (rep == 'N')) :
    explications()
from random import randint
gravite = randint(1, GRAVITE_MAX)
masse = randint(1, MASSE_MAX)
poids = masse * gravite
print('Gravité = ', gravite)
print('Tapez la poussée : ', end = "")
for essai in range(1, CHANCES+1) :
    poussee = int(input())
    if poussee == poids :
        print("C'est bon, decollez.")
        break
    if poussee > poids :
        print('Trop grand !')
    else :
        print('Trop petit !')
    if essai < CHANCES :
        print('Essayez à nouveau : ', end = "")
    else :
        print('Vous avez echoué.')
        print('Les extra-terrestres vous ont eu !')
print('La poussée nécessaire était', poids);

La fonction randint() importée du module random permet de générer des nombres peudo-aléatoires entiers compris entre les valeurs du 1er et du 2e paramètre (tous deux inclus).

Autres langages

Javascript, PHP, etc… peut-être un autre jour…

Programme en BASIC

Voici une capture d’écran d’un émulateur de ZXSpectrum avec le programme (en anglais).

Source : WorldOfSpectrum.org

Vous pourrez remarquer qu’en Sinclair BASIC la fonction RND permet de générer un nombre pseudo-aléatoire décimal entre 0 et 1.

Programme Scratch

Voir ici

Publicités
Laisser un commentaire

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :