Python 3,频道1.x,Django 1.11。
游戏是tron轻循环,但要转弯,用户必须解决数学问题。多人游戏,目前最多2人
generate_first_4_problems_game
func (inside channels session - see decorator @channel_session_user
) is triggered at the start of a game. it sends the flux_instance
to generate_first_4_problems
func, which is outside the channels session (I'm not sure if this matters though). Inside generate_first_4_problems
, setattr is supposed to set the values (details aren't too important, just know that the relevant (class) attributes are p1/p2-up/down/left/right (8 attributes total) and they store math problems) in the flux_instance
that is being used in the channels session but that never happens.
Printing getattr(flux_instance,d)
(example, flux.p1up = '2 + 8'
) inside generate_first_4_problems
exhibits expected behavior (math problem is printed), but printing inside send_answer
gives a None.
The focus of this question is inside send_answer
, where getattr(flux_instance,d)
is supposed to be some math problem, which was supposed to be defined in generate_first_4_problems
(and it seems like it was, because the print statement inside of it exhibited expected behavior (a math problem for each getattr(flux_instance, d)
)), but it is not.
有人可以帮忙吗?
def is_correct_answer(problem_string, input_answer):
# determines if input answer is correct for given problem string
def generate_problem(level, operation, flux_instance=None, player_type=None):
# generates random math problem
def generate_first_4_problems(flux_instance, player_type):
creator_directions = ['p1up', 'p1right', 'p1down', 'p1left']
opponent_directions = ['p2up', 'p2right', 'p2down', 'p2left']
problems = []
answers = []
while len(problems) < 4:
problem = generate_problem(flux_instance.level, flux_instance.operation)
answer = x(problem).expr()
# no duplicate answers
if answer not in answers:
if flux_instance.level == 1:
# no negative numbers as answers
if answer > 0:
problems.append(problem)
answers.append(answer)
else:
pass
else:
problems.append(problem)
answers.append(answer)
else:
pass
if player_type == 'creator':
for i, d in enumerate(creator_directions):
setattr(flux_instance, d, problems[i])
elif player_type == 'opponent':
for i, d in enumerate(opponent_directions):
setattr(flux_instance, d, problems[i])
return problems
class Flux:
# player starting positions and directions
creator_history = ['790,358']
opponent_history = ['262,358']
creator_direction = 'left'
opponent_direction = 'right'
# game dimensions in pixels
game_width = 1056
game_height = 708
# questions for player directions
p1up = None
p1right = None
p1down = None
p1left = None
p2up = None
p2right = None
p2down = None
p2left = None
# needed for checkcollision
creator = {
'x': None,
'y': None,
}
opponent = {
'x': None,
'y': None
}
def __init__(self, game_object, game_label):
self.game_object = game_object
self.level = game_object.level
self.operation = game_object.operation
self.game_label = game_label
def update_game_state(self, player_and_direction=None):
last_cx = self.creator_history[-1].split(',')[0]
last_cy = self.creator_history[-1].split(',')[1]
last_ox = self.opponent_history[-1].split(',')[0]
last_oy = self.opponent_history[-1].split(',')[1]
def check_collision(cycle, opponent):
# checks to see if creator or opponent have collided, which would end the game
def get_player_xy(direction, last_x, last_y):
direction_actions = {
'left': lambda last_x, last_y : '%s,%s' % (int(last_x) - 4, last_y),
'right': lambda last_x, last_y : '%s,%s' % (int(last_x) + 4, last_y),
'up': lambda last_x, last_y : '%s,%s' % (last_x, int(last_y) - 4),
'down': lambda last_x, last_y : '%s,%s' % (last_x, int(last_y) + 4),
}
xy = direction_actions[direction](last_x, last_y)
return xy
if player_and_direction != None:
if player_and_direction[0:2] == 'p1':
self.creator_direction = player_and_direction[2:]
elif player_and_direction[0:2] == 'p2':
self.opponent_direction = player_and_direction[2:]
cxy = get_player_xy(self.creator_direction, last_cx, last_cy)
oxy = get_player_xy(self.opponent_direction, last_ox, last_oy)
self.creator_history.append(cxy)
self.opponent_history.append(oxy)
self.creator['x'] = cxy.split(',')[0]
self.creator['y'] = cxy.split(',')[1]
self.opponent['x'] = oxy.split(',')[0]
self.opponent['y'] = oxy.split(',')[1]
check_collision(self.creator, self.opponent)
check_collision(self.opponent, self.creator)
context = {
'cxy': cxy,
'oxy': oxy
}
Group('game-' + self.game_label).send({'text': json.dumps(context)})
def stop_game(self, winner, loser):
context = {}
gs_interval = getattr(self, 'gs_interval', None)
if gs_interval:
self.gs_interval.cancel()
self.game_object.winner = winner
self.game_object.loser = loser
self.game_object.save()
context['game_over_finished'] = True
Group('game-' + self.game_label).send({'text': json.dumps(context)})
@channel_session_user
def ws_receive_game(message):
gamelabel = message.channel_session[u'gamelabel']
gamepk = gamelabel.split('-')[1]
with transaction.atomic():
game = Game.objects.select_for_update().get(pk=gamepk)
data = json.loads(message['text'])
# set these to something to avoid
# referenced before assignment error
flux = Flux(game, gamelabel)
# fix weird glitch where history from last game is loaded
# (find out why this happens at some point)
flux.creator_history = ['790,358']
flux.opponent_history = ['262,358']
flux.creator_direction = 'left'
flux.opponent_direction = 'right'
answer = None
level = None
operation = None
winner = None
current_position = None
current_direction = None
game_start = None
if u'level' in data:
level = data[u'level']
if u'operation' in data:
operation = data[u'operation']
if u'answer' in data:
answer = data[u'answer']
if u'winner' in data:
winner = data[u'winner']
if u'current_position' in data:
current_position = data[u'current_position']
if u'current_direction' in data:
current_direction = data[u'current_direction']
if message.user.username != data[u'username']:
return
context = {}
if message.user == game.creator:
player_type = 'creator'
elif message.user == game.opponent:
player_type = 'opponent'
def game_start():
game.game_start = timezone.now()
flux.game_state = flux.update_game_state()
flux.gs_interval = SetInterval(0.1, flux.update_game_state)
game.save()
def generate_first_4_problems_game(flux_instance, player_type):
problem_list = generate_first_4_problems(flux_instance, player_type)
if player_type == 'creator':
context['creator_problem_list'] = problem_list
else:
context['opponent_problem_list'] = problem_list
# cpl = current_problems_list
def generate_problem_game(level, operation, flux_instance=None, player_type=None):
problem = generate_problem(level, operation, flux_instance, player_type)
return problem
def send_answer(answer, flux_instance, player_type):
directions_list = {
'creator': ['p1up', 'p1right', 'p1down', 'p1left'],
'opponent': ['p2up', 'p2right', 'p2down', 'p2left']
}
for d in directions_list[player_type]:
if is_correct_answer(getattr(flux_instance, d), int(answer)):
flux_instance.game_state = flux_instance.update_game_state(d)
new_problem = generate_problem_game(
flux_instance.level, flux_instance.operation, flux_instance, player_type)
setattr(flux_instance, d, new_problem)
context['new_problem'] = [d, new_problem]
signals = {
u'generate_first_4_problems_game': partial(generate_first_4_problems_game, flux, player_type),
u'send_answer': partial(send_answer, answer, flux, player_type),
u'game_start': game_start,
}
if 'signal' in data and message.user.username == data[u'username']:
signal = data[u'signal']
signals[signal]()
print('context', context)
Group('game-' + gamelabel).send({'text': json.dumps(context)})