0

I am a beginner at python and I am attempting to create a simple game. I am struggling to create a function that is required to take in zero arguments and returns a grid which contains randomly placed explosives.

As a general requirement, there should be a ten percent chance of getting a mine.

This is my code so far, but I'm struggling to figure out where to go from here. I also don't really understand the ten percent chance of placing a mine requirement because I thought there would have to be 10 different boxes? If someone could help push me in the right direction, I'd really appreciate it.

def mines():
    gridSize = 3
    createGrid = [[' ' for i in range(gridSize)] for i in range(gridSize)]
    return createGrid
print(initMines())

All of these answers were really helpful, thanks! :)

Blackthorn
  • 47
  • 4
  • If it is only a 3x3 there is a good chance that there will be no mines at a 1 in 10 chance. Are you sure you don't want to define a minimum number of mines? – Cory L Nov 28 '18 at 01:59

4 Answers4

0

Using the random library, you can use randint to get your 1 in 10 chance, and implement via an if statement

import random

GRIDSIZE = 3
CHANCE = 10

def mines():
    createGrid = [[("x" if random.randint(0, CHANCE) == 0  else  " ") for i in range(GRIDSIZE)] for i in range(GRIDSIZE)]
    return createGrid
print(mines())

Output example

[['x', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]

Edit: I have added global constants for the grid size and chance based on your question, however I would pass these as parameters if I were you.

Cory L
  • 273
  • 1
  • 12
0

For a 1/10 chance of a mine, you can just use something like (remembering to import random):

opts = "M........."
[[random.choice(opts) for c in range(gridSize)] for r in range(gridSize)]

It just chooses one of the characters from the string, which happens to have a 10% chance of getting a mine.

Using that in a complete program, and making it more configurable:

import random

def mines(gsz, pct):
    # Silently enforce int 0-100, create choices, then choose.

    pct = max(0, min(100, int(pct)))
    opts = "M" * pct + ' ' * (100 - pct)
    return [[random.choice(opts) for i in range(gsz)] for i in range(gsz)]

# Test harness. First, create a grid.

sz = 10
grid = mines(sz, 20)

# Then dump it for confirmation.

for line in grid: print(line)
mineCount = sum([cell == 'M' for row in grid for cell in row])
print('\nActual percentage was', 100 * mineCount / sz / sz)

shows it in action:

[' ', ' ', 'M', ' ', ' ', ' ', 'M', ' ', ' ', ' ']
['M', ' ', ' ', ' ', 'M', ' ', ' ', ' ', ' ', ' ']
['M', ' ', ' ', ' ', 'M', 'M', ' ', ' ', ' ', ' ']
[' ', 'M', 'M', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['M', ' ', ' ', ' ', ' ', 'M', ' ', ' ', ' ', ' ']
['M', ' ', ' ', ' ', ' ', ' ', 'M', 'M', ' ', ' ']
[' ', ' ', 'M', ' ', 'M', ' ', 'M', ' ', ' ', 'M']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', 'M', ' ', ' ', ' ']

Actual percentage was 19.0
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

I'm not most familiar with Python, so sorry if things don't quite work, but from the looks of things you're looking at making a 2d array, and then filling them with either an empty string "" or a mine "x", based on probability.

Based on the first answer here, you're mostly on the right track with initialising the array, though you may have to make the two "i"s different (given they represent "coordinates" in an array I'd suggest x and y)

createGrid = [[' ' for x in range(gridSize)] for y in range(gridSize)]

You then need to populate the array, and the way I'd suggest you do this would be using nested for loops as shown below:

for i in range(gridSize)
    for j in range(gridSize)
        createGrid[i][j] = //code for mine/empty

This will loop through all values in the array, and then update them based on whether or not it should contain a mine or be empty.

To decide whether or not it should be a mine, your best bet would probably be to import the random module, and use either the randint function or the random function, and then use an if statement to determine whether or not it should be a mine. (The if statement goes within the for loops, the import happens before anything else in your code)

e.g.

import random

if random.randint(0, 10) <= 1
    createGrid[i][j] = "x"

Hope that makes sense and is helpful!

JBrown521
  • 94
  • 9
0

In case you want guaranteed number of mines you could do this:

import random

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]


size = int(input('Enter length of row: '))

# By default 1/size of cells will be mines.
mines = (size**2)//size

# There is probably a better way to get user input, but this will do.
try:
    mines = int(input('Enter number of mines [default=%s]: ' % mines))
except:
    mines = (size**2)//size

# Make an one dimensional list of size square.
field_1d = [' ']*(size**2)

# Stick the mines into the list.
for m in range(mines):
    field_1d[m] = '*'

# Randomly place the mines.
random.shuffle(field_1d)

# Make a 2D list out of the 1D list.
field = [r for r in chunks(field_1d,size)]

# Display it.
for row in field:
    print(row)

Here is the output:

$ ./minesweeper.py
Enter length of row: 3
Enter number of mines [default=3]: 1
[' ', ' ', ' ']
[' ', '*', ' ']
[' ', ' ', ' ']
$ ./minesweeper.py
Enter length of row: 10
Enter number of mines [default=10]:
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', ' ']
[' ', '*', '*', ' ', ' ', ' ', ' ', ' ', ' ', '*']
[' ', ' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ']

Sorry I could resist. I went ahead and wrote a complete minesweeper game:

import random

class Cell():

    def __init__(self,i,j,field):
        self.i = i
        self.j = j
        self.exposed = False
        self.field = field
        self.value = self.calc_value()

    def display(self):
        if self.exposed:
            return self.value
        return '_'

    def expose(self):
        self.exposed = True

    def calc_value(self):
        i = self.i
        j = self.j
        f = self.field

        if self.field[i][j] == '*':
            return '*'
        v=0
        try:
            if f[i-1][j-1] == '*':
                v += 1
        except:
            pass
        try:
            if f[i-1][j] == '*':
                v += 1
        except:
            pass
        try:
            if f[i-1][j+1] == '*':
                v += 1
        except:
            pass
        try:
            if f[i][j-1] == '*':
                v += 1
        except:
            pass
        try:
            if f[i][j+1] == '*':
                v += 1
        except:
            pass
        try:
            if f[i+1][j-1] == '*':
                v += 1
        except:
            pass
        try:
            if f[i+1][j] == '*':
                v += 1
        except:
            pass
        try:
            if f[i+1][j+1] == '*':
                v += 1
        except:
            pass
        return str(v)


def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]


size = int(input('Enter size of field: '))

# 1/10th of cells will be mines.
mines = (size**2)//size

try:
    mines = int(input('Enter number of mines [default=%s]: ' % mines))
except:
    mines = (size**2)//size

# Make an one dimensional list of size square.
field_1d = [' ']*(size**2)

# Stick the mines into the list.
for m in range(mines):
    field_1d[m] = '*'

# Randomly place the mines.
random.shuffle(field_1d)

# Make a 2D list out of the 1D list.
field = [r for r in chunks(field_1d,size)]

# Display it.
for row in field:
    print(row)

board_1d = []
for i in range(size):
    for j in range(size):
        print(i,j)
        board_1d.append(Cell(i,j,field))

board = [r for r in chunks(board_1d,size)]
def display(board):
    for i in range(size):
        for j in range(size):
            print(board[i][j].display(), end='|')
        print("")

def win(board):
    unexposed = 0
    for i in range(size):
        for j in range(size):
            if board[i][j].exposed == False:
                unexposed += 1

    if unexposed == mines:
        print('WINNER!!!!')
        return True

    return False

gameover = False

while not gameover:
    display(board)
    I = int(input('Enter I: '))
    J = int(input('Enter J: '))
    c = board[I][J]
    c.expose()
    if c.value == '*':
       print("BOOM!")
       gameover = True
    gameover = win(board)

display(board)
Red Cricket
  • 9,762
  • 21
  • 81
  • 166