summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--board/board.py11
-rw-r--r--bots/dssp.py6
-rw-r--r--doc/DEV.md16
-rw-r--r--doc/muistilista.txt10
-rw-r--r--pyproject.toml3
-rw-r--r--tests/test_board.py260
7 files changed, 209 insertions, 101 deletions
diff --git a/README.md b/README.md
index 526d5d0..de07154 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,10 @@ Miinaharava ratkaisijalla
## Ohjeita:
### Asennus
+#### Kloonaamalla uusin
+`git clone https://github.com/Aineopintojen-harjoitustyo-Algoritmit-j/miinaharava`
+`python3 miinaharava`
+#### Lataamalla jokin tietty versio
`mkdir miinaharava && wget -O - https://github.com/Aineopintojen-harjoitustyo-Algoritmit-j/miinaharava/archive/refs/tags/v0.1-beta.tar.gz | tar xz --strip-components=1 --directory=miinaharava`
### Käyttöohje
diff --git a/board/board.py b/board/board.py
index 118a771..36ceb62 100644
--- a/board/board.py
+++ b/board/board.py
@@ -18,14 +18,19 @@ class Board():
board = None):
# pylint: disable = too-many-arguments
+ if ( not width or not height or
+ width not in range(2,51) or
+ height not in range(2,51) ):
+ width, height = None, None
+
self.__level = level
self.__width, self.__height, self.__mines =LevelSpecs[self.__level][:3]
- if width and width in range(2,51):
+ if width:
self.__width = width
- if height and height in range(2,51):
+ if height:
self.__height = height
- if mines:
+ if height or width or mines:
self.__mines = mines
if self.__mines not in range(1,self.__width*self.__height):
diff --git a/bots/dssp.py b/bots/dssp.py
index 1e559a2..0cace12 100644
--- a/bots/dssp.py
+++ b/bots/dssp.py
@@ -40,16 +40,12 @@ class DSSPBot(SimpleBot):
continue
# vähennetään yhteinen alue ja sen pommit alueesta 2
- # jos jäljelle ei jää pommeja merkataan seiffeiks
- # jos avaamattomia pommien määrä merkataan pommeiks
+ # jos jäljelle ei jää miinoja merkataan alueet seiffeiks
c2 -= cc
if c2 == 0:
for safe in n2:
self.safe_tiles.add(safe)
- if cc == len(nc) and c2 == len(n2):
- for mine in n2:
- self.mine_tiles.add(mine)
return self.saved_hints()
diff --git a/doc/DEV.md b/doc/DEV.md
new file mode 100644
index 0000000..6f3eec4
--- /dev/null
+++ b/doc/DEV.md
@@ -0,0 +1,16 @@
+# Ohjeita kehitykseen
+## Riippuvuuksien asennus:
+`PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring poetry install --no-root`
+
+## Aja pytest:
+`poetry run python3 -m pytest`
+
+## Generoi haarakattavuusraportti:
+`poetry run python3 -m coverage run --branch -m pytest -v && poetry run python3 -m coverage html && firefox htmlcov/index.html`
+
+## Linttaus:
+`poetry run python3 -m pylint -v .`
+
+## Kaikki samassa:
+`poetry run python3 -m coverage run --branch -m pytest -v && poetry run python3 -m coverage html && firefox htmlcov/index.html && poetry run python3 -m pylint -v .`
+
diff --git a/doc/muistilista.txt b/doc/muistilista.txt
deleted file mode 100644
index d163048..0000000
--- a/doc/muistilista.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-MUISTILISTA!
-
-Generoi haarakattavuusraportti:
-poetry run python3 -m coverage run --branch -m pytest -v && poetry run python3 -m coverage html && firefox htmlcov/index.html
-
-Linttaus
-poetry run python3 -m pylint -v .
-
-riippuvuuksien asennus:
-PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring poetry install --no-root
diff --git a/pyproject.toml b/pyproject.toml
index 0dfb3e9..fd1ea78 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,9 +20,6 @@ build-backend = "poetry.core.masonry.api"
[tool.pylint.main]
recursive = true
source-roots = ["./"]
-# Jostain syystä paikallisesti b._Board__tiles privatti tietojen lukemisen
-# aiheuttamaa linttausvirhettä ei voi disabloida test_board.py:ssä.
-ignore-patterns = 'test_board'
[tool.pylint.basic]
diff --git a/tests/test_board.py b/tests/test_board.py
index b7678c8..37a2d54 100644
--- a/tests/test_board.py
+++ b/tests/test_board.py
@@ -1,13 +1,34 @@
-"""test_board.py - Testit pelilaudalle"""
-# Tämä tiedosto on jätettty pylint testien ulkopuolelle, koska tässä tehdään
-# paljon "kiellettyjä asioita", kuten käydään lukemassa luokan "privaatteja"
-# muuttujia
+""" tests/test_board.py - Testit pelilaudalle """
import unittest
from board import Board, Level, LevelSpecs
+
+def matrix_equals(m1, m2):
+ """ matrix_equals - apufunktio testaa onko matriisit samat """
+ if len(m1)!=len(m2):
+ return False
+ # pylint: disable = consider-using-enumerate
+ for i in range(len(m1)):
+ if m1[i] != m2[i]:
+ return False
+ return True
+
+def matrix_swap_xy(m):
+ """ matrix_swap_xy - palauttaa matriisin korvattu x -> y ja y -> x """
+ if not m:
+ return None
+ w, h = len(m[0]), len(m)
+ ret_m = [[0 for _ in range(h)] for _ in range(w)]
+ for y in range(h):
+ for x in range(w):
+ ret_m[x][y]=m[y][x]
+ return ret_m
+
+
class TestBoardClass(unittest.TestCase):
""" pelilauden testit kattava luokka """
+
def test_init_works_and_defaults_beginner(self):
""" pelilautaolion luominen onnistuu ja defaulttaa aloittelijaksi """
b = Board()
@@ -16,6 +37,7 @@ class TestBoardClass(unittest.TestCase):
self.assertEqual(b.get_mines(), LevelSpecs[Level.BEGINNER][2])
self.assertTrue(b.get_width()>0)
+
def test_init_with_level(self):
""" olion luominen onnistuu vaikeustasolla"""
b = Board(level=Level.EXPERT)
@@ -23,24 +45,27 @@ class TestBoardClass(unittest.TestCase):
self.assertEqual(b.get_height(), LevelSpecs[Level.EXPERT][1])
self.assertEqual(b.get_mines(), LevelSpecs[Level.EXPERT][2])
+
+ def test_init_with_custom_dimentions(self):
+ """ mukautetun kentän luominen onnistuu """
+ b = Board(width=13, height=14, mines=15)
+ self.assertEqual(b.get_width(), 13)
+ self.assertEqual(b.get_height(), 14)
+ self.assertEqual(b.get_mines(), 15)
+ b = Board(width=22, height=12)
+ self.assertEqual(b.get_width(), 22)
+ self.assertEqual(b.get_height(), 12)
+ self.assertEqual(b.get_mines(), 22)
+
+
def test_init_with_incorect_dimensions(self):
""" luominen ei saa onnitua mahdottomilla mitoilla """
- b = Board(width=1, height=999)
+ b = Board(width=1, height=999, mines=0)
self.assertEqual(b.get_width(), LevelSpecs[Level.BEGINNER][0])
self.assertEqual(b.get_height(), LevelSpecs[Level.BEGINNER][1])
self.assertEqual(b.get_mines(), LevelSpecs[Level.BEGINNER][2])
- def matrixs_equals(self, m1, m2):
- """ apufunktio testaa onko matriisit samat """
- # onko edes samaa kokoa ?
- if len(m1)!=len(m2):
- return False
- for i in range(len(m1)):
- if m1[i] != m2[i]:
- return False
- return True
-
-
+
def test_init_with_valid_board(self):
""" Pelilaudan luominen onnistuu kelvollisella asettelulla """
t = [
@@ -53,8 +78,44 @@ class TestBoardClass(unittest.TestCase):
self.assertEqual(b.get_height(), 3)
self.assertEqual(b.get_mines(), 1)
- def test_init_board_is_masked_right(self):
- """ Luodun pelilaudan laatat ja peitteet on asetettu oikein """
+
+ def test_init_with_invalid_board(self):
+ """ Yritetään luoda peli kelvottomalla laudalla """
+ t = [
+ [0,0,0,0,0],
+ [0,0,0,1],
+ [0,0,0,0,0]
+ ]
+ b = Board(board = t)
+ # Resetoituihan aloittelijan lauta
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+ t = [
+ [0,1,0,0,0],
+ ]
+ b = Board(board = t)
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+ t = [
+ [0,0,0,0],
+ [0,0,0,0],
+ [0,0,0,0]
+ ]
+ b = Board(board = t)
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+ t = [
+ [1,1,1],
+ [1,1,1],
+ [1,1,1]
+ ]
+ b = Board(board = t)
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+
+ def test_tiles_and_masks_ok(self):
+ """ Luohan luokka sisäiset laatat ja maskit oikein """
+ # pylint: disable = protected-access
t = [
[0,0,0,0],
[0,0,0,1],
@@ -66,26 +127,25 @@ class TestBoardClass(unittest.TestCase):
self.assertEqual(b.get_mines(), 1)
# testataan onko laatat tallennettu oikein luokkaan
- t = [
- [0,0,0],
- [0,0,0],
- [1,1,1],
- [1,9,1]
- ]
- self.assertTrue(self.matrixs_equals(b._Board__tiles, t))
+ t = matrix_swap_xy([
+ [0,0,1,1],
+ [0,0,1,9],
+ [0,0,1,1]
+ ])
+ self.assertTrue(matrix_equals(b._Board__tiles, t))
# onko maksit asetettu oikein
- t = [
- [12,12,12],
- [12,12,12],
- [12,12,12],
- [12,12,12]
- ]
- self.assertTrue(self.matrixs_equals(b._Board__masked, t))
+ t = matrix_swap_xy([
+ [12,12,12,12],
+ [12,12,12,12],
+ [12,12,12,12]
+ ])
+ self.assertTrue(matrix_equals(b._Board__masked, t))
+
def test_get_view_and_guess(self):
""" laudan näkymä on oikein senkin jälkeen kun on arvattu """
-
+
t = [
[0,0,1],
[0,0,0],
@@ -94,56 +154,98 @@ class TestBoardClass(unittest.TestCase):
b = Board(board=t)
# Antaahan pelikenttä pelkkää maskia aluksi
- t = [
+ t = matrix_swap_xy([
[12,12,12],
[12,12,12],
[12,12,12]
- ]
- self.assertTrue(self.matrixs_equals(b.get_view(), t))
+ ])
+ self.assertTrue(matrix_equals(b.get_view(), t))
# avataan yläkulma -> palatuu True
self.assertTrue(b.guess(0,0))
# onko näkymä nyt oikein
- t = [
- [0,0,0],
- [1,1,0],
- [12,1,0]
- ]
- self.assertTrue(self.matrixs_equals(b.get_view(), t))
+ t = matrix_swap_xy([
+ [0,1,12],
+ [0,1,1],
+ [0,0,0]
+ ])
+ self.assertTrue(matrix_equals(b.get_view(), t))
# avataan alakulma jossa miina -> palautuu False
self.assertFalse(b.guess(2,0))
+
def test_is_winning(self):
""" toimiiko voittotilanteen tunnistus """
- b = Board(width=2, height=2)
- b._Board__tiles=[[1,9],[9,9]]
- b._Board__masked=[[12,12],[12,12]]
+
+ t = [
+ [0,1],
+ [0,0],
+ ]
+ b = Board(board=t)
+ self.assertFalse(b.is_winning())
+
+ # Avataan ruutu jolla ei tule viellä voittoa
+ t = matrix_swap_xy([
+ [1,12],
+ [12,12]
+ ])
+ self.assertTrue(b.guess(0,0))
+ self.assertTrue(matrix_equals(b.get_view(), t))
self.assertFalse(b.is_winning())
- b._Board__masked=[[0,12],[12,12]]
+
+ # Avataan loputkin ruudut, jolloin pitäisi voittaa
+ t = matrix_swap_xy([
+ [1,12],
+ [1,1]
+ ])
+ self.assertTrue(b.guess(0,1))
+ self.assertTrue(b.guess(1,1))
+ self.assertTrue(matrix_equals(b.get_view(), t))
self.assertTrue(b.is_winning())
- b._Board__masked=[[0,0],[12,12]]
+
+ # Lupuksi avataan miina jolloin voittoa ei enää pitäisi olla
+ t = matrix_swap_xy([
+ [1,9],
+ [1,1]
+ ])
+ self.assertFalse(b.guess(1,0))
+ self.assertTrue(matrix_equals(b.get_view(), t))
self.assertFalse(b.is_winning())
+
def test_error_conditions_in_guess(self):
""" ruudun avaus alueen ulkopuolelta tai avatussa ruudussa ei onnistu"""
- b = Board(width=2, height=2)
- b._Board__tiles=[[1,9],[9,9]]
+ t = [
+ [0,1],
+ [0,0],
+ ]
+ b = Board(board=t)
self.assertFalse(b.guess(2,2))
self.assertTrue(b.guess(0,0))
self.assertFalse(b.guess(0,0))
+
def test_get_mask(self):
""" maski annetaan oikein """
- b = Board(width=2, height=2)
- b._Board__tiles=[[1,9],[9,9]]
- self.assertEqual(b.get_mask(0,0), 12)
+ t = [
+ [1,0],
+ [0,0],
+ ]
+ b = Board(board=t)
+ self.assertEqual(b.get_mask(1,0), 12)
+ self.assertTrue(b.guess(1,0))
+ self.assertFalse(b.get_mask(1,0))
+
def test_flag(self):
- """ ruudun liputus toimii """
- b = Board(width=2, height=2)
- b._Board__tiles=[[1,9],[9,9]]
+ """ ruudun lipun vaihto ja asetus toimii """
+ t = [
+ [0,0],
+ [0,1],
+ ]
+ b = Board(board=t)
self.assertEqual(b.get_mask(0,0), 12)
self.assertTrue(b.flag(0,0))
self.assertEqual(b.get_mask(0,0), 13)
@@ -156,40 +258,38 @@ class TestBoardClass(unittest.TestCase):
self.assertTrue(b.flag(0,0,10))
self.assertEqual(b.get_mask(0,0), 10)
+
def test_flag_error_conditions(self):
""" liputus ei onnistu jos avattu, alueen ulkopuolella, outo arvo """
- b = Board(width=2, height=2)
- b._Board__tiles=[[1,9],[9,9]]
- b._Board__masked[0][0]=6
- self.assertFalse(b.flag(0,0))
- b._Board__masked[0][0]=10
- self.assertFalse(b.flag(0,0,4))
- b._Board__masked[0][0]=0
- self.assertFalse(b.flag(0,0))
- self.assertFalse(b.flag(2,2))
+ t = [
+ [0,1],
+ [1,1],
+ ]
+ b = Board(board=t)
+ self.assertFalse(b.flag(0,0,6)) # Lippu jota ei ole
+ self.assertFalse(b.flag(2,2)) # Alueen ulkopuolella
+ self.assertTrue(b.guess(0,0))
+ self.assertFalse(b.flag(0,0)) # Avattu laatta
+
def test_reveal(self):
""" paljastuksen jälkeen näkyy laatat sellaisenaan """
- b = Board(width=2, height=2)
+ t = [
+ [0,1],
+ [1,1],
+ ]
+ b = Board(board=t)
b.reveal()
- t = b._Board__tiles
- v = b.get_view()
- for i in range(2):
- self.assertEqual(v[i],t[i])
+ t = matrix_swap_xy([
+ [3,9],
+ [9,9]
+ ])
+ self.assertTrue(matrix_equals(b.get_view(), t))
+
- def test_get_level(self):
+ def test_get_level_name(self):
""" Testataan että nykyinen vaikeustaso palautuu oikein """
b = Board(level=Level.INTERMEDIATE)
self.assertIn(LevelSpecs[Level.INTERMEDIATE][3], b.get_level_name())
b = Board(level=Level.INTERMEDIATE, width=25, mines=2)
self.assertIn("Mukautettu", b.get_level_name())
-
- def test_board_invalid(self):
- """ Yritetään luoda peli kelvottomalla laudalla """
- b = Board(board=[[0,0,0,0,0],[0,0,0,1],[0,0,0,0,0]])
- self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
- b = Board(board=[[0,0,0,0,0]])
- self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
- b = Board(board=[[0,0,0,0],[0,0,0,0],[0,0,0,0]])
- self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
-