Created
January 30, 2016 20:38
-
-
Save SpaceVoyager/341d37d7a94ff7d15a66 to your computer and use it in GitHub Desktop.
eight_puzzle_v0.6.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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