Skip to content

Instantly share code, notes, and snippets.

@SpaceVoyager
Created January 30, 2016 20:38
Show Gist options
  • Save SpaceVoyager/341d37d7a94ff7d15a66 to your computer and use it in GitHub Desktop.
Save SpaceVoyager/341d37d7a94ff7d15a66 to your computer and use it in GitHub Desktop.
eight_puzzle_v0.6.py
import ui
import speech
import random, time
import requests
import json
import random
import urllib
from collections import deque
END_POINT = 'http://192.168.1.8:5000/puzzlescores'
def add_player(player_name):
headers = {'Content-Type': 'application/json'}
data = json.dumps({"name": player_name})
response = requests.post(END_POINT, data, headers=headers)
return response.json()
def get_sorted_players():
headers = {'Content-Type': 'application/json'}
url = END_POINT + '?' + urllib.quote('where={"moves": {"$gt": 1}}&sort=moves,name', safe = '/=&')
r = requests.get(url, headers=headers)
response = r.json()
results = []
for item in response['_items']:
results.append({k:v for k,v in item.iteritems() if k in ['_updated', 'name', 'moves']})
return results
# only update score if the new score is better
def update_score(player_name, score):
headers = {'Content-Type': 'application/json'}
url = END_POINT + '?where=name=="' + urllib.quote(player_name) + '"'
r = requests.get(url, headers=headers)
response = r.json()
if len(response.get('_items', [])) == 1:
player_dict = response['_items'][0]
if 'moves' not in player_dict or player_dict['moves'] > score:
headers['If-Match'] = player_dict['_etag']
data = json.dumps({'moves': score})
r2 = requests.patch(END_POINT + '/' + player_dict['_id'], data, headers=headers)
return r2.json()
else:
return {'_status': 'OK2',
'reason': 'score not updated because it is not better'}
else:
return {'_status': 'ERR',
'reason': 'player ' + player_name + ' not found'}
border_color = (1.00, 0.50, 0.00)
moves = 0
buttons_by_number = {}
shuffled = False
def isAdjacent(row1, col1, row2, col2):
if abs(row1-row2) + abs(col1-col2) == 1:
return True
else:
return False
def move_piece(button, x, y):
def animation():
button.x = x
button.y = y
ui.animate(animation, duration=0.2)
def button_pressed(sender):
global moves
if shuffled:
number = sender.title
index = pieces.index(number)
(row, col) = index2loc(index)
empty_space_index = pieces.index('')
(empty_space_row, empty_space_col) = index2loc(empty_space_index)
if isAdjacent(row, col, empty_space_row, empty_space_col):
move_piece(sender, empty_space_col*sender.width, empty_space_row*sender.width)
moves += 1
steps_label.text = 'Steps: ' + str(moves)
pieces[index] = ''
pieces[empty_space_index] = number
if pieces == win_state:
speech.say('you win', 'en-US', 0.3)
update_score('Yuhang', moves)
def move_this_button(number):
if shuffled:
index = pieces.index(number)
(row, col) = index2loc(index)
empty_space_index = pieces.index('')
(empty_space_row, empty_space_col) = index2loc(empty_space_index)
if isAdjacent(row, col, empty_space_row, empty_space_col):
this_button = buttons_by_number[number]
move_piece(this_button, empty_space_col*this_button.width, empty_space_row*this_button.width)
# steps_label.text = 'Steps: ' + str(moves)
pieces[index] = ''
pieces[empty_space_index] = number
if pieces == win_state:
speech.say('I win', 'en-US', 0.3)
def show_leaderboard(sender):
print get_sorted_players()
def shuffle_now(sender):
global shuffled, moves
for i in range(10):
shuffle()
# speech.say('shuffling is done')
shuffled = True
moves = 0
steps_label.text = 'Steps: ' + str(moves)
def shuffle():
#find what pieces can move
movable_pieces = []
empty_space_index = pieces.index('')
(empty_space_row, empty_space_col) = index2loc(empty_space_index)
for number in pieces:
index = pieces.index(number)
(row, col) = index2loc(index)
if isAdjacent(row, col, empty_space_row, empty_space_col):
movable_pieces.append(number)
random.shuffle(movable_pieces)
to_move = movable_pieces[0]
to_move_button = buttons_by_number[to_move]
move_piece(to_move_button, empty_space_col*to_move_button.width, empty_space_row*to_move_button.width)
pieces[pieces.index(to_move)] = ''
pieces[empty_space_index] = to_move
def goal_test(state):
if state == ('1', '2', '3', '4', '5', '6', '7', '8', ''):
return True
return False
def is_legal(action, state):
index = state.index(action)
(row, col) = index2loc(index)
empty_index = state.index('')
(empty_row, empty_col) = index2loc(empty_index)
return isAdjacent(row, col, empty_row, empty_col)
# apply action to state and return the resulting state
def apply_action(action, state):
index = state.index(action)
(row, col) = index2loc(index)
empty_index = state.index('')
(empty_row, empty_col) = index2loc(empty_index)
new_state = list(state)
new_state[index] = ''
new_state[empty_index] = action
return tuple(new_state)
# initial_state is the tuple (initial positions of pieces)
# we cannot use a list to store state because Python does not allow us to add lists to the explored set
def bfs_eight_puzzle(initial_state):
frontier = deque([(initial_state, [])]) # node is (state, solution path)
explored = set([])
actions = ['1', '2', '3', '4', '5', '6', '7', '8'] # each action is to try to move a piece
while (frontier):
current_node = frontier.popleft()
current_state = current_node[0]
solution_path = current_node[1]
if goal_test(current_state):
# print 'solution found:'
# print solution_path
return solution_path
explored.add(current_state)
for action in actions:
if is_legal(action, current_state):
child_state = apply_action(action, current_state)
if child_state not in explored:
frontier.append((child_state, solution_path + [action])) # solution path is a list of actions taken to go from initial state to this child state
# print 'solution not found'
return None
pieces = ['1', '2', '3', '4', '5', '6', '7', '8', '']
win_state = ['1', '2', '3', '4', '5', '6', '7', '8', '']
v = ui.View(background_color=(0.40, 0.80, 1.00))
board = ui.View()
v.add_subview(board)
v.present('full_screen', hide_title_bar=False , orientations=['landscape'])
steps_label = ui.Label()
steps_label.frame = (30, 30, 250, 70)
#steps_label.background_color = (1.00, 0.00, 0.50)
steps_label.font = ('Futura-CondensedExtraBold', 40)
steps_label.text = ' Steps: 0'
v.add_subview(steps_label)
board.frame = (v.width-v.height, 0, v.height, v.height)
board.border_width = 3
board.border_color = border_color
board.background_color = (1,1,1)
# convert index of button to row number and column number
def index2loc(index):
row = index / 3
column = index % 3
return (row, column)
for i in range(9):
button_text = pieces[i]
if button_text != '':
button = ui.Button(title=button_text)
button.background_color = (1,1,1)
button.font = ('Futura-CondensedExtraBold', 200)
button.width = v.height/3
button.height = button.width
button.border_color = border_color
button.border_width = 2
(r, c) = index2loc(i)
button.x = button.width*c
button.y = button.height*r
button.action = button_pressed
board.add_subview(button)
buttons_by_number[button_text] = button
leader_button = ui.Button(title='Leaderboard')
leader_button.background_color = (1,1,1)
leader_button.frame = (30, 150, 250, 70)
leader_button.corner_radius = 5
leader_button.font = ('Futura-CondensedExtraBold', 40)
leader_button.border_color = (0,0,0)
leader_button.border_width = 1
leader_button.action = show_leaderboard
v.add_subview(leader_button)
shuffle_button = ui.Button(title='Shuffle')
shuffle_button.background_color = (1,1,1)
shuffle_button.frame = (30, 250, 250, 70)
shuffle_button.corner_radius = 5
shuffle_button.font = ('Futura-CondensedExtraBold', 40)
shuffle_button.border_color = (0,0,0)
shuffle_button.border_width = 1
shuffle_button.action = shuffle_now
v.add_subview(shuffle_button)
def auto_solve(sender):
solution = bfs_eight_puzzle(tuple(pieces))
if solution == None:
print 'puzzle too hard. me cannot solve'
else:
for but in solution:
move_this_button(but)
autosolve_button = ui.Button(title='Auto Solve')
autosolve_button.background_color = (1,1,1)
autosolve_button.frame = (30, 350, 250, 70)
autosolve_button.corner_radius = 5
autosolve_button.font = ('Futura-CondensedExtraBold', 40)
autosolve_button.border_color = (0,0,0)
autosolve_button.border_width = 1
autosolve_button.action = auto_solve
v.add_subview(autosolve_button)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment