Tetris remove completed line and shift all the remaining block - python

For now the code i'm using is this one:
self.board = numpy.delete(self.board, row, 0)
new_row = [0 for _ in range(configuration.config["cols"])]
self.board = numpy.vstack([new_row, self.board])
The code corretly remove the row(an index) in question from self.board(2d numpy array), then add a new empty row shifting every piece down one.
The problem is when a piece should fall more than one single row, like in this situation:
The yellow piece should go all the way to the bottom since the rest of his tetramino is gone with the row
And i have no idea on how i could implement something like this
Full example:
import numpy
if __name__ == '__main__':
board = numpy.array([
[6,0,0,0,0,5,0,0,0,0],
[6,6,1,1,2,5,5,5,1,2],
[6,6,1,1,1,0,1,0,0,0]
])
expected_result = numpy.array([
[0,0,0,0,0,0,0,0,0,0],
[6,0,0,0,0,0,0,0,0,0],
[6,6,1,1,1,5,1,0,0,0]
])
for y,row in enumerate(board):
if not 0 in row:
board = numpy.delete(board, y, 0)
new_row = [0 for _ in range(10)]
board = numpy.vstack([new_row, board])
print(board)
print("--------")
print(expected_result)

It isn't clear exactly what you're trying to achieve. For what it's worth, the way you have it currently is how the "real" Tetris works. Blocks are left floating.
If you want pieces to fall, how to you want it to work?
Only pieces on the row immediately above? This would leave strange voids in the field but would be achieved by comparing each element in the row with the row below, and if the row below contains a 0 in that place then replace it with the row above. You'd get behaviour like this:
All pieces in rows above the break? This would make an interesting game that would snowball quickly, but would be very different from traditional Tetris (traditional 2nd, all falling 3rd). You would need to loop over all of the rows with the same logic as the single row until you don't find any more elements to move.
If you want to try to reinvent the game you're going to come into some balancing issues - I get that this is a programming exersize but its worth considering that it will probably take more time to make the game playable with falling blocks as it will to work out how to make the blocks fall.

Related

Assign string X to index of multidimensional data based on user directions.

grid = int(input("Grid size: "))
x = []
for i in range(grid):
y = []
for j in range(grid):
e = '.'
y.append(e)
x.append(y)
x[0][0] = 'X'
for row in x:
print(*row)
d = input("Direction: ")
I'm trying to work out how to assign X to the index of the grid position which the user input gives. Below is the question.
You're familiar with the story of Hansel and Gretel, so when you decide to go exploring you always make sure to keep track of where you've come from. Since you know how unreliable leaving a trail of breadcrumbs is, you decide to write a program to help you map out your trail.
Your program should first read in the size of the grid that you will be exploring, and then read in directions: left, right, up or down. You always start exploring at the top left of your map. After every step, you should print out the trail, reading in directions until a blank line is entered. You will never be directed off the edges of the map.

python go board game, struggling to figure out how to capture multiple stones

