Reputation:
I have been tasked with creating minesweeper in the terminal as a project. I am relatively new to Python so this is quite a big task for me. For some reason I cannot get the numbers that surround the bombs to add up correctly. I have pasted the code and some outputs below. I get no errors when running the code. (I have noticed that it may have something to do with the code for the top right block above the bomb, but I've looked through everything and can't seem to find the issue. There's also sometimes less bombs than there should be.)
import random
def minesweeper(dim_size, num_bombs):
print_list = []
for i in range(dim_size):
print_list.append([])
for j in range(dim_size):
print_list[i].append(0)
for i in range(num_bombs):
random_row = random.randrange(0,dim_size-1)
random_column = random.randrange(0,dim_size-1)
print_list[random_row][random_column] = 'X'
# centre-top
if random_row >= 1:
if print_list[random_row - 1][random_column] != 'X':
print_list[random_row - 1][random_column] += 1
# right-top
if random_row >= 1 and random_column > dim_size:
if print_list[random_row - 1][random_column + 1] != 'X':
print_list[random_row - 1][random_column + 1] += 1
# right
if random_column < dim_size:
if print_list[random_row][random_column + 1] != 'X':
print_list[random_row][random_column + 1] += 1
# bottom-right
if random_row < dim_size and random_column < dim_size:
if print_list[random_row + 1][random_column + 1] != 'X':
print_list[random_row + 1][random_column + 1] += 1
# bottom
if random_row < dim_size:
if print_list[random_row + 1][random_column] != 'X':
print_list[random_row + 1][random_column] += 1
# bottom-left
if random_row < dim_size and random_column >= 1:
if print_list[random_row + 1][random_column - 1] != 'X':
print_list[random_row + 1][random_column - 1] += 1
# left
if random_column >= 1:
if print_list[random_row][random_column - 1] != 'X':
print_list[random_row][random_column - 1] += 1
# top-left
if random_row >= 1 and random_column >= 1:
if print_list[random_row - 1][random_column - 1] != 'X':
print_list[random_row - 1][random_column - 1] += 1
for row in range(dim_size):
for column in range(dim_size):
print(print_list[row][column], end=' ')
print()
if __name__ == '__main__':
minesweeper(5,5)
Outputs:
1 X 1 0 0
2 3 3 1 0
2 X X X 1
X 3 3 2 1
1 1 0 0 0
2 X 1 0 0
4 X 2 0 0
X X 3 0 0
2 3 X 1 0
0 1 1 1 0
X 2 X X 1
X 3 2 2 1
1 2 1 0 0
0 1 X 1 0
0 1 1 1 0
X 3 X 2 0
1 4 3 2 0
1 1 X 1 0
X 2 1 1 0
1 1 0 0 0
Upvotes: 0
Views: 260
Reputation: 95
Okay, For that 'There's also sometimes less bombs than there should be'... You need to use While loop to track number of bombs you've planted in Grid. Using for loop will run only in range(num_bombs) & it won't care if it has planted the required num of bombs. But While loop will first check if the code has planted the required num_bombs, if so... it will stop running but if not it will continue running
Also before planting the Bomb, you need to check if that row_column has Bomb, if so... don't Plant the bomb... if not plant the bomb.
here the code:
planted_num_bomb = 0 #number of bombs planted
while planted_num_bomb < num_bombs:
# for i in range(num_bombs):
random_row = random.randrange(0,dim_size-1)
random_column = random.randrange(0, dim_size - 1)
# check if the row_colm has a Bomb
if print_list[random_row][random_column] == 'X': #contains the bomb
continue #pass it
else:
print_list[random_row][random_column] = 'X'
planted_num_bomb += 1
There 5 results:
0 0 2 X 1
1 1 3 X 2
2 X 3 X 2
2 X 3 1 1
1 1 1 0 0
1 2 1 0 0
1 X X 1 0
2 4 X 3 0
1 X 3 X 1
1 1 2 1 1
5 #number of bombs planted
1 0 2 X 1
X 1 2 X 2
3 2 1 1 1
X X 1 0 0
2 2 1 0 0
5 #number of bombs planted
1 0 1 1 0
X 2 2 X 1
3 3 X 2 1
X X 2 1 0
2 2 1 0 0
5 #number of bombs planted
0 0 0 0 0
2 2 1 0 0
X X X 2 0
X 4 3 X 1
1 1 1 1 1
5 #number of bombs planted
Now if you take a look... the code can't place a mine a column number 5... why? ANSWER is at the top(1st answer). if you find a solution to that problem, still use the while loop because for loop won't always plant the required number of bombs, why? because, in for loop, when we skip(the continue part in code when there's bomb), the for loop still counts that as an iteration.
Anyway Goodluck on Your WTC bootcamp.
Upvotes: 0
Reputation: 10799
A couple things stand out:
random.randrange
doesn't include the endpoint, so if your endpoint is dim_size-1
, that means you'll only ever generate numbers between zero and three inclusive. This means mines will never appear anywhere in the bottom row, or right-most column.
The second issue, which you've already pointed out, has to do with the way you're placing mines. You generate a random xy-coordinate, and then place a mine there. What if you happen to generate the same coordinate more than once? You simply place another mine in the same field which is already occupied by a mine.
Instead of using random.randrange
, or even random.randint
to generate random coordinates, I would first generate a collection of all possible coordinates, and then use random.sample
to pull five unique coordinates from that collection. In the same way lottery numbers are drawn, the same numbers (coordinates in our case) can never be drawn more than once:
import random
import itertools
dim_size = 5
num_mines = 5
for x, y in random.sample(list(itertools.product(range(dim_size), repeat=2)), k=num_mines):
print("Put a mine at {}, {}".format(x, y))
Output:
Put a mine at 4, 4
Put a mine at 4, 3
Put a mine at 3, 1
Put a mine at 1, 0
Put a mine at 3, 0
>>>
Upvotes: 1