From d62c8aefb0fb332697585fe1f01c0bad3a3e509e Mon Sep 17 00:00:00 2001 From: Dahmane Lynda <lynda.dahmane.etu@118p28.fil.univ-lille.fr> Date: Wed, 14 Feb 2024 09:53:11 +0100 Subject: [PATCH] Tp5 --- Tp5/minesweeper.zip | Bin 0 -> 12993 bytes Tp5/minesweeper/apl1test.py | 89 +++++++++++++ Tp5/minesweeper/cell.py | 125 ++++++++++++++++++ Tp5/minesweeper/graphicalboard.py | 174 +++++++++++++++++++++++++ Tp5/minesweeper/icons/0.gif | Bin 0 -> 99 bytes Tp5/minesweeper/icons/1.gif | Bin 0 -> 404 bytes Tp5/minesweeper/icons/10.gif | Bin 0 -> 393 bytes Tp5/minesweeper/icons/11.gif | Bin 0 -> 879 bytes Tp5/minesweeper/icons/12.gif | Bin 0 -> 658 bytes Tp5/minesweeper/icons/13.gif | Bin 0 -> 648 bytes Tp5/minesweeper/icons/2.gif | Bin 0 -> 668 bytes Tp5/minesweeper/icons/3.gif | Bin 0 -> 639 bytes Tp5/minesweeper/icons/4.gif | Bin 0 -> 649 bytes Tp5/minesweeper/icons/5.gif | Bin 0 -> 418 bytes Tp5/minesweeper/icons/6.gif | Bin 0 -> 660 bytes Tp5/minesweeper/icons/7.gif | Bin 0 -> 420 bytes Tp5/minesweeper/icons/8.gif | Bin 0 -> 427 bytes Tp5/minesweeper/icons/9.gif | Bin 0 -> 337 bytes Tp5/minesweeper/minesweeper.py | 204 ++++++++++++++++++++++++++++++ 19 files changed, 592 insertions(+) create mode 100644 Tp5/minesweeper.zip create mode 100644 Tp5/minesweeper/apl1test.py create mode 100755 Tp5/minesweeper/cell.py create mode 100644 Tp5/minesweeper/graphicalboard.py create mode 100644 Tp5/minesweeper/icons/0.gif create mode 100644 Tp5/minesweeper/icons/1.gif create mode 100644 Tp5/minesweeper/icons/10.gif create mode 100644 Tp5/minesweeper/icons/11.gif create mode 100644 Tp5/minesweeper/icons/12.gif create mode 100644 Tp5/minesweeper/icons/13.gif create mode 100644 Tp5/minesweeper/icons/2.gif create mode 100644 Tp5/minesweeper/icons/3.gif create mode 100644 Tp5/minesweeper/icons/4.gif create mode 100644 Tp5/minesweeper/icons/5.gif create mode 100644 Tp5/minesweeper/icons/6.gif create mode 100644 Tp5/minesweeper/icons/7.gif create mode 100644 Tp5/minesweeper/icons/8.gif create mode 100644 Tp5/minesweeper/icons/9.gif create mode 100755 Tp5/minesweeper/minesweeper.py diff --git a/Tp5/minesweeper.zip b/Tp5/minesweeper.zip new file mode 100644 index 0000000000000000000000000000000000000000..687e5f0b46b39c599e0898f6bbf214e5d9e55113 GIT binary patch literal 12993 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 Z)@is5WMu=DC_)TE498g+7@mMTd;o(4zv2J@ literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/apl1test.py b/Tp5/minesweeper/apl1test.py new file mode 100644 index 0000000..8533cca --- /dev/null +++ b/Tp5/minesweeper/apl1test.py @@ -0,0 +1,89 @@ +import thonnycontrib +from thonnycontrib.backend.evaluator import Evaluator +import thonnycontrib.backend.l1test_backend +from thonny.plugins.cpython_backend.cp_back import MainCPythonBackend +import thonnycontrib.backend.doctest_parser +from thonnycontrib.backend.doctest_parser import ExampleWithExpected, ExampleWithoutExpected +import thonnycontrib.backend.ast_parser +from thonnycontrib.backend.ast_parser import L1DocTest +import thonnycontrib.backend.verdicts +from thonnycontrib.backend.verdicts.ExceptionVerdict import ExceptionVerdict + +import inspect +import tempfile +import os +import sys + +class MockBackend(MainCPythonBackend): + """ + Fake backend. + """ + def __init__(self): + ... + + def send_message(self, msg) -> None: + ... + +# register backend +thonnycontrib.backend.l1test_backend.BACKEND = MockBackend() + +def l1test_to_org(filename: str, source: str=""): + """ + Return an org abstract of the tests presents in `filename` file. + """ + abstract = {'total': 0, + 'success': 0, + 'failures': 0, + 'errors': 0, + 'empty': 0} + + if source == "": + with open(filename, 'rt') as fin: + source = fin.read() + evaluator = Evaluator(filename=filename, + source=source) + tests = evaluator.evaluate() + n = len(tests) + abstract['total'] = n + res = "" + for test in tests: + examples = test.get_examples() + res_examples = "" + nb_test, nb_test_ok = 0, 0 + empty = True + for example in examples: + verdict = test.get_verdict_from_example(example) + if isinstance(example, ExampleWithExpected): + nb_test += 1 + if verdict.isSuccess(): + nb_test_ok += 1 + abstract['success'] += 1 + else: + abstract['failures'] += 1 + empty = False + if isinstance(verdict, ExceptionVerdict): + abstract['errors'] += 1 + empty = False + res_examples += f"** {verdict}\n\n" + if not verdict.isSuccess(): + res_examples += f" {verdict.get_details()}\n\n" + if not empty: + res += f"* {test.get_name()} ~ {nb_test_ok}/{nb_test} réussis\n\n" + else: + abstract['empty'] += 1 + res += f"* {test.get_name()}\n\n Aucun test trouvé !\n\n" + res += res_examples + res = f"Tests exécutés : {abstract['total']}\nSuccès: {abstract['success']}, \ +Echecs: {abstract['failures']}, Erreurs: {abstract['errors']}, \ +Vide: {abstract['empty']}\n\n" + res + return res + + +def testmod(modulename: str): + """ + mimic the doctest.testmod function + for `modulename` module + """ + print(l1test_to_org(modulename)) + + diff --git a/Tp5/minesweeper/cell.py b/Tp5/minesweeper/cell.py new file mode 100755 index 0000000..d182698 --- /dev/null +++ b/Tp5/minesweeper/cell.py @@ -0,0 +1,125 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`cell` module + +:author: + +:date: + + +""" + +class Cell: + + def __init__(self): + """ + initialize a new hidden cell of a minesweeper's grid. + existence of a bomb, number of bombs in neighborhood + have to be stated later. + + precondition: none + Examples: + + $$$ cel = Cell() + $$$ cel.is_bomb + False + $$$ cel.is_revealed + False + $$$ cel.nbombs_in_neighborhood + 0 + """ + + + self.is_bomb=False + self.is_revealed=False + self.nbombs_in_neighborhood=0 + + def incr_number_of_bombs_in_neighborhood(self): + """ + :return: None + :side effect: increment the number of bombs in neighborhood of self + precondition: none + Examples: + + $$$ cel = Cell() + $$$ cel.nbombs_in_neighborhood + 0 + $$$ cel.incr_number_of_bombs_in_neighborhood() + $$$ cel.nbombs_in_neighborhood + 1 + """ + + + self.nbombs_in_neighborhood+=1 + + def reveal(self): + """ + modify reveal state of self + precondition: none + Examples: + + $$$ cel = Cell() + $$$ cel.is_revealed + False + $$$ cel.reveal() + $$$ cel.is_revealed + True + """ + + self.is_revealed=True + + def set_bomb(self): + """ + put a bomb in self + + precondition: none + Examples: + + $$$ cel = Cell() + $$$ cel.is_bomb + False + $$$ cel.set_bomb() + $$$ cel.is_bomb + True + """ + + self.is_bomb=True + + def __str__(self): + """ + :return: a string representation of self state + :rtype: str + precondition: none + Examples: + + $$$ cel = Cell() + $$$ str(cel) == ' ' + True + $$$ cel.reveal() + $$$ str(cel) == '0' + True + $$$ cel.incr_number_of_bombs_in_neighborhood() + $$$ str(cel) == '1' + True + $$$ cel.set_bomb() + $$$ str(cel) == 'B' + True + """ + + + + if self.is_revealed: + if self.is_bomb: + return'B' + else: + return str(self.nbombs_in_neighborhood) + else: + + return' ' + +if (__name__ == '__main__'): + import apl1test + apl1test.testmod('cell.py') + diff --git a/Tp5/minesweeper/graphicalboard.py b/Tp5/minesweeper/graphicalboard.py new file mode 100644 index 0000000..3ec2941 --- /dev/null +++ b/Tp5/minesweeper/graphicalboard.py @@ -0,0 +1,174 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`graphicalboard` module + +:author: `FIL - IEEA - Univ. Lille1.fr <http://portail.fil.univ-lille1.fr>`_ + +:date: 2015, september, last revision: 2024, february + +This module implements some functions to draw a minesweeper game. The +graphical board uses buttons to draw each cell and maps the left-click +and right-click events to interact with the minesweeper. + +This module uses from :mod:`minesweeper`: + +* :method:`Minesweeper.reveal_all_cells_from` + +To draw and run a minesweeper game, one has to: + +* create a minesweeper game g +* create a graphical board from the minesweeper g + +""" + +import os +import tkinter as tk +from functools import partial +from cell import Cell +from minesweeper import * + +# the list of icons +img = [] + +def create(game: Minesweeper): + """ + This function creates the graphical board from a game. It also + launches the event loop. Thus, this is the only function to run to + have a functional graphical board. + """ + global img + # create a new Tk window + win = tk.Tk() + # define the window title + win.title('Minesweeper ({:d} bombs)'.format(game.nbombs)) + # load images + iconpath = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icons") + img = [ + tk.PhotoImage(file=os.path.join(iconpath, "0.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "1.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "2.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "3.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "4.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "5.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "6.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "7.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "8.gif")), + tk.PhotoImage(file=os.path.join(iconpath, "9.gif")), # unrevealed + tk.PhotoImage(file=os.path.join(iconpath, "10.gif")), # bomb explosed + tk.PhotoImage(file=os.path.join(iconpath, "11.gif")), # bomb discovered + tk.PhotoImage(file=os.path.join(iconpath, "12.gif")), # flag + tk.PhotoImage(file=os.path.join(iconpath, "13.gif")) # question + ] + # create the graphical board made of Tk buttons + width, height = game.width, game.height + board = [] + for i in range(width): + board.insert(i, []) + for j in range(height): + button = tk.Button(win, padx=0, pady=0, width=19, height=19, image=img[9]) + button.grid(column=i, row=j) + board[i].insert(j, button) + # bind the right-click event + button.bind("<Button-3>", + partial(__changeflag, board=board, game=game, x=i, y=j)) + # bind the left-click event + button.config(command=partial(__changestate, board, game, i, j)) + # event loop + win.mainloop() + +def __test_end(board: list[list[tk.Button]], game: Minesweeper): + """ + This function tests if the game is finished or not. In the first + case, depending on the state of the game, all graphical cells are + disabled or events are unbinded. + """ + state = game.state + if state == GameState.losing: + __disable_game(board, game) + elif state == GameState.winning: + __block_game(board, game) + +def __changestate(board: list[list[tk.Button]], + game: Minesweeper, + x: int, y: int): + """ + This function is called on left-click on a button. + + """ + game.reveal_all_cells_from(x, y) + __redraw(board, game, x, y) + __test_end(board, game) + +def __changeflag(evt, board: list[list[tk.Button]], + game: Minesweeper, + x: int, y: int): + """ + This function is called on right-click on a button. + """ + cel = game.get_cell(x, y) + # if not cel.is_hypothetic(): + # cel.set_hypothetic() + # else: + # cel.unset_hypothetic() + __redraw(board, game, x, y) + __test_end(board, game) + + +def __block_game(board: list[list[tk.Button]], + game: Minesweeper): + """ + This function is called once the player wins. The chosen behavior + is to let the board as it and to unbind events. + """ + width, height = (game.width, game.height) + for i in range(width): + for j in range(height): + button = board[i][j] + game.get_cell(i, j).reveal() + button.config(command="") + button.bind("<Button-3>", "") + __redraw(board, game, -1, -1) + +def __disable_game(board: list[list[tk.Button]], + game: Minesweeper): + """ + This function is called once the player looses. The chosen behavior + is to shade the board and to unbind events. + """ + width, height = game.width, game.height + for i in range(width): + for j in range(height): + button = board[i][j] + button.config(state=tk.DISABLED) + button.bind("<Button-3>", "") + + +def __redraw(board: list[list[tk.Button]], + game: Minesweeper, + x: int, y: int): + """ + This function draws the board. Positions x and y are used to test + which bomb icon has to be drawn. + """ + width, height = (game.width, game.height) + for i in range(width): + for j in range(height): + cel = game.get_cell(i, j) + button = board[i][j] + if cel.is_revealed: + if cel.is_bomb: + new_img = img[10] + if x == j and y == i: + new_img = img[11] + else: + new_img = img[cel.nbombs_in_neighborhood] + button.config(relief=tk.FLAT, image=new_img, command="") + else: + button.config(image=img[9]) + + +if __name__ == "__main__": + import apl1test + doctest.testmod('graphicalboard.py') diff --git a/Tp5/minesweeper/icons/0.gif b/Tp5/minesweeper/icons/0.gif new file mode 100644 index 0000000000000000000000000000000000000000..26d8a1024c3e988cc71d1f44e5eb9785a24920e8 GIT binary patch literal 99 zcmZ?wbhEHb6lM@+_{hM}-Q7KB&YYb)ckbG?OYtWQ0|@AV2#`DjlZi{;%Jj$li>;k+ zbbns3^RaBmJoc`|$L40NSeK?f<%8<^LaXbRe6MZqe`3{~^hh}&LPM~DiNP8G+AJkq literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/1.gif b/Tp5/minesweeper/icons/1.gif new file mode 100644 index 0000000000000000000000000000000000000000..fc817675c6f607b73904f16c369713edf2f914fc GIT binary patch literal 404 zcmZ?wbhEHb6lM@+_{zY*$oP+e;Xfnee`e-?tgL^zxqtKW{t^-SE-(LCQu3>$<Tn|a zFFHE!%*|if+P+Xw_#7X9J1XjKM8v(=*gKh-*K=~NrKH>}E4x%#d9kA6lB?@eH@7F< z-Q9EM%$_r6&dQbhSFhf;YSsSr>-X;6yM6oiUE8+p-mqcMjvYI9?%cU+*N)x0ckJ4= zbN6mAZ`ZCpdv@&Ev$LV$Tw~+8&d$>_W*nU}=g9Kq2Ue^&z<>iN{$v5m=zvI&pBUIS zI`pM`sFYb9U3lSYmR0PUpp!RCc%xV3l$Caw>Zt3kDivMrBH-*Gd~K5LjWw&DNw8dd z`^MUDlI^?loTO?EEeY0!#>(VWEfFqmPL{6bR1GyVa}(|<dDFDDwG=t#R!xhRUs5r( zAW3`W(w?;%n)=ELtE9E`HJ7c`HW8N;WiRIu7dO$~6rnH7$iUFRbV*qMjK;an+t+Sr h8Vd<NdMqepyf@!RSI6M(yLURFa!#IKJ!KpjtO0VirM>_F literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/10.gif b/Tp5/minesweeper/icons/10.gif new file mode 100644 index 0000000000000000000000000000000000000000..10d928aa589648fbfd4e0c37a997cfa5e0eeaf2f GIT binary patch literal 393 zcmZ?wbhEHb6lM@+_{snRjEsy-Oiawo%q%P{tgNhTY-}7H9Gsk-TwGi{JUqO-ynK9o z{QUevLPEmA!s6oM5)u-Ul9IBrvhwosii(QL%E~G#Dr#zKnwpy0+S>a1`UVCDCMG7P zrluAa7M7NlR#sLvHZ~3p4vvnFE-o(a?(UwRo_>CQ{{H@ffq@Yb5m8Z5+1c5-xw#<M zkcbt3vM@3*=ribm^nv`uz_#qb^a2kZsa}>tg_<@BGn}0gU$F47A7?teU_pw3&=H1( zHd0CpE_XiJX|n9JtH;r#rEW4@hpLv$iO|#4R+AOyXLM!ZV3(}d)sR<}6%$}%VG88n zkWkUomX}hJ7M;pE!-YXePFYP=NmfFbufv^FTt-$_T0%sKv&M~?S43P)R9J|I`G6}2 nD+j-T0ACW@a#v;+1_nkpHpbhGTLOXt+?lRFd-dAek--`OQ*cI4 literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/11.gif b/Tp5/minesweeper/icons/11.gif new file mode 100644 index 0000000000000000000000000000000000000000..51fb6a928424a34021239bbb290456976666bcc1 GIT binary patch literal 879 zcmZ?wbhEHb6krfw_|5<U)eH>(8LAno85pXotM~5Rd+*-8{|pTO|1<m_1*0J_tV2Kt zlmkF{fq^50fty3dW5WUm77k&pn1}>LCk8%2lM;@L4_#OU7&ESP7(R6Ekv7-bvm&su wX@aP#nogzB688xj$*XE4CM!ElG7YX<V_Br?(`Ti;?2V`4qvIW1%uEc{0D652vj6}9 literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/12.gif b/Tp5/minesweeper/icons/12.gif new file mode 100644 index 0000000000000000000000000000000000000000..2854de27bbf73d5d8a9c21db979ab75f144a8a9f GIT binary patch literal 658 zcmZ?wbhEHb6lM@+_{IPN%*@Q}?Cjj!+;Vbqii(OVDk`d~syaG4Mmjo%hK5#FR@T<m zB_$=LrKOdXl~q+$)z#ItwY3{nRQ@wC{9|VR%f|LyMC7}u=yx%(PfAK}jEo)z1Uv{1 zzL}bOv9hwcxq05adAmD07A#n>aN)v*ix)3iv}oy~MN5_}S-pDonl)?Iu3fus-MYPt z7VTTJX3x5H+qZAuy?OJVO`CRZ-MVZ0_8mKR>;%D`J9qBfwR6{wUAuPf+O=c%?wz}L z@7lF%*KQElvuDrg&d%c#CLCP6_|T$7$BrF4e*E~clP6D{IC1IHrEg!q{rLXl=Z~L1 zfByXY=kLG2|3H2oG+6N`3)n3>AQBWO4D9b4{F|CvTKxlj%$odsd;9wPyv+ps{k+`V zXU_DPHPh2lh}YlO&A@cIm9ewF`EpYWO#!~e?(3~>TxFzOtSt7~X>HoF-cVjjL~_qQ zivx#z-OY_;#Y9e=+JA8Kc~cW7Y0+zYZ=Bm|VWTG}E^+<L&BObwZIy&|AH99DexJQ6 zr@H;=vs<Qq7G+^&5^-eMb^F+wV;ll(4m~R#KAv|VSjR_0LLi}mNmxfi&xR?Rk&%%h zh)ZFE0_%iU&jv${ga-}2%&ZbCI5s(nO;NQBTB0DhXvIYVm7p~W9}hSxaSAB7%<!6; Wb!8c!nrXp-t*fuE=VM}Ium%8KhvqW? literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/13.gif b/Tp5/minesweeper/icons/13.gif new file mode 100644 index 0000000000000000000000000000000000000000..947d01285d2ba0b83ccd14bf3fde61887798ad16 GIT binary patch literal 648 zcmZ?wbhEHb6lM@+_{PA%#l^+T%PS-#BrGf}Dk>@`C#R^WsI084qN1Xqp`oLrqpPcH zY;0_4X=!U~>+bIE?d|RB>zkC6l#-HCP*6}(Qc_x4T3K0HRaI46TU%dW-_p|3*4Eb9 z+1cOUKWWmW$&)8fojP^Kj2Sa$&YU}U?)>@l7cN}5Xwjl2OO~u$xpMXD)oa$QS-W=a z`t|EKZQ8VX^X4sEwrt(Hb^G@1J9g~Yxnt+fojZ5!+_h`huHCzL@7c3w@7}$~jvYIG z{P>9zCr+I_b?VfqOP4Nv`}*z2_a8rh{QUXz=ifhn|NZ^PFm!<8PZqFabwDI2P8isq zHn=u5x3s#tIhi!MIQRDT_c@wKxVku4+sw4Jv$waMX=7_9DeCHMZDee0rY$Kfs&2Z< zR7*l^nT@fjxh5YICo_kl#cu6wJ9e21F^KEQF!G-~w%vKBnE@}iu7xf;x1O2#<rAhx zO3KC-vW$Y4j$hqnYVlctl}pw9==+_ff6aAy-U(iI?~S*YQRK+EaIs&(vR*@D#fj(n zGJD!ga~^DH47{_i;**Vog5iaSN9!z2Bz^>3Qr;@JJMTozM5Q*LnHI|=Ig^}^cFnhs jWZ=zu)YR%CX`m5%s$^v#_hhYz8D3jgg>pACFjxZsaZJjg literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/2.gif b/Tp5/minesweeper/icons/2.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ef31056ccd581f2df4fe0f10e03f9ae831ac7ef GIT binary patch literal 668 zcmZ?wbhEHb6lM@+_{PA%(7?dZ$iUFVz}Upd)WpQp%*4{n!rIKr*22c#!p_;s$<@Ne z)yl=)%FWZt!`sHo*TyH)B_rD{tJI^U(xal<tE$$krrxKn(W{}`udCOuXFAc;bdss< z6kEF~c23irT&B6WO?L~L6%;%>IAnH6*zB<IIpGm=BBJL;$Igq5n-`ZfKPhKXPX6Nj z!X<@8ONvUDmX<9ot65%CyS%n;MO}Ay_nbL%=FXYhu%e-9WmD^_){fO3-K)FjY?!lT z^OB{Tm#*2iX6?4M>$a_1zis`7?He|2-?VxA<}KT|Y~HbX%Z@EucWm9ZW83x}+qduB zzGLT(ojZ5#+PQ1@&fU9q?b^L-_nuvQ_U+ooFrYy3Ckxnq9S{kM69)F54W?$zEv;?M zO+i7ye%^ik{eHn+%|YJA@-nk#&sMPX32F{D<Y8oFSh12}8NW$zv!^s86SJtC><(FB zCMHHXUo&%OiPhXT{yrxItT^^cxo*%=RnxK$^!LB6&vx#DSx{hb@bw$PcFF>K*|q(r z-gqDAV<E=8Oi<5l;r;ji!S+hLKB^oSmAOP}gEkyJU6|;g&uP%-bFgj0e10K5A4P_X z$y`&)IrKvdG#DOD(h3O*ni<mB+7!toH)nyNbDQsM>nSYClNgsVFtKrQ$Z8#Mnjmf7 vB4B)U%SufKk%l`P7CvF^5{cNH<=eQ3b&{9X;jU0guL}z|w`8#}F<1it-)Pab literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/3.gif b/Tp5/minesweeper/icons/3.gif new file mode 100644 index 0000000000000000000000000000000000000000..4abac7be126376b0b3c7a8dd202c91e51c401810 GIT binary patch literal 639 zcmZ?wbhEHb6lM@+_{PBSpMl{&BjZ0NroSvKe_2`ova$VPXaCK`^_!df4=3j@Uf%B_ zB0mKMe+UVEla%}-BlAU0?!A`QJ6+w+3JPzGjbEFXyf!tx8y$ToCgx6T>|<~52Z4bP z0|Orf1>H_axRsQ2D>?aQYU=f@tn1m?*K%{O=I5WUtGirWe6h0fLUna_clYc$Ah3Vs z%6+R>?_0BG_vX!eHf-3tVZ)w{8+UKnvU}UMUE8;B-?wk)&Yin<?%c6!*UnwLcI@80 zbNB9DyLRo^vuEd?J?9!4&NnoiYivB*+InK*#1oSy9h))Z@Z7nF=g&VfckY2@%MPqq z!7x~X;!hT^({w;2C{7sI?=)!XXt%Vswd!;>*_oO4^-nOhw6(PBv{n@nn>}Z)l&gj1 zbQy-F%a$+YcekCcARxS9;|88(at@t#hPu1=?AF&{T`Ijs$I{x$+S<ncjJ>%V`%)R} zPD_jH7DgUkcRW>C4js96-QJm-_XRKKGR5sjZ`f-xtys$9Xn*yC8W+c34(4SB9f!9a zcAePl+Ec^8kr1^{_Iim)F`KW{)+CdpGdE5YvhgUgd6g<`b9Q0j)CgWw5}<W}quko# sqP6IPLqd~W^ipn|-29wV&B|rthl|OJE~ZV<;q*GPWo58yBLjmq08zQwi~s-t literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/4.gif b/Tp5/minesweeper/icons/4.gif new file mode 100644 index 0000000000000000000000000000000000000000..4e942e211f7d29940e2f0868ad8888d6dc396064 GIT binary patch literal 649 zcmZ?wbhEHb6lM@+_{PA%z|h3N(9FQl!pPXd%-q7n)XKur%F5cx$=Sxm)y~J)&coBe z%iF=n*C8O#AuQY}D%vF>(Jd#}D=*)xtlX!f(x<B0Z)iBl*m$yu$z*HmskXLL?d+!6 z+fQ?FnC9d(-P?PnukS2>|Je}{bK~RZCnYUNO<kClwy>aJNoD2o?(Xh6bLPyQJ7?a! zIrHbwnLmGSW8=!^=2a~%t2#SZcXqCsFk$VKDeI<AT|aHw`svfx&zP}()~pSS7HwL( zbn~)hTb3{1vSP)SRjanHS+jNR+HD&)Y}>G5`{vEtH*emtWy_9j+jeZ<zGK_Ao!htX z+_7Wl&Ye4V?E(|KcJ1E1YtNot`}XYu1;Bt}#h)x-`*lDhC{7sIpEYP{H@CF5H8%wY zbO-u+_WSsGPY4KX4)F5}a8s6$l(Mpsm6T9&@t;03$bf^9LDJQdYn`am3hf#G&f<(r zoJJv*yiAN+x6cUDU^^o35q#*#vFZM{B76BvgU=sk6mt%m9-zW}#?HafnCFPFnR|1P zwII`HeqkXYLDtV~0w#Le-VO{L4i`il8b3c1?D*Jpv|m8R%45z8#>0)3+-46lHZJO% z)URM~we#RwCjsvrMk_-!S)&Z2SB7mW(bQe)6KaxpYmX-D@io(r=cQFKJ#pa_*6djj ZvSmf)WsO@~TsNw`m=Nlu#l*;94FJ{F(dhsH literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/5.gif b/Tp5/minesweeper/icons/5.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b6b607be42cfbd7aed2dd30c2bafc1ce9d3e4c9 GIT binary patch literal 418 zcmZ?wbhEHb6lM@+_{zZ0#K6$Zz|g|L(89>r%FNu#!qUdh-p<L{&duG<!_&df-z_fQ zEg{jTtUTG+c(SSK6m#<_78X;jtfpF9&v192>FGJk$7hzG-|T>Z*@1y`BO>NSN6(9i znI9WFKQ3-Ta`K{#jK$g6i}Ui9m6mpQch8wKXJtdf%Erc(O--wsn^$*qteZS}{j_Q8 zr%&H7bLOT63pOuVvSrz_Ez6g0S+Qc<h7CKmZQHqh`_7#^cY*LO5ZJwY*PcDQ_wQ!_ z1I3>#U|I)6g8an5w%;Kr(?dt9-D&RHV>wo{&F+3+E3#R4<IQ2lUA~$P4HZ6o3>x<? z^$H1a@O164nRj5x^|ua3ufF;ntz%#jUnyg2)6v;s*_@Tb#3*58FlDNNNl!~2C(qn@ zJlq2M*71p{$$5<OHo=O5LK`*;3G*^f5D!wd@b>pH*J7U_)@xzi)n%*Aap;Jyy2gcz z8k$n96C{^pi88U=y?1vT6SLBqzGcgknE4EEnyX36e*E-FPT6>-s@1XMf2=KnoccIa JoRl~itN|%@qD24z literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/6.gif b/Tp5/minesweeper/icons/6.gif new file mode 100644 index 0000000000000000000000000000000000000000..2cc9004893ede6904937f1f6c3fdfea9d517e0de GIT binary patch literal 660 zcmZ?wbhEHb6lM@+_{PA%(9p!t(9F=-%+S=r*wn(@+{)72%GT1x-qOa=(#F-=&fVJ1 z)7sA8)*;Z=A<*6-*xo7B-YL@2CDGX}*WDx6-K)^ktJu@4(%Yxr*RRt*QMZ4h>7>b) zlc!iso?<;^s@wD#9@A%f&Y0;nW2X0vnPIc%#LS%+J8ypC`~?{c7v(KpT(Eda;gTiA zOP1CwU(wy&J!j6GmX)j8SFP?`y}EbJnh9&yP6VNKlh&@Ay<x-LjT`4}+&F*Z#)X?U zE!wns+2$=Pw`^ItW$UUfTUT%0x@POvwOhAt+`fI&_U+qt?AX3z$M&5&ckBd#T|0N~ z-nnzvu3fu#?b@?z*S=l5_V3=!FbII+PZqE%bU-91P8irfHs~8Px3so3H~ISq_;~d7 z_xl8NHT!!TDag#4JzK%Z+rK%$SdeKM<BAo_m;{XjntfE5n3?&-wr}TKuI$t7CAXPP z*TwOuvz~;gu(H=a+07g#!GTu-y<Hvbo%b4eoo8m%w6S{f#M;Tvcj4Xp%$$NBJ_?HK zc)q^3dCTf$zjzD-&wUaN*s$P16Z0>Zg2V3GM|h<L3fBY}I5@PYz4^3phMR8}Kc}ev zuU`}Rj|wVl^k2yc_{e-rUG<aWg$)azv2n3zO^aYxb#LopV&D*!N(gI{S)X8&dCB=G gr*OdHSr!WyweRxkUX^*(N^{Br=LF8Z94rjh0PvmatpET3 literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/7.gif b/Tp5/minesweeper/icons/7.gif new file mode 100644 index 0000000000000000000000000000000000000000..aa755b7661dc088e2c73f8650f3b563bd3f2395e GIT binary patch literal 420 zcmZ?wbhEHb6lM@+_{zZ0%+TDz(9*)#(#qW0%GTP((bmr0-p<?JA<)q&*x4o8)vMUs zr_|T4(LdRE@??|AlT9a2v79o^ZrXIm>9hT3&k3G0Cv?ud=y~&E=FN|tKR<5%{Dk=n zQx+~vTevWN;iAk%i?S9iDOj?kaLLl5rOT_9cXxNsnKNf)<H}X7tJZX_S<|y-{nYgv zXK&m%XXD0s8#gW7v~|taZELq}Tfc4lrtLen?bxw>$Icx)L15R;T|0My!0uhU_UziV zcNYT~DE?#t(>fp$<R=EUg9j#Mdgw^CJI(DqmSZ*B?Cyl}Du;D9bdESa@^x(3P@(g! z!q=uC;cVV|=e-Z}j;_3IEz10Rg4Oc^o5n_46A`9tW+~GkHB0mU3Fh)FIl@L3md<?> ztu;8Z8F=-r&1d$`(cxyu=F(cSbk+n51HsjdtjZP>md&;>5o>2;5;NJ=zo*|qiFJXX z!Lj2Tt+luo@aV4JJ<D33cN?e1&0A_#hC)d!3KJ(Tv(}TAkQ7%mzVOD`%Brc+%JSd; Qe@i$lohEp6Dlk|B03blLf&c&j literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/8.gif b/Tp5/minesweeper/icons/8.gif new file mode 100644 index 0000000000000000000000000000000000000000..283c520e31c108effb9d477e4359a3654ce8470e GIT binary patch literal 427 zcmZ?wbhEHb6lM@+_{zXgTwGjIQc_x4T2@w8US3{NQBhf0SzTRSQ&Uq{SJ&9s*xcOQ z*4Eb1(b3h_)!p6Q-`_uB!i33_Cr_C&W%~5#vuDqqGiT1+xpU{wpTB6)qUFn%uUxru z)v8tN)~#E=e*K0G8#Zs=yk*OlZQHhO-@bjvjvYI9?%cI&*Y4fB8K?vlf3kp0(gBem zKQXYKIMANzp(EAqG<lOtmepL<rI{I8nF_sY!niNGteoYXz@st!cw=)~mZmEc(?Lha z<?@djJu*Ft4zNooDl{ufFf%dosnpalu}Z54sY|nVboJDW%FUiF+TPhMrY2O-$FY3* z)DEE>b@9TEjEoK9>dvYHOF4P=?BT2ss1~a&V3AZ-I;kwlGHv0Jz6q12oU7rl7m<;^ zEh93Yf1#T2Qf9Vi&)PeLbJS$HH*VU@E&E1QUR>nouV3Qw@r%6tIAlBwCJAvn^=YVl JQs7{)1^}Q{kkkMG literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/icons/9.gif b/Tp5/minesweeper/icons/9.gif new file mode 100644 index 0000000000000000000000000000000000000000..50ac94d02f9e29ba36133da6281c3f0b9b2026ec GIT binary patch literal 337 zcmZ?wbhEHb6lM@+_{zXwYisM^;Na-!=;!Ab5fKp|AD@trkeHa5pPye=R#s6_(b(A7 z)YR16+}zR8(b?JA)z#J0(=&DI)M?YEO`kq}=FFM1XV0E9XU^QYbLY>Wzi{EgMT-_K zUc7kOvSn-5tXa2i-R8}kckbMI=+L3VhYue+c8r1AK=CIF*hn1^3Gx#ITb{!u4;LM& z-o*lJS1#tvyPz>e*|9=rQfJxeyFoIn=Tn_DXP<w@bwojJ@qH1~YM%Pjw@bgwo#(&) zV{K}6USo4(Q+-WqXG?8cdw+LvZ)K6Zr0C39vuBG5vP<%F^DJ4qY$-1n3nw!p)A|h? LH!?CfGFSrugVS!t literal 0 HcmV?d00001 diff --git a/Tp5/minesweeper/minesweeper.py b/Tp5/minesweeper/minesweeper.py new file mode 100755 index 0000000..f0ab0dc --- /dev/null +++ b/Tp5/minesweeper/minesweeper.py @@ -0,0 +1,204 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`minesweeper` module + +:author: HERE YOUR NAME + +:date: + +This module provides functions and a class for minesweeper's game's management. + +""" + +import random +from enum import Enum +from cell import Cell + + +################################################ +# Type declaration +################################################ + +class GameState(Enum): + """ + A class to define an enumerated type with three values : + + * ``winning`` + * ``losing`` + * ``unfinished`` + + for the three state of minesweeper game. + """ + winning = 1 + losing = 2 + unfinished = 3 + + +############################################## +# Function for game's setup and management +############################################## + + +def neighborhood(x: int, y: int, width: int, height: int) -> list[tuple[int, int]]: + """ + return the list of coordinates of the neighbors of position (x,y) in a + grid of size width*height + + précondition: 0 <= x < width and 0 <= y < height + + examples: + + $$$ neighborhood(3, 3, 10, 10) + [(2, 2), (2, 3), (2, 4), (3, 2), (3, 4), (4, 2), (4, 3), (4, 4)] + $$$ neighborhood(0, 3, 10, 10) + [(0, 2), (0, 4), (1, 2), (1, 3), (1, 4)] + $$$ neighborhood(0, 0, 10, 10) + [(0, 1), (1, 0), (1, 1)] + $$$ neighborhood(9, 9, 10, 10) + [(8, 8), (8, 9), (9, 8)] + $$$ neighborhood(3, 9, 10, 10) + [(2, 8), (2, 9), (3, 8), (4, 8), (4, 9)] + """ + res =[] + if x>0: + res.append(x-1,y) + if x< width-1: + res.append(x+1,y) + if y>0: + res.append(x,y-1) + if y<height-1: + res.append(x,y+1) + return res +class Minesweeper(): + """ + $$$ game = Minesweeper(20, 10, 4) + $$$ game.width + 20 + $$$ game.height + 10 + $$$ game.nbombs + 4 + $$$ game == GameState.unfinished + True + $$$ cel = game.get_cell(1, 2) + $$$ cel.is_revealed + False + $$$ + """ + + def __init__(self, width: int=30, height: int=20, nbombs: int=99): + """ + build a minesweeper grid of size `width*height` of cells + with `nbombs` bombs randomly placed. + + for each build cell, this constructor sets the number of bombs + in neighborhood. + + precondition: width and height must be positive integers, and + nbombs <= width * height + + example: + + $$$ game = Minesweeper(20, 10, 4) + $$$ game.width + 20 + $$$ game.height + 10 + $$$ game.nbombs + 4 + $$$ game.state == GameState.unfinished + True + """ + ... + + def get_cell(self, x: int, y: int) -> Cell: + """ + return: the cell of coordinates (x,y) in the game's grid + + precondition: 0 <= x < width of game and O <= y < height of game + + $$$ game = Minesweeper(20, 10, 4) + $$$ sum(1 for x in range(20) for y in range(10) if game.get_cell(x, y).is_bomb) + 4 + """ + ... + + def _put_a_bomb_at(self, x: int, y: int): + """ + this method change the cells's state at x, y to a bomb, + + if the cell is already a bomb, nothing append. + otherwise it change cell's state and increments by one every + cells in its neighborhood. + + precondition: 0 <= x < self.width and 0 <= y < self.height + + exemples: + + $$$ game = Minesweeper(10, 5, 0) + $$$ voisins = neighborhood(1, 1, game.width, game.height) + $$$ all(game.get_cell(x, y).nbombs_in_neighborhood == 0 for x, y in voisins) + True + $$$ game._put_a_bomb_at(1, 1) + $$$ all(game.get_cell(x, y).nbombs_in_neighborhood == 1 for x, y in voisins) + True + $$$ game._put_a_bomb_at(1, 1) + $$$ all(game.get_cell(x, y).nbombs_in_neighborhood == 1 for x, y in voisins) + True + """ + ... + + def all_cells_are_revealed_or_bomb(self) -> bool: + """ + return True iff all cells are revealed or bomb. + + précondition: none + + """ + ... + + def reveal_all_cells_from(self, x, y): + """ + recursively reveal all cells of game game from the initial cell (x,y). + + * if the cell is a bomb one, update game's state to losing. + * otherwise if the cell's neighborhood doesn't contains bomb, + recursively reveal all neighboors. + * and finally, if all cell's are revealed, update game's state to + winning + + precondition: 0 <= x < width of game and O <= y < height of game + + exemples: + + $$$ game = Minesweeper(20, 10, 0) + $$$ game._put_a_bomb_at(1, 1) + $$$ game.state + GameState.unfinished + $$$ game.all_cells_are_revealed_or_bomb() + False + $$$ game.reveal_all_cells_from(5, 5) + $$$ game.all_cells_are_revealed_or_bomb() + False + $$$ game.reveal_all_cells_from(0, 0) + $$$ game.reveal_all_cells_from(1, 0) + $$$ game.reveal_all_cells_from(0, 1) + $$$ game.all_cells_are_revealed_or_bomb() + True + $$$ game.state + GameState.winning + $$$ game = Minesweeper(20, 10, 0) + $$$ game._put_a_bomb_at(1, 1) + $$$ game.reveal_all_cells_from(1, 1) + $$$ game.state + GameState.losing + """ + ... + + +if (__name__ == '__main__'): + import apl1test + apl1test.testmod('minesweeper.py') + -- GitLab