I would like to create a "for" loop (in Python 2). I have a list of obstacles and for each obstacle, if they are true (i.e. exist and appear in the list) I would like to append them to a list called "tests" and call a function called "obstacle_detection" (which deals with what happens when an obstacle is detected) (and I use "tests" later). This is part of a much larger program and I can't quite tell whether it's working, so I was wondering if anyone would be able to tell me if it makes sense? Or advise me of a better way there might be of doing this?
obstacles = [obstacle, obstacle1, obstacle2]
tests = []
counter = 0
for obstacle in obstacles:
tests.append(0)
tests[counter] = obstacle_detection(obstacle, pos)
counter = counter + 1
Your code possibly makes sense, depending on how you define obstacles and obstacle_detection.
As it is, you could write your code this way :
tests = [obstacle_detection(obstacle, pos) for obstacle in obstacles]
It creates a new list automatically, with the same length as obstacles and filled with obstacle_detection values for each obstacle.
Related
My very first post, sorry if I made any mistakes!
I'm messing around the pygame library, and I'm extremely new to python in general. I have created 3 enemies classes and they work as intended, however, this is how I make them move (I call the move function stored inside the class).
I wonder if there is a more clean way to do things. I have many other enemies to code and this seems very repetitive to type, so it's a sign I'm doing something wrong.
I tried creating a "control list" where I list every enemy list there is and I try to access them through their index but it isn't working. I also tried to concatenate but I'm getting an error saying I can't concatenate list names, another error was that my list names turned into strings (yes, I tried using quotation marks). I'm sure this will be a simple fix, but I spent 3 days and I wrap my head around it. If it's possible to do so
The sample of my code so far - it is located in the main run loop of my game.
for giant in lst_enemy_giants:
giant.move()
else:
pass
for spider in lst_enemy_spiders:
spider.move()
else:
pass
for goblin in lst_enemy_goblin:
giant.move()
else:
pass
# The pattern the I want
for ENEMY in lst_enemy_ENEMY:
ENEMY.move()
# where ENEMY is any enemy list that can be stored somewhere
Just chain the iterators together.
from itertools import chain
for enemy in chain(lst_enemy_giants, lst_enemy_spiders, lst_enemy_goblin):
enemy.move()
This is a slightly nicer way of writing a nested loop like
for enemy_list in [lst_enemy_giants, lst_enemy_spiders, lst_enemy_goblin]:
for enemy in enemy_list:
enemy.move()
Unrelated, but I recommend keeping a single dict like
enemies = {'giants': [...], 'spiders': [...], 'goblins': [...]}
rather than three separate variables referencing separate lists. You can still use, for example, enemies['giants'] anywhere you would have used lst_enemy_giants, but now you can write
for enemy in chain(*enemies.values()):
enemy.move()
I have a class called Move which has a function called getNotation which is used to name a move in chess in a specific manner.
class Move():
def __init__(self):
def getNotation(self):
return OutputString
I have a list class validMoves which contains all the possible moves(each individual element of the list is an instance of the class Move) that can be made for a given GameState.
validMoves=[]
Now I have a program that returns me a move by looking at the opening book but that program returns the move in the form of OutputString (which is the mentioned in the getNotation function in the Move class). Let us call it the bestMove.
My make move function :
def makeMove(move):
# makes the move on the board
Here in my makeMove function , the parameter move can only be an instance of the class Move for the function to work.
So what I did was :
for move in validMoves :
if bestMove == move.getNotation():
makeMove(move)
But I was wondering if there is any other way in which we can make this work because my code has many for loops and I think that it is increasing my runtime.
What I thought of was that if there is any way in which we can modify each element of the list according to a function . Like maybe we can modify each element in validMoves list by appling getNotation without using a for loop , then we can easily check
if bestMove in modifiedvalidMoves :
i = modifiedvalidMoves.index(bestMove)
makeMove(validMoves[i])
The other question if at all this is possible , will this decrease my runtime or not because my perception is that minimizing the number of for loops in code (when it is absolutely not necessary)
increases the speed of the code.
You could consider using the map class from builtins.
Make an iterator that computes the function using arguments from each
of the iterables. Stops when the shortest iterable is exhausted.
result = map(makeMove, validMoves)
would return in result an iterator containing each value of validMoves with the function makeMove applied to it.
I suggest to use a namedtuple
This let you to access to each elements positionally or namely.
I'm working on a game where each object should check if it is colliding with any other object. I have a single list of all the objects and a function which can determine if two objects are colliding and destroys them. The current method I'm using is very inefficient.
for i in list1:
for j in list1:
if collide(i, j):
i.kill()
j.kill()
Initially I removed both objects from the list after they were killed, but some collision occurred without detecting so I reverted back to this code. It works, but I'd like something more efficient.
first this is testing twice too much and also testing if one object collides with itself:
for i in list1:
for j in list1:
if collide(i, j):
i.kill()
j.kill()
This loops exactly len(list1)**2 times.
a very simple way to divide the number of tests by 2 (and avoiding testing against itself):
for i,obj1 in enumerate(list1):
for j in range(i+1,len(list1)):
obj2 = list1[j]
if collide(obj1,obj2):
obj1.kill()
obj2.kill()
It takes advantage of the fact that collide(obj1,obj2) is the same as collide(obj2,obj1).
At this point, you probably want to break out the inner loop since obj1 is now dead. But that depends on what you want to do.
If an accurate collision test is expensive, you could consider a rougher check (distance, rectangle boundary, any quick method), so you can discard items which are too far away from each other without performing the "expensive" test.
I want to solve a puzzle. But I simply don't know what kind of code is required for it. The problem is an exponential one.
Description:
The Player walks/runs one step at a time. Sometimes there will be a decision to be made; that is a yes/no question. Once the question is answered, the player continues walking until the next decision/question is reached. Continue this until the total distance is covered.
The problem is I want to see every possible route through this (many python lists such as ['y','y','n','y','n']). Here is the code I have written so far: (the Player is in a Player() class, I have removed it because it is unimportant here.)
class Solver(object):
""" Solver object. """
def __init__(self, field):
self.field = field
self.dinc = 113
self.distance = 128
def take_step(self, player):
""" Takes a step and records players route. """
# Adds 0 if there is no decision to be made on this step
# Adds 1 if there is a decision to be made on this step
player.run(self.dinc)
if self._is_decision_time(player):
player.route.append((player.step_id, 1))
else:
player.route.append((player.step_id, 0))
def next_decision(self, player):
""" Accepts a player object. Walks until reaches next decision. """
while not self._is_decision_time(player):
self.take_step(player)
self.display_stats(player)
def say_no(self, player):
""" Simulates a no response. Resets danger. Updates route with decision. """
player.route[-1] = (player.step_id, 'n')
player.danger = 0
print 'no!'
def say_yes(self, player):
""" Simulates a yes response. Updates route with decision. """
player.route[-1] = (player.step_id, 'y')
print 'yes!'
The solution of what I'm looking for is like this:
Walk until a question is reached
Make a copy of the route
On route A say Yes
On route B (the copy) say No
Route A:
repeat what is above (this forks another two routes)
Route B:
repeat what is above (this forks another two routes)
Using the code I have so far, it is something like:
route_a = Player()
solver = Solver()
# walk until a battle is reached
solver.next_decision(route_a)
# make a copy of the route (there are now two routes A + route B)
route_b = copy.deepcopy(route_a)
# on route A say 'yes'
solver.say_yes(route_a)
# on route B say 'no'
solver.say_no(route_b)
# walk until the next decision is reached
solver.next_battle(route_a)
solver.next_battle(route_b)
# Then?
This problem is exponential, because at each decision the route forks into two more routes. I need all of the possibilities; I happen to know there are less than 512 possibilities so a computer can solve it in an instant.
Each route will be stored in a Player.route instance (as a list, eg: ['y','y','n','y'])
I just have no idea how to solve a problem like this programmatically. I would appreciate some ideas as to how to structure code to solve a problem like this.
Actually, such a data structure -- a binary tree -- is used in order to just avoid the exponential problem you mentioned. Or, in other words, the supposed list of 'y' and 'n' will grow exponentially, but usually you don't need it, because you have the binary tree. You know that you get each way by a yes-or-no question.
But, if you want to print the list you were asking for, do it like in this pseudo-code (since I'm lost to C++, I still can't program in Python ;-) )
def recurse(node, s=''):
if node == end_node:
print s
return
recurse(node.left, s + 'n')
recurse(node.right, s + 'y')
Then invoke the function starting at the root or head node, i.e. recurse(root_node).
This seems like a fairly easy job for recursion and you already have a pretty simple tree structure. Perhaps you should just migrate the decision process into an explicit tree structure and implement a recursive traversal of the nodes? That's probably the most prudent solution given what it looks like you're trying to do. I guess you're looking for "brute force"... but the alternate iterative solution would be a lot less elegant (and harder to write).
A naive, but probably a suitable way to generate permutations like this is to run through numbers 0..512, convert them to binary (with right padding) and treat zeroes as 'No' and ones as 'Yes'. Nine bits is enough for 512 values, so generate a string like this:
'{0:0>9b}'.format(123)
I have several lines in my code that look very similar to
[this.Attribute for this in THAT if something]
Is there a way to make a function to return that in a shorter way? Because it gets very tedious creating them and I don't find them so readable especially if there's too many 'if-conditions'.
edit:
Well, I often spend time trying to get something from a big list meeting certain criteria. And I often need to change the criteria and the output.
Like so:
[obj for obj in Object.ALLOBJECTS if obj.pos == (x,y)]
[creature.pos for creature in Creature.ALLCREATURES if creature is not caller]
[creature for creature in Creature.ALLCREATURES if creature.pos == pos and creature is not caller]
And so on.
Maybe I'm doing something wrong from the start.
You could outsource the conditional to a function. If it's complex, that
would split up the complexity and make each part easier to read, which
is more or less the point of functions in the first place.