Skip to content
Snippets Groups Projects
Commit d62c8aef authored by Dahmane Lynda's avatar Dahmane Lynda
Browse files

Tp5

parent f23034de
Branches
No related tags found
No related merge requests found
Showing
with 592 additions and 0 deletions
File added
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))
#!/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')
#!/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')
Tp5/minesweeper/icons/0.gif

99 B

Tp5/minesweeper/icons/1.gif

404 B

Tp5/minesweeper/icons/10.gif

393 B

Tp5/minesweeper/icons/11.gif

879 B

Tp5/minesweeper/icons/12.gif

658 B

Tp5/minesweeper/icons/13.gif

648 B

Tp5/minesweeper/icons/2.gif

668 B

Tp5/minesweeper/icons/3.gif

639 B

Tp5/minesweeper/icons/4.gif

649 B

Tp5/minesweeper/icons/5.gif

418 B

Tp5/minesweeper/icons/6.gif

660 B

Tp5/minesweeper/icons/7.gif

420 B

Tp5/minesweeper/icons/8.gif

427 B

Tp5/minesweeper/icons/9.gif

337 B

#!/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')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment