Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
AP-WALLOT-Angy
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Angy Wallot
AP-WALLOT-Angy
Commits
86668bc2
Commit
86668bc2
authored
1 year ago
by
Angy Wallot
Browse files
Options
Downloads
Patches
Plain Diff
Upload New File
parent
86ed63f4
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
tp.5/minesweeper.py
+230
-0
230 additions, 0 deletions
tp.5/minesweeper.py
with
230 additions
and
0 deletions
tp.5/minesweeper.py
0 → 100644
+
230
−
0
View file @
86668bc2
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
:mod:`minesweeper` module
:author: KINADINOVA Dariya
:date: 14/02/24
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
=
[
(
xn
,
yn
)
for
xn
,
yn
in
[(
x
-
1
,
y
-
1
),
(
x
-
1
,
y
),
(
x
-
1
,
y
+
1
),
(
x
,
y
-
1
),
(
x
,
y
+
1
),(
x
+
1
,
y
-
1
),
(
x
+
1
,
y
),
(
x
+
1
,
y
+
1
)]
if
0
<=
xn
<
width
and
0
<=
yn
<
height
]
return
res
class
Minesweeper
():
"""
$$$ game = Minesweeper(20, 10, 4)
$$$ game.width
20
$$$ game.height
10
$$$ game.nbombs
4
$$$ game.state == 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
"""
self
.
width
=
width
self
.
height
=
height
self
.
nbombs
=
nbombs
self
.
state
=
GameState
.
unfinished
self
.
grid
=
[[
Cell
()
for
x
in
range
(
width
)]
for
y
in
range
(
height
)]
bombs
=
random
.
sample
(
range
(
width
*
height
),
nbombs
)
for
i
in
bombs
:
x
,
y
=
(
i
%
width
),
i
//
width
self
.
_put_a_bomb_at
(
x
,
y
)
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
"""
return
self
.
grid
[
y
][
x
]
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 happens.
otherwise it changes 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
"""
if
self
.
get_cell
(
x
,
y
).
is_bomb
==
False
:
self
.
get_cell
(
x
,
y
).
set_bomb
()
for
i
,
j
in
neighborhood
(
x
,
y
,
self
.
width
,
self
.
height
):
self
.
get_cell
(
i
,
j
).
incr_number_of_bombs_in_neighborhood
()
def
all_cells_are_revealed_or_bomb
(
self
)
->
bool
:
"""
return True iff all cells are revealed or bomb.
précondition: none
"""
for
i
in
range
(
self
.
width
):
for
j
in
range
(
self
.
height
):
self
.
get_cell
(
i
,
j
)
if
not
self
.
get_cell
(
i
,
j
).
is_bomb
and
not
self
.
get_cell
(
i
,
j
).
is_revealed
:
return
False
return
True
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
self
.
get_cell
(
x
,
y
).
is_bomb
:
self
.
state
=
GameState
.
losing
elif
not
self
.
get_cell
(
x
,
y
).
is_revealed
:
self
.
get_cell
(
x
,
y
).
reveal
()
if
self
.
get_cell
(
x
,
y
).
nbombs_in_neighborhood
==
0
:
for
i
,
j
in
neighborhood
(
x
,
y
,
self
.
width
,
self
.
height
):
self
.
reveal_all_cells_from
(
i
,
j
)
else
:
self
.
all_cells_are_revealed_or_bomb
()
self
.
state
=
GameState
.
winning
# game = Minesweeper(20, 10, 4)
# game.state == GameState.unfinished
if
(
__name__
==
'
__main__
'
):
import
apl1test
apl1test
.
testmod
(
'
minesweeper.py
'
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment