Skip to content

Commit 465088a

Browse files
authored
Merge pull request larymak#134 from tomimara52/main
add ConsoleSnake and ConsoleMinesweeper
2 parents aa8bc55 + cace1b7 commit 465088a

File tree

10 files changed

+1361
-0
lines changed

10 files changed

+1361
-0
lines changed

ConsoleMinesweeper/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/venv
2+
__pycache__
3+
.main.py.swp

ConsoleMinesweeper/LICENSE

+674
Large diffs are not rendered by default.

ConsoleMinesweeper/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# ConsoleMinesweeper
2+
3+
python script to play the classic minesweeper game in your console.
4+
5+
## How to play
6+
7+
input the row and column in the following form:
8+
``` row,col ```
9+
this will dig in the specified place.
10+
11+
if you want to mark a spot you know there is a bomb,
12+
put an 'm' following the row and column, like this:
13+
``` row,colm ```
14+
15+
press 'h' for help in-game and 'q' to quit.

ConsoleMinesweeper/main.py

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
from random import randint, choice
2+
import os
3+
import re
4+
5+
6+
class MineField:
7+
def __init__(self, size, n_bombs):
8+
self.size = size
9+
self.digged = 0
10+
self.n_bombs = n_bombs
11+
self.grid = [[0 for j in range(size)] for i in range(size)]
12+
self.grid_mask = [['·' for j in range(size)] for i in range(size)]
13+
self.plant_bombs()
14+
# self.assign_numbers()
15+
self.first_dig()
16+
17+
def __str__(self):
18+
19+
_str = ' ';
20+
21+
for i in range(1, self.size+1):
22+
_str += str(i) + ' '
23+
if i < 10:
24+
_str += ' '
25+
_str += '\n'
26+
27+
_str += ' ' + '―' * (self.size * 3 + 3) + '\n'
28+
29+
for i, row in enumerate(self.grid_mask, 1):
30+
if i < 10:
31+
_str += ' '
32+
_str += str(i) + '| '
33+
for char in row:
34+
_str += str(char) + ' '
35+
_str += '\n'
36+
return _str
37+
38+
def plant_bombs(self):
39+
bombs_planted = 0
40+
while bombs_planted < self.n_bombs:
41+
row = randint(0, self.size - 1)
42+
column = randint(0, self.size - 1)
43+
44+
if self.grid[row][column] == '*':
45+
continue
46+
47+
self.grid[row][column] = '*'
48+
49+
self.fill_neighbors(row, column)
50+
51+
bombs_planted += 1
52+
53+
def fill_neighbors(self, row, column):
54+
if row != 0:
55+
if column != 0:
56+
if self.grid[row-1][column-1] != '*':
57+
self.grid[row-1][column-1] += 1
58+
59+
if self.grid[row-1][column] != '*':
60+
self.grid[row-1][column] += 1
61+
62+
if column != self.size-1:
63+
if self.grid[row-1][column+1] != '*':
64+
self.grid[row-1][column+1] += 1
65+
66+
if column != 0:
67+
if self.grid[row][column-1] != '*':
68+
self.grid[row][column-1] += 1
69+
70+
if column != self.size-1:
71+
if self.grid[row][column+1] != '*':
72+
self.grid[row][column+1] += 1
73+
74+
if row != self.size-1:
75+
if column != 0:
76+
if self.grid[row+1][column-1] != '*':
77+
self.grid[row+1][column-1] += 1
78+
79+
if self.grid[row+1][column] != '*':
80+
self.grid[row+1][column] += 1
81+
82+
if column != self.size-1:
83+
if self.grid[row+1][column+1] != '*':
84+
self.grid[row+1][column+1] += 1
85+
86+
def first_dig(self):
87+
zeros = []
88+
for row in range(self.size):
89+
for column in range(self.size):
90+
if self.grid[row][column] == 0:
91+
zeros.append((row, column))
92+
93+
spot_to_dig = choice(zeros)
94+
self.dig(spot_to_dig[0], spot_to_dig[1])
95+
96+
def dig(self, row, col):
97+
spot = self.grid[row][col]
98+
if spot == '*':
99+
return False
100+
elif spot != self.grid_mask[row][col]:
101+
self.grid_mask[row][col] = spot
102+
self.digged += 1
103+
if (spot == 0):
104+
self.clear_zeros(row, col)
105+
return True
106+
107+
def clear_zeros(self, row, col):
108+
if row != 0:
109+
if col != 0:
110+
self.dig(row-1, col-1)
111+
112+
self.dig(row-1, col)
113+
114+
if col != self.size-1:
115+
self.dig(row-1, col+1)
116+
117+
if col != 0:
118+
self.dig(row, col-1)
119+
120+
if col != self.size-1:
121+
self.dig(row, col+1)
122+
123+
if row != self.size-1:
124+
if col != 0:
125+
self.dig(row+1, col-1)
126+
127+
self.dig(row+1, col)
128+
129+
if col != self.size-1:
130+
self.dig(row+1, col+1)
131+
132+
def mark_spot(self, row, col):
133+
spot_mask = self.grid_mask[row][col]
134+
if spot_mask == 'X':
135+
self.grid_mask[row][col] = '·'
136+
elif spot_mask == '·':
137+
self.grid_mask[row][col] = 'X'
138+
139+
def show_bombs(self):
140+
for row in range(self.size):
141+
for column in range(self.size):
142+
if self.grid[row][column] == '*':
143+
self.grid_mask[row][column] = '*'
144+
145+
146+
def print_help():
147+
print('――――― Console Minesweeper ―――――')
148+
print('To dig in a spot, input the row\nand the column you want to dig in.')
149+
print('For example, if I wanted to dig\nin the row 2, column 4, I would\ntype: 2,4')
150+
print('―――――――――――――――――――――――――――――――――')
151+
print('If you just want to mark a spot\nwhere you know is a bomb, type the\ncoordinates followed with an "m".\nExample: 1,4m')
152+
print('\n')
153+
154+
155+
def play(field):
156+
pattern = re.compile(r"^[0-9]+,[0-9]+m?$")
157+
os.system('cls' if os.name == 'nt' else 'clear')
158+
print(field)
159+
move = 'h'
160+
alive = True
161+
while alive:
162+
163+
move = input("Your move ('h' for help, 'q' to quit): ")
164+
os.system('cls' if os.name == 'nt' else 'clear')
165+
166+
if move == 'h':
167+
print_help()
168+
elif move == 'q':
169+
print('Bye!\n')
170+
alive = 'bye'
171+
break
172+
elif re.fullmatch(pattern, move):
173+
row, column= [int(i)-1 for i in move.strip('m').split(',')]
174+
if (row > field.size) |( column > field.size):
175+
print('Invalid coordinates\n')
176+
elif move[-1] == 'm':
177+
field.mark_spot(row, column)
178+
else:
179+
alive = field.dig(row, column)
180+
if field.digged == (field.size**2 - field.n_bombs):
181+
break
182+
else:
183+
print('Invalid input\n')
184+
185+
print(field)
186+
187+
if alive:
188+
if alive == True:
189+
print(field)
190+
print("You won, congratulations!!!")
191+
else:
192+
os.system('cls' if os.name == 'nt' else 'clear')
193+
field.show_bombs()
194+
print(field)
195+
print("You lost :(")
196+
197+
198+
field = MineField(10, 10)
199+
play(field)

ConsoleSnake/.gitignore

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# celery beat schedule file
95+
celerybeat-schedule
96+
97+
# SageMath parsed files
98+
*.sage.py
99+
100+
# Environments
101+
.env
102+
.venv
103+
env/
104+
venv/
105+
ENV/
106+
env.bak/
107+
venv.bak/
108+
109+
# Spyder project settings
110+
.spyderproject
111+
.spyproject
112+
113+
# Rope project settings
114+
.ropeproject
115+
116+
# mkdocs documentation
117+
/site
118+
119+
# mypy
120+
.mypy_cache/
121+
.dmypy.json
122+
dmypy.json
123+
124+
# Pyre type checker
125+
.pyre/

ConsoleSnake/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 tomimara52
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

ConsoleSnake/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# ConsoleSnake
2+
Snake game in your windows, linux or macOS console

0 commit comments

Comments
 (0)