using Dates let # portée locale d = Dates.now() println("Daniel Hagnoul $d\n") end
Daniel Hagnoul 2020-11-04T16:29:48.732
Les fonctions sont des éléments fondamentaux du code.
Nous allons coder quelques éléments d'un jeu d'astéroïdes. Notre but n'est pas le jeu mais la construction et l'exécution de diverses fonctions.
J'ai volontairement largement utilisé le français pour les variables et les fonctions, Julia n'a pas de problèmes avec l'utf-8.
mutable struct Position x::Int y::Int end struct Taille largeur::Int hauteur::Int end #= Une chose est n'importe quoi qui existe dans la galaxie. Les sous-types concrets doivent avoir au moins deux propriétés : position et taille. =# abstract type Chose end # Fonctions qui s'appliquent à toutes les choses position(c::Chose) = c.position taille(c::Chose) = c.taille forme(c::Chose) = :unknown # types d'armes @enum Armes Laser Missile struct VaisseauSpatial <: Chose nom::String position::Position taille::Taille armes::Armes end forme(v::VaisseauSpatial) = :soucoupe_volante struct Astéroïde <: Chose nom::String position::Position taille::Taille end struct Rectangle sommet::Int gauche::Int bas::Int droit::Int #= Retourne les points : sommet, gauche, bas et droit Pour créer un Rectangle on doit écrire mon_rect = Rectangle(Position(10, 20), Taille(30, 20)) et pas mon_rect = Rectangle(40, 10, 20, 40) new() : fonction spéciale utilisée pour les constructeurs internes qui crée un nouvel objet du type =# Rectangle(p::Position, t::Taille) = new(p.y + t.hauteur, p.x, p.y, p.x + t.largeur) end # test s'il y a un chevauchement entre deux Rectangle function chevauchement(A::Rectangle, B::Rectangle) return A.gauche < B.droit && A.droit > B.gauche && A.sommet > B.bas && A.bas < B.sommet end function collision(A::Chose, B::Chose) rectA = Rectangle(position(A), taille(A)) rectB = Rectangle(position(B), taille(B)) return chevauchement(rectA, rectB) end # Le point d'exclamation indique que la Chose sera modifiée. déplacement_en_haut!(c::Chose, v::Int) = c.position.y -= v déplacement_en_bas!(c::Chose, v::Int) = c.position.y += v déplacement_à_gauche!(c::Chose, v::Int) = c.position.x -= v déplacement_à_droite!(c::Chose, v::Int) = c.position.x += v ast1 = Astéroïde("Véga", Position(0, 0), Taille(10, 20)) vs1 = VaisseauSpatial("Entreprise 1", Position(0, 0), Taille(30, 5), Missile) vs2 = VaisseauSpatial("Entreprise 2", Position(10, 0), Taille(30, 5), Laser) println("Position du vaisseau spatial $(vs1.nom) = $(position(vs1))\n") déplacement_en_bas!(ast1, 30) println("Position de l'astéroïde $(ast1.nom) = $(position(ast1))\n") println("Forme du vaisseau spatial $(vs2.nom) = $(forme(vs2))\n") println("Teste s'il y a collision entre $(vs1.nom) et $(vs2.nom) = $(collision(vs1, vs2))\n")
Position du vaisseau spatial Entreprise 1 = Main.##WeaveSandBox#253.Positio n(0, 0) Position de l'astéroïde Véga = Main.##WeaveSandBox#253.Position(0, 30) Forme du vaisseau spatial Entreprise 2 = soucoupe_volante Teste s'il y a collision entre Entreprise 1 et Entreprise 2 = true
#= Utilisation de mots-clés comme arguments. Les arguments de position (dans ce cas, n) et les arguments de mots-clés doivent être séparés par le caractère point-virgule. L'avantage, avoir des valeurs par défaut (ce n'est pas obligatoire) et ne pas devoir se rappeler de l'ordre d'insertion des mots-clés lors de l'appel de la fonction. =# function fabrique_astéroïde(n::Int ; nom = "Astéroïde", pos_range = 0:200, size_range = 10:30) pos_rand() = rand(pos_range) size_rand() = rand(size_range) return [Astéroïde("$nom #$i", Position(pos_rand(), pos_rand()), Taille(size_rand(), size_rand())) for i in 1:n] end function fabrique_vaisseau_spatial(n::Int ; nom = "Vaisseau_spatial", pos_range = 0:200, size_range = 10:30, arme::Armes = Missile) pos_rand() = rand(pos_range) size_rand() = rand(size_range) return [VaisseauSpatial("$nom #$i", Position(pos_rand(), pos_rand()), Taille(size_rand(), size_rand()), arme) for i in 1:n] end # Chose... : slurping arguments, aspirer les arguments pour créer un Array function tirer(origine::Chose, cibles::Chose...) println("type des cibles = $(typeof(cibles))\n") for cible in cibles println("$(origine.nom) abat $(cible.nom)") end end mes_astéroïdes = fabrique_astéroïde(5) mes_vaisseaux = fabrique_vaisseau_spatial(3) target1 = mes_astéroïdes[1] target2 = mes_astéroïdes[2] target3 = mes_astéroïdes[3] tirer(mes_vaisseaux[1], target2, target1, target3) println() # mes_astéroïdes[2:4]... : splatting arguments, exploser l'Array pour obtenir les arguments tirer(mes_vaisseaux[3], mes_astéroïdes[4:5]...)
type des cibles = Tuple{Main.##WeaveSandBox#253.Astéroïde,Main.##WeaveSandB ox#253.Astéroïde,Main.##WeaveSandBox#253.Astéroïde} Vaisseau_spatial #1 abat Astéroïde #2 Vaisseau_spatial #1 abat Astéroïde #1 Vaisseau_spatial #1 abat Astéroïde #3 type des cibles = Tuple{Main.##WeaveSandBox#253.Astéroïde,Main.##WeaveSandB ox#253.Astéroïde} Vaisseau_spatial #3 abat Astéroïde #4 Vaisseau_spatial #3 abat Astéroïde #5
# retourne, au hasard, une fonction déplacement function déplacement_aléatoire() return rand([déplacement_en_bas!, déplacement_à_gauche!, déplacement_à_droite!, déplacement_en_haut!]) end function saut_aléatoire!(c::Chose, déplacement_fonction::Function, distance::Int) déplacement_fonction(c, distance) return c end println("mes_vaisseaux[1] = $(mes_vaisseaux[1])\n") saut_aléatoire!(mes_vaisseaux[1], déplacement_aléatoire(), 25)
mes_vaisseaux[1] = Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatia l #1", Main.##WeaveSandBox#253.Position(103, 86), Main.##WeaveSandBox#253.T aille(29, 22), Main.##WeaveSandBox#253.Missile) Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatial #1", Main.##Weave SandBox#253.Position(103, 61), Main.##WeaveSandBox#253.Taille(29, 22), Main .##WeaveSandBox#253.Missile)
intact(s::VaisseauSpatial) = true # true pour le test mais normalement rand(Bool) function feu(f::Function, s::VaisseauSpatial) if intact(s) f(s) else println("Opération annulée car le vaisseau n'est pas intact") end return nothing end println("mes_vaisseaux[2] = $(mes_vaisseaux[2])\n") # fonction anonyme do-block feu(mes_vaisseaux[2]) do s déplacement_en_haut!(s, 100) println("$(s), missile tiré") déplacement_en_bas!(s, 100) end
mes_vaisseaux[2] = Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatia l #2", Main.##WeaveSandBox#253.Position(194, 134), Main.##WeaveSandBox#253. Taille(20, 24), Main.##WeaveSandBox#253.Missile) Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatial #2", Main.##Weave SandBox#253.Position(194, 34), Main.##WeaveSandBox#253.Taille(20, 24), Main .##WeaveSandBox#253.Missile), missile tiré
# fonction anonyme x -> function clean_up_galaxy(astéroïdes, vaisseaux) f = x -> println("explosion de $(x)") foreach(f, astéroïdes) foreach(f, vaisseaux) end clean_up_galaxy(mes_astéroïdes, mes_vaisseaux)
explosion de Main.##WeaveSandBox#253.Astéroïde("Astéroïde #1", Main.##Weave SandBox#253.Position(143, 155), Main.##WeaveSandBox#253.Taille(14, 11)) explosion de Main.##WeaveSandBox#253.Astéroïde("Astéroïde #2", Main.##Weave SandBox#253.Position(151, 189), Main.##WeaveSandBox#253.Taille(27, 12)) explosion de Main.##WeaveSandBox#253.Astéroïde("Astéroïde #3", Main.##Weave SandBox#253.Position(196, 169), Main.##WeaveSandBox#253.Taille(11, 13)) explosion de Main.##WeaveSandBox#253.Astéroïde("Astéroïde #4", Main.##Weave SandBox#253.Position(6, 140), Main.##WeaveSandBox#253.Taille(28, 20)) explosion de Main.##WeaveSandBox#253.Astéroïde("Astéroïde #5", Main.##Weave SandBox#253.Position(77, 88), Main.##WeaveSandBox#253.Taille(12, 22)) explosion de Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatial #1", Main.##WeaveSandBox#253.Position(103, 61), Main.##WeaveSandBox#253.Taille( 29, 22), Main.##WeaveSandBox#253.Missile) explosion de Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatial #2", Main.##WeaveSandBox#253.Position(194, 134), Main.##WeaveSandBox#253.Taille (20, 24), Main.##WeaveSandBox#253.Missile) explosion de Main.##WeaveSandBox#253.VaisseauSpatial("Vaisseau_spatial #3", Main.##WeaveSandBox#253.Position(14, 126), Main.##WeaveSandBox#253.Taille( 25, 10), Main.##WeaveSandBox#253.Missile)
Licence Creative Commons Attribution 2.0 Belgique