I've been trying to make a board game of GO, in python with pygame and a numpy array for storing the board locations and stone colors (0, 1, 2). My issue is that I've been using a for loop to examine each index at a time, and examining the adjacent indexes by adding or taking away an int:
columns = 5
rows = 5
def create_board():
board = np.zeros((row,col))
return board
board = create_board()
def libertyCheck():
for c in range(columns):
for r in range(rows):
if board[c][r+1] == 0:
x = 1
(lots more ifs, then add x's to see if all spaces are occupied)
This method seems to be OK for capturing a single stone (as long as its not on the edges of the board, because it also starts causing out of bounds issues), but becomes very convoluted once several stones of the same color are next to each other and may or may not need to be captured.
There has to be a better way of searching these indexes without causing out of bounds? one that will allow me to keep track of all of the stones and their adjacent spaces?

Fast code for finding the max value of a 2d array

I've read a lot of answers including this one so it's not a duplicate (especially with the way I read the value). Is there a faster code for this:
mx = 0
for i in range(0, len(self.board)):
for j in range(0, len(self.board[i])):
for k in range(0, len(self.board[i][j]['b'])):
l = self.board[i][j]['b'][k]
mx = max([mx, l.get('id', 0)])
in Python? Maybe with map but I dont see how?
Each "cell" of the board is a dict like that
'b' = array of dicts: each dicts contains an information about a piece of a game, example: {'id':3, 'nb':1, 'kind':'bee'}. We can have many pieces on the same cell (one piece on top of another one)
'p' = array of ids of the pieces above if we can put them on this cell
'h' = array of 'kind' of pieces that are not yet on the board but we can put on this cell
FYI I pre-calculate the whole board before sending it in JSON to a JavaScript client, so that I can do all pre-calculation in Python, and have to code as few as possible in JavaScript.
It seems you have a board which have rows with cells and each cell have multiple pieces.
You can use list comprehension to get all the ids and then get the `max of it:
max(piece.get('id', 0) for row in self.board for cell in row for piece in cell['b'])
I am not sure how fast it would be (will ofcourse depend on how big your board is) but I am pretty sure it would faster than the 3 for loops and calculating max on each iteration.

Bejeweled Style Game Matches

I am working on designing a bejeweled style game with a twist. Rather than trying to match all the blocks of the same shape, you are trying to match a pair of letters. The board will always have roughly 10 letters on the board and you are trying to get them together. There are three different color blocks. Each color has 1 blank block and then 5 blocks with different letters. The goal is to get say a red "T" block next to a red "A" block. This is where I am running into problems.
Right now, the code will clear from the board three or more of the same color and letter. So, if I can get three red "T" blocks next to each other they will clear. The code basically scans each line looking for a group of three (or more). I have tried to modify the code so it will clear even just the same color (regardless of letter combo) but I can't even get that working. I think it has to do with how I load the images. I have posted most of the code (without any of my crazy modifications to try and get this working since it just broke it) that deals with loading the images and finding matches. Can anybody help me modify the code so it can at least find one correct match. When a red "T" block is next to a red "A" block and a blank red block, it should be classified as a match and be removed from the board. It doesn't need to be anything that complex as long as it works. Thanks for any help!
Find matches code:
def find_matches(self):
def lines():
for j in range(self.h):
yield range(j * self.w, (j + 1) * self.w)
for i in range(self.w):
yield range(i, self.size, self.w)
def key(i):
return self.board[i].image
def matches():
for line in lines():
for _, group in itertools.groupby(line, key):
match = list(group)
if len(match) >= MINIMUM_MATCH:
yield match
return list(matches())
Image loading:
shapes = 'red blue yellow'
rareshapes = 'reda redc redg redt redu bluea bluec blueg bluet blueu yellowa yellowc yellowg yellowt yellowu'
self.shapes = [pygame.image.load('images/{}.png'.format(shape))
for shape in shapes.split()]
self.rareshapes = [pygame.image.load('rareimages/{}.png'.format(shape))
for shape in rareshapes.split()]
EDIT:
Since this post, a lot has changed and been updated with the game. It has sound and background music, the groundwork for a new scoring system, a new timer system, and I can specify which rare shape I want to appear in a specific spot on the grid when the game first starts. However, I am still having issues with the core gameplay. I hate to drag up and older post, but I am at a loss as to how to get this to work. I have messed around with the code dealing with matches with no luck.
Basically, the rareshapes are assigned numbers. So, a red A is 0, a red T is 3, all the way up to a yellow T which is 14. For the gameplay to work the way we intend, the user will need to get a red A (0), a red T(3), and 2 blank red squares next to each other for it to be a valid match and clear from the board. This is the ONLY correct way you can clear squares from the board. Getting 4 blank squares of the same color next to each other DOES NOT remove them.
However, the code needs to detect if they get an invalid pair as well. For example, if they get a red A(0), a red C(1), and two blank red squares, it will disappear but count as a strike against them.
The goal of the game is to remove all the letter blocks before time runs out without getting three strikes. Since we can specify how many and where letter blocks appear now, it just comes down to the matching. Does anybody have any idea how to make this work?
I was reading the code you posted, and I said to myself, that looks pretty good — one-dimensional board representation, well-named variables, use of itertools.groupby — that's pretty much how I would have written it myself. And then I remembered that I had written it myself. Still, I'm glad to see someone's making use of my code!
(Having said that, I notice that you removed the docstring. Why did you do that? Put it back right away!)
Anyway, this match finder uses itertools.groupby to find runs of identical items in a sequence. Or rather, since a key function is given, runs of items where the key function returns identical results.
You can see that the key function as written just returns the image at the board location. This means that board locations match so long as they contain identical images. But you want to relax that: you want board locations to match so long as they contain images of the same colour.
So you need to revise the key function so that it returns the colour of the image at the board location. For example, when you loaded the images you could create a dictionary mapping images to their colour:
self.image_colour = {}
self.shapes = []
self.rareshapes = []
colours = 'red blue yellow'
letters = 'acgtu'
for c in colours.split():
im = pygame.image.load('images/{}.png'.format(c))
self.shapes.append(im)
self.image_colour[im] = c
for l in letters:
im = pygame.image.load('rareimages/{}{}.png'.format(c, l))
self.rareshapes.append(im)
self.image_colour[im] = c
and then in the key function you could look up the image to find its colour:
def key(i):
return self.image_colour.get(self.board[i].image)

Project Euler #82 (Python)

First of all this is the problem : https://projecteuler.net/problem=82 .
This is my code :
# https://projecteuler.net/problem=82
matrice = open('matrix3.txt','r').read().split('\n')
m = []
for el in matrice:
if el=='':
continue
tmp = el.split(',')
m.append(tmp)
matrix = [[0 for i in range(80)]for j in range(80)]
x,y = 0,0
while(True):
matrix[x][y]=int(m[x][y])
y+=1
if y==80:
y=0
x+=1
if x==80:
break
tmp = [0]*80
x,y = 0,78
while(True):
if x==0:
tmp[x]=min(matrix[x][y+1],matrix[x+1][y]+matrix[x+1][y+1])
if x==79:
tmp[x]=min(matrix[x][y+1],matrix[x-1][y]+matrix[x-1][y+1])
else:
tmp[x]=min(matrix[x][y+1],matrix[x-1][y]+matrix[x-1][y+1],matrix[x+1][y]+matrix[x+1][y+1])
x+=1
if x==80:
for e in range(80):
matrix[e][y]+=tmp[e]
tmp = [0]*80
x=0
y+=-1
if y<0:
break
minimo = 10**9
for e in range(80):
if matrix[e][0]<minimo:
minimo=matrix[e][0]
print(minimo)
The idea behind this code is the following:
I start from the 79th column(78th if you start counting from 0) and I calculate the best(the minimal) way to get from any given entry in that column to the column to the right.
When the column is over I replace it with the minimal results I found and I start doing the same with the column to the left.
Is anyone able to help me understand why I get the wrong answer?(I get 262716)
The same code works for the matrix in the example(It works if you change the indeces of course).
If I understand the question, your code, and your algorithm correctly, it looks like you aren't actually calculating the best way to get from one column to the next because you're only considering a couple of the possible ways to get to the next column. For example, consider the first iteration (when y=78). Then I think what you want is tmp[0] to hold the minimum sum for getting from matrix[0][78] to anywhere in the 79th column, but you only consider two possibilities: go right, or go down and then go right. What if the best way to get from matrix[0][78] to the next column is to go down 6 entries and then go right? Your code will never consider that possibility.
Your code probably works on the small example because it so happens that the minimum path only goes up or down a single time in each column. But I think that's a coincidence (also possibly a poorly chosen example).
One way to solve this problem is using the following approach. When the input is a NxN matrix, define a NxN array min_path. We're going to want to fill in min_path so that min_path[x][y] is the minimum path sum starting in any entry in the first column of the input matrix and ending at [x][y]. We fill in one column of min_path at a time, starting at the leftmost column. To compute min_path[i][j], we look at all entries in the (j-1)th column of min_path, and the cost of getting from each of those entries to (i, j). Here is some Python code showing this solution: https://gist.github.com/estark37/5216851. This is an O(N^4) solution but it can probably be made faster! (maybe by precomputing the results of the sum_to calls?)

Categories

Resources