Skip to content
Snippets Groups Projects
Commit 0f68cd26 authored by David Palmer's avatar David Palmer
Browse files

Completed and self-tested tower of hanoi puzzle

parent 9a62a3cb
Branches
No related tags found
No related merge requests found
# GroupProject
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://git.cardiff.ac.uk/c23031373/groupproject.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://git.cardiff.ac.uk/c23031373/groupproject/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
import random
password = "apuzaazle"
def print_key():
print(
1,
"",
2,
"",
3,
"",
4,
"",
5,
"",
6,
"",
7,
"",
8,
"",
9,
"",
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
)
print(
"a ",
"b ",
"c ",
"d ",
"e ",
"f ",
"g ",
"h ",
"i ",
"j ",
"k ",
"l ",
"m ",
"n ",
"o ",
"p ",
"q ",
"r ",
"s ",
"t ",
"u ",
"v ",
"w ",
"x ",
"y ",
"z ",
)
def function_guessing(encoded_word, function):
print("Figure out the function to decode the password")
print("This is the encoded password: ", encoded_word)
print(function)
function_guess = 0
for i in range(5, 0, -1):
run = True
while run:
try:
function_guess = int(input("Guess a number between -26 and 26: "))
run = False
except ValueError:
print("Enter an integer between -26 and 26")
if function_guess > function:
print("Lower")
elif function_guess < function:
print("Higher")
else:
return True
print("You have", i, "guesses left")
return False
def decode(encoded_word):
# Allows for 2 attemps in case the user typo or mistake
for j in range(2):
print(
"The function you have found will be how many places in the alphabet is added to or subracted from the non-encoded password"
)
print("This is the encoded password: ", encoded_word)
print_key()
guess = input("Guess the password: ")
if guess == password:
print("CORRECT")
break
# Needs to make sure the user knows they have one more try or if they have just failed
else:
if j == 0:
print("One more try!")
else:
print("FAIL")
def function_setter():
"""Returns the randomly generated number to act as the function"""
# Needed to have 2 seperate random number generators for negative and positive numbers as it is not continuous
# And also needed to randomly choose if the function is negative or positive
negpos = random.randint(0, 1)
if negpos:
return random.randint(3, 23)
else:
return random.randint(-23, -3)
def encode(function):
"""Returns a string that seems like a jumble of random letter"""
# Creating a list with the corresponding place in the alphabet of each letter in the word
nums_of_chars = []
for char in password:
num = ord(char) - 96
nums_of_chars.append(num)
# Creates a list, where each item is a letter in the now encoded word
encoded_list = []
for item in nums_of_chars:
# This ensures that when going above 26, it goes back to 1 again and when going below 1 it goes to 26
num = (item + function) % 26
if num == 0:
num = 26
encoded_list.append(chr(num + 96))
# converts the list of the encoded word to a string
encoded = ""
for item in encoded_list:
encoded += item
return encoded
def decoder_puzzle():
"""
Runs the decoding loop, currently allowing for an infinite amount of trys to guess the function
"""
for c in range(2, -1, -1):
function = function_setter()
encoded_word = encode(function)
# function = -(function)
correct = function_guessing(encoded_word, function)
if correct:
print("That is the function!")
break
else:
if c == 0:
print("You Failed")
else:
print("You have", c, "more chances!")
if correct:
decode(encoded_word)
else:
return False
return True
#!/usr/bin/python3
from decoder import *
from gameparser import *
from items import *
from lightswitches import *
from map import rooms
from player import *
def check_complete(room):
if room == rooms["Reception"]:
if len(room["items"]) >= 6:
print("YOU HAVE COMPLETED THE GAME, CONGRATULATIONS!!!")
return True
return False
def list_of_items(items):
"""This function takes a list of items (see items.py for the definition) and
returns a comma-separated list of item names (as a string). For example:
"""
items_string = ""
for item in items:
items_string = items_string + item["name"] + ", "
# items_string = (
# items_string + item["name"] + " (" + str(item["mass"]) + "g)" + ", "
# )
items_string = items_string[:-2]
return items_string
def print_room_items(room):
"""This function takes a room as an input and nicely displays a list of items
found in this room (followed by a blank line). If there are no items in
the room, nothing is printed. See map.py for the definition of a room, and
items.py for the definition of an item. This function uses list_of_items()
to produce a comma-separated list of item names. For example:
"""
items_list = room["items"]
items_string = list_of_items(items_list)
if items_string == "":
pass
else:
print("There is " + items_string + " here.")
print("")
def print_inventory_items(items):
"""This function takes a list of inventory items and displays it nicely, in a
manner similar to print_room_items(). The only difference is in formatting:
print "You have ..." instead of "There is ... here.". For example:
"""
items_string = list_of_items(inventory)
if items_string == "":
print("You have nothing")
else:
print("You have " + items_string + ".")
# print(
# "Your inventory's weight is "
# + str(inventory_weight)
# + "g out of "
# + str(inventory_max_weight)
# + "g."
# )
print("")
def print_room(room):
"""This function takes a room as an input and nicely displays its name
and description. The room argument is a dictionary with entries "name",
"description" etc. (see map.py for the definition). The name of the room
is printed in all capitals and framed by blank lines. Then follows the
description of the room and a blank line again. If there are any items
in the room, the list of items is printed next followed by a blank line
(use print_room_items() for this). For example:
"""
# Display room name
print()
print(room["name"].upper())
print()
# Display room description
print(room["description"])
print()
# Displays items in the room
print_room_items(room)
def exit_leads_to(exits, direction):
"""This function takes a dictionary of exits and a direction (a particular
exit taken from this dictionary). It returns the name of the room into which
this exit leads. For example:
"""
return rooms[exits[direction]]["name"]
def print_exit(direction, leads_to):
"""This function prints a line of a menu of exits. It takes a direction (the
name of an exit) and the name of the room into which it leads (leads_to),
and should print a menu line in the following format:
GO <EXIT NAME UPPERCASE> to <where it leads>.
"""
print("GO " + direction.upper() + " to " + leads_to + ".")
def print_menu(exits, room_items, inv_items):
"""This function displays the menu of available actions to the player. The
argument exits is a dictionary of exits as exemplified in map.py. The
arguments room_items and inv_items are the items lying around in the room
and carried by the player respectively. The menu should, for each exit,
call the function print_exit() to print the information about each exit in
the appropriate format. The room into which an exit leads is obtained
using the function exit_leads_to(). Then, it should print a list of commands
related to items: for each item in the room print
"TAKE <ITEM ID> to take <item name>."
and for each item in the inventory print
"DROP <ITEM ID> to drop <item name>."
For example, the menu of actions available at the Reception may look like this:
You can:
GO EAST to your personal tutor's office.
GO WEST to the parking lot.
GO SOUTH to MJ and Simon's room.
TAKE BISCUITS to take a pack of biscuits.
TAKE HANDBOOK to take a student handbook.
DROP ID to drop your id card.
DROP LAPTOP to drop your laptop.
DROP MONEY to drop your money.
What do you want to do?
"""
print("You can:")
# Iterate over available exits
for direction in exits:
# Print the exit name and where it leads to
print_exit(direction, exit_leads_to(exits, direction))
# Iterate over all items in the room
for item in room_items:
# Print the item id and the item name with formatting
print("TAKE " + item["id"].upper() + " to take " + item["name"] + ".")
# Iterate over all items in the player's inventory
for item in inv_items:
print("DROP " + item["id"].upper() + " to drop your " + item["id"] + ".")
if puzzle_check():
print("ATTEMPT", current_room["puzzle"], "Puzzle")
print("What do you want to do?")
def is_valid_exit(exits, chosen_exit):
"""This function checks, given a dictionary "exits" (see map.py) and
a players's choice "chosen_exit" whether the player has chosen a valid exit.
It returns True if the exit is valid, and False otherwise. Assume that
the name of the exit has been normalised by the function normalise_input().
For example:
"""
return chosen_exit in exits
def print_clues():
clues = []
for key in rooms:
room = rooms[key]
if room["puzzle_complete"]:
clues.append(room["clue"])
if len(clues) > 0:
print("You know the following clues: ")
for item in clues:
print(item)
print()
def execute_go(direction):
"""This function, given the direction (e.g. "south") updates the current room
to reflect the movement of the player if the direction is a valid exit
(and prints the name of the room into which the player is
moving). Otherwise, it prints "You cannot go there."
"""
global current_room
if direction in current_room["exits"]:
current_room = move(current_room["exits"], direction)
else:
print("You cannot go there.")
def execute_take(item_id):
"""This function takes an item_id as an argument and moves this item from the
list of items in the current room to the player's inventory. However, if
there is no such item in the room, this function prints
"You cannot take that."
"""
global inventory_weight
# loops through the items in the room so they can be checked against
for item in current_room["items"]:
if item_id == item["id"]:
inventory_weight += item["mass"]
if inventory_weight > inventory_max_weight:
inventory_weight -= item["mass"]
print("You cannot take that, it is too heavy")
return None
# adds the item to the inventory and removes it from the room
inventory.append(item)
current_room["items"].remove(item)
# inventory_weight
return None
print("You cannot take that.")
def execute_drop(item_id):
"""This function takes an item_id as an argument and moves this item from the
player's inventory to list of items in the current room. However, if there is
no such item in the inventory, this function prints "You cannot drop that."
"""
global inventory_weight
for item in inventory:
if item_id == item["id"]:
inventory_weight -= item["mass"]
# adds the item to the room and removes it from the inventory
inventory.remove(item)
current_room["items"].append(item)
return None
print("You cannot drop that.")
def execute_puzzle(puzzle):
"""This function runs a different puzzle depending on the room and key
in the room dictionary that determins if a puzzle is complete is set to
the output of the puzzle
"""
if puzzle == current_room["puzzle"].lower():
if current_room["puzzle"] == "Decoder":
current_room["puzzle_complete"] = decoder_puzzle()
elif current_room["puzzle"] == "Lights":
lights.StartPuzzle()
current_room["puzzle_complete"] = lights.solved
print("You have a new clue!")
else:
print("You cannot attempt that.")
def execute_command(command):
"""This function takes a command (a list of words as returned by
normalise_input) and, depending on the type of action (the first word of
the command: "go", "take", or "drop"), executes either execute_go,
execute_take, or execute_drop, supplying the second word as the argument.
"""
if 0 == len(command):
return
if command[0] == "go":
if len(command) > 1:
execute_go(command[1])
else:
print("Go where?")
elif command[0] == "take":
if len(command) > 1:
execute_take(command[1])
else:
print("Take what?")
elif command[0] == "drop":
if len(command) > 1:
execute_drop(command[1])
else:
print("Drop what?")
elif command[0] == "attempt":
if len(command) > 1 and current_room["puzzle_complete"] == False:
execute_puzzle(command[1])
else:
print("You cannot attempt that")
else:
print("This makes no sense.")
def puzzle_check():
if current_room["puzzle_complete"] == False and current_room["puzzle"] != False:
return True
return False
def menu(exits, room_items, inv_items):
"""This function, given a dictionary of possible exits from a room, and a list
of items found in the room and carried by the player, prints the menu of
actions using print_menu() function. It then prompts the player to type an
action. The players's input is normalised using the normalise_input()
function before being returned.
"""
# Display menu
print_menu(exits, room_items, inv_items)
# Read player's input
user_input = input("> ")
if user_input == "":
quit()
# Normalise the input
normalised_user_input = normalise_input(user_input)
return normalised_user_input
def move(exits, direction):
"""This function returns the room into which the player will move if, from a
dictionary "exits" of avaiable exits, they choose to move towards the exit
with the name given by "direction". For example:
"""
# Next room to go to
return rooms[exits[direction]]
# This is the entry point of our program
def main():
print(
"YOUR TASK IS TO FIND ALL OF THE ITEMS AND BRING THEM BACK TO RECEPTION. GOOD LUCK!"
)
saved_dict = {
"current_room": current_room,
"rooms_state": rooms,
"inventory": inventory,
}
print(saved_dict)
complete = False
# Main game loop
while not complete:
# Display game status (room description, inventory etc.)
print_room(current_room)
print_inventory_items(inventory)
print_clues()
# Show the menu with possible actions and ask the player
command = menu(current_room["exits"], current_room["items"], inventory)
# Execute the player's command
execute_command(command)
complete = check_complete(current_room)
# Are we being run as a script? If so, run main().
# '__main__' is the name of the scope in which top-level code executes.
# See https://docs.python.org/3.4/library/__main__.html for explanation
if __name__ == "__main__":
main()
import string
# List of "unimportant" words (feel free to add more)
skip_words = [
"a",
"about",
"all",
"an",
"another",
"any",
"around",
"at",
"bad",
"beautiful",
"been",
"better",
"big",
"can",
"every",
"for",
"from",
"good",
"have",
"her",
"here",
"hers",
"his",
"how",
"i",
"if",
"in",
"into",
"is",
"it",
"its",
"large",
"later",
"like",
"little",
"main",
"me",
"mine",
"more",
"my",
"now",
"of",
"off",
"oh",
"on",
"please",
"small",
"some",
"soon",
"that",
"the",
"then",
"this",
"those",
"through",
"till",
"to",
"towards",
"until",
"us",
"want",
"we",
"what",
"when",
"why",
"wish",
"with",
"would",
]
def filter_words(words, skip_words):
"""This function takes a list of words and returns a copy of the list from
which all words provided in the list skip_words have been removed.
For example:
>>> filter_words(["help", "me", "please"], ["me", "please"])
['help']
>>> filter_words(["go", "south"], skip_words)
['go', 'south']
>>> filter_words(['how', 'about', 'i', 'go', 'through', 'that', 'little', 'passage', 'to', 'the', 'south'], skip_words)
['go', 'passage', 'south']
"""
for w in words[:]:
if w in skip_words:
words.remove(w)
return words
def remove_punct(text):
"""This function is used to remove all punctuation
marks from a string. Spaces do not count as punctuation and should
not be removed. The funcion takes a string and returns a new string
which does not contain any puctuation. For example:
>>> remove_punct("Hello, World!")
'Hello World'
>>> remove_punct("-- ...Hey! -- Yes?!...")
' Hey Yes'
>>> remove_punct(",go!So.?uTh")
'goSouTh'
"""
no_punct = ""
for char in text:
if not (char in string.punctuation):
no_punct = no_punct + char
return no_punct
def normalise_input(user_input):
"""This function removes all punctuation from the string and converts it to
lower case. It then splits the string into a list of words (also removing
any extra spaces between words) and further removes all "unimportant"
words from the list of words using the filter_words() function. The
resulting list of "important" words is returned. For example:
>>> normalise_input(" Go south! ")
['go', 'south']
>>> normalise_input("!!! tAkE,. LAmp!?! ")
['take', 'lamp']
>>> normalise_input("HELP!!!!!!!")
['help']
>>> normalise_input("Now, drop the sword please.")
['drop', 'sword']
>>> normalise_input("Kill ~ tHe :- gObLiN,. wiTH my SWORD!!!")
['kill', 'goblin', 'sword']
>>> normalise_input("I would like to drop my laptop here.")
['drop', 'laptop']
>>> normalise_input("I wish to take this large gem now!")
['take', 'gem']
>>> normalise_input("How about I go through that little passage to the south...")
['go', 'passage', 'south']
"""
# Remove punctuation and convert to lower case
no_punct = remove_punct(user_input).lower()
# Convert the string of words into a list of words
word_list = no_punct.split()
# Remove the words in the skip_words list
filtered_list = filter_words(word_list, skip_words)
return filtered_list
item_id = {
"id": "id",
"name": "id card",
"description": """You new shiny student ID card. Expires 1 June 2017.
You wonder why they have printed a suicide hotline number on it?...""",
"mass": 2,
}
item_laptop = {
"id": "laptop",
"name": "laptop",
"description": "It has seen better days. At least it has a WiFi card!",
"mass": 10,
}
item_money = {
"id": "money",
"name": "money",
"description": "This wad of cash is barely enough to pay your tuition fees.",
"mass": 4,
}
item_biscuits = {
"id": "biscuits",
"name": "a pack of biscuits",
"description": "A pack of biscuits.",
"mass": 6,
}
item_pen = {
"id": "pen",
"name": "a pen",
"description": "A basic ballpoint pen.,",
"mass": 3,
}
item_handbook = {
"id": "handbook",
"name": "a student handbook",
"description": "This student handbook explains everything. Seriously.",
"mass": 12,
}
class LightPuzzle:
def __init__(self):
self.statearray = [[1, 0, 1], [0, 0, 0], [1, 0, 1]]
self.solved = False
def PrintPuzzle(self):
i = 3
for row in self.statearray:
rowprint = " ".join([str(tile) for tile in row])
print(str(i)+"| "+rowprint)
i-=1
print(" _ _ _")
print(" 1 2 3")
print()
def FlipTile(self, x, y):
self.statearray[y][x] = self.ChangeState(self.statearray[y][x])
if y > 0:
self.statearray[y - 1][x] = self.ChangeState(self.statearray[y - 1][x])
if y < len(self.statearray) - 1:
self.statearray[y + 1][x] = self.ChangeState(self.statearray[y + 1][x])
if x > 0:
self.statearray[y][x - 1] = self.ChangeState(self.statearray[y][x - 1])
if x < len(self.statearray[y]) - 1:
self.statearray[y][x + 1] = self.ChangeState(self.statearray[y][x + 1])
def ChangeState(self, number):
return 0 if number == 1 else 1
def TakeEdit(self):
valid = False
while not valid:
ToChange = input(
"What part of the puzzle would you like to flip? Enter coordinates in the format X,Y (1-3): "
)
if ToChange == "":
quit()
XY = ToChange.split(",")
if len(XY) != 2 or not XY[0].isdigit() or not XY[1].isdigit():
print("Invalid input. Please enter two numbers separated by a comma.")
elif int(XY[0]) > 3 or int(XY[0]) < 1 or int(XY[1]) > 3 or int(XY[1]) < 1:
print("Invalid input. Coordinates must be between 1 and 3.")
else:
valid = True
self.FlipTile(int(XY[0]) - 1, 3 - int(XY[1]))
def StartPuzzle(self):
for i in range(10):
if i == 9:
print("You have", 10 - i, "go left")
else:
print("You have", 10 - i, "goes left")
self.PrintPuzzle()
self.TakeEdit()
self.CheckSolved()
if self.solved:
print("Puzzle solved!")
break
def CheckSolved(self):
for row in self.statearray:
if 0 in row:
return
self.solved = True
lights = LightPuzzle()
from items import *
from decoder import *
room_reception = {
"name": "Reception",
"description": """You are in a maze of twisty little passages, all alike.
Next to you is the School of Computer Science and
Informatics reception. The receptionist, Matt Strangis,
seems to be playing an old school text-based adventure
game on his computer. There are corridors leading to the
south and east. The exit is to the west.""",
"exits": {"south": "Admins", "east": "Tutor", "west": "Parking"},
"items": [item_biscuits, item_handbook],
"puzzle": False,
"puzzle_complete": False,
}
room_admins = {
"name": "MJ and Simon's room",
"description": """You are leaning agains the door of the systems managers'
room. Inside you notice Matt "MJ" John and Simon Jones. They
ignore you. To the north is the reception.""",
"exits": {"north": "Reception"},
"items": [],
"puzzle": "Decoder",
"puzzle_complete": False,
"clue": "Decoder Hint",
}
room_tutor = {
"name": "your personal tutor's office",
"description": """You are in your personal tutor's office. He intently
stares at his huge monitor, ignoring you completely.
On the desk you notice a cup of coffee and an empty
pack of biscuits. The reception is to the west.""",
"exits": {"west": "Reception"},
"items": [],
"puzzle": "Lights",
"puzzle_complete": False,
"clue":"Lights clue",
}
room_parking = {
"name": "the parking lot",
"description": """You are standing in the Queen's Buildings parking lot.
You can go south to the COMSC reception, or east to the
general office.""",
"exits": {"east": "Office", "south": "Reception"},
"items": [],
"puzzle": False,
"puzzle_complete": False,
}
room_office = {
"name": "the general office",
"description": """You are standing next to the cashier's till at
30-36 Newport Road. The cashier looks at you with hope
in their eyes. If you go west you can return to the
Queen's Buildings.""",
"exits": {"west": "Parking"},
"items": [item_pen],
"puzzle": False,
"puzzle_complete": False,
}
rooms = {
"Reception": room_reception,
"Admins": room_admins,
"Tutor": room_tutor,
"Parking": room_parking,
"Office": room_office,
}
from items import *
from map import rooms
inventory = [item_id, item_laptop, item_money]
inventory_weight = item_id["mass"] + item_laptop["mass"] + item_money["mass"]
inventory_max_weight = 25
# Start game at the reception
current_room = rooms["Reception"]
#sliding puzzle
import random
class SlidePuzzle:
solved_board = [[1, 2, 3], [4, 5, 6], [7, 8, " "]] # Final solved board
def __init__(self):
"""
Create a new shuffled board when the object is created
"""
self.board = self.shuffled_board()
def print_board(self):
"""
Prints the current state of the board
"""
for row in self.board:
print('_|_'.join(str(cell) for cell in row))
def find_empty_cell(self):
"""
Finds the position of the empty cell in the board
"""
for i, row in enumerate(self.board):
for j, cell in enumerate(row):
if cell == " ":
return i, j
def shuffled_board(self):
"""
Creates a new shuffled board by randomly shuffling numbers
"""
board = [1, 2, 3, 4, 5, 6, 7, 8, " "]
random.shuffle(board)
return [board[i:i+3] for i in range(0, len(board), 3)]
def is_solved(self):
"""
Checks if the current board is the solved board or not
"""
return self.board == SlidePuzzle.solved_board
def move(self, direction):
"""
Moves the empty cell in the given direction if it is valid. Otherwise, it prints an error message.
"""
empty_cell = self.find_empty_cell()
i, j = empty_cell
if direction == "up" and i > 0:
self.board[i][j], self.board[i-1][j] = self.board[i-1][j], self.board[i][j]
elif direction == "down" and i < 2:
self.board[i][j], self.board[i+1][j] = self.board[i+1][j], self.board[i][j]
elif direction == "left" and j > 0:
self.board[i][j], self.board[i][j-1] = self.board[i][j-1], self.board[i][j]
elif direction == "right" and j < 2:
self.board[i][j], self.board[i][j+1] = self.board[i][j+1], self.board[i][j]
else:
print("Invalid direction! Try again.")
def play_game():
"""
The main game loop, asks the player for a move until the puzzle is solved
"""
puzzle = SlidePuzzle()
while not puzzle.is_solved():
puzzle.print_board()
move = input("Enter the direction (up, down, left, right): ").lower()
puzzle.move(move)
if puzzle.is_solved():
print("Congratulations! You solved the puzzle!")
puzzle.print_board()
play_game()
\ No newline at end of file
def print_tower(start_index, current_layout):
"""
prints out each tower by using a different index to start from. each row in a tower is +3 index from the previous in the list
"""
for i in range(start_index, 15, 3):
tower_row = ''
for char in current_layout[i]:
tower_row += char
print(tower_row)
print()
def display_towers(current_layout):
"""
loops to print every tower, providing the starting index for each tower using that loop
"""
for i in range (0, 3):
print_tower(i, current_layout)
def select_tower(x):
"""
repeatedly asks the user to choose one of the threee towers until they give a valid choice. x represents whether they are selecting a tower to move an item from or to
"""
invalid_input = True
while invalid_input:
if x == 1:
chosen_tower = input("Please select a tower to take an item from (top, middle, bottom) >> ").upper()
else:
chosen_tower = input("Please select the tower you want to move the item to (top, middle, bottom) >> ").upper()
if chosen_tower == "TOP":
return 0
elif chosen_tower == "MIDDLE":
return 1
elif chosen_tower == "BOTTOM":
return 2
else:
print("not a valid choice, please type 'top', 'middle', or 'bottom'\n")
def valid_move(item_to_go_above, item_beneath):
"""
tests to see if the player is trying to put a larger item on top of a smaller item (e.g., 2 on top of 1) as this is an invalid move to make
"""
if item_to_go_above > item_beneath:
print("Invalid move, cannot have a bigger item on top of a smaller one")
return False
else:
return True
def move_tile(current_layout):
"""
will (based on validation results carried out in other sub-routines) move an item from one tower to another
"""
tower_start_index = select_tower(1)
selected_empty_tower = True #assume they selected an empty tower until porven otherwise
for i in range(tower_start_index, 15, 3):
if current_layout[i] > [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' ']: #means that you have found the first row with a number on
selected_empty_tower = False
row_to_move = current_layout[i]
break
if selected_empty_tower:
print("There is nothing to move on the tower you chose")
else:
new_tower_start_index = select_tower(2)
if new_tower_start_index != tower_start_index: #changes only need to be made if user decides to move item to a different tower
for j in range (new_tower_start_index, 15, 3):
if current_layout[j] > [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' ']:
if valid_move(current_layout[i], current_layout[j]):
current_layout[j - 3] = current_layout[i]
current_layout[i] = [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' ']
return
else:
return
else:
return
#if code reaches this point the tower to move item to must be empty - so add item to very bottom of that tower
current_layout[new_tower_start_index + 12] = current_layout[i]
current_layout[i] = [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' ']
def tower_of_hanoi():
"""
this is the main game loop, it will repeatedly let the player move items from one tower to another until they get their towers to match the solution
"""
#how the board will be displayed to the user at the beginning
current_layout = [
[' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ','1','1','|','1','1',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '],
[' ',' ',' ','2','2','2','|','2','2','2',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '],
[' ',' ','3','3','3','3','|','3','3','3','3',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '],
[' ','4','4','4','4','4','|','4','4','4','4','4',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '],
]
#what the board needs to look like for the player to have solved the puzzle
solution = [
[' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ','1','1','|','1','1',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ','2','2','2','|','2','2','2',' ',' ',' '],
[' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ','3','3','3','3','|','3','3','3','3',' ',' '],
[' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ',' ',' ',' ',' ',' ','|',' ',' ',' ',' ',' ',' '], [' ','4','4','4','4','4','|','4','4','4','4','4',' '],
]
objective = """
You must move all items from the top tower to the bottom tower, and have them in the same order as when you started.
You may only move one item at a time - this being the item at the highest point of a given tower.
You cannot place a larger item on top of a smaller item.
You may move the selected item to any of the towers, even if they aren't adjacent.
"""
print(objective)
while current_layout != solution:
display_towers(current_layout)
move_tile(current_layout)
display_towers(current_layout)
print("Congratulations, you solved the puzzle!")
tower_of_hanoi()
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment