Importing function in python - python

I am trying to create menu where user can choose which part of the program he/she wants to run. When I am importing function computer automatically runs it rather to wait for user input. What shall I do to run function only when called? My code:
import hangman
menu = raw_input("""Welcome to Menu, please choose from the following options:
1. Hangman game
2.
3.
4. Exit
""")
if menu == 1:
hangman()
elif menu == 2:
"Something"
elif menu == 3:
"Something"
elif menu == 4:
print "Goodbye"
else:
print "Sorry, invalid input"
The code for hangman.py looks like that:
import random
words = ["monitor", "mouse", "cpu", "keyboard", "printer",]
attempts = [] # Stores user input
randomWord = random.choice(words) # Computer randomly chooses the word
noChar = len(randomWord) # Reads number of characters in the word
print randomWord , noChar
print "Hello, Welcome to the game of Hangman. You have to guess the given word. The first word has", noChar, " letters."
def game():
guess = raw_input ("Please choose letter")
attempts.append(guess) # Adds user input to the list
print (attempts)
if guess in randomWord:
print "You have guessed the letter"
else:
print "Please try again"
while True:
game()
chance = raw_input ("Have a guess")
if chance == randomWord:
print "Congratulations, you have won!"
break

Without seeing hangman.py, I would assume that it directly contains the code for running the hangman game, not wrapped in a function. If that's the case, you created a module, no function (yet).
Wrap that code in
def run_hangman():
# Your existing code, indented by 4 spaces
# ...
import it like this:
from hangman import run_hangman
and finally call the function like this:
run_hangman()

So here is the start menu:
import hangman
option = raw_input('1) Start Normal\n2) Quick Start\n3) Default') # '\n' is a new line
if option == '1':
hangman.main()
elif option == '2':
hangman.run_hangman('SKIP')
elif option == '3':
handman.run_hangman('Default User')
Inside your hangman code you want to have it modulated. You should have somthing like this:
def main():
stuff = raw_input('Starting new game. Please enter stuff to do things')
run_hangman(stuff)
def run_hangman(options):
if options == 'SKIP':
important_values = 5
vales_set_by_user = 'Player 1'
else:
values_set_by_user = options
rest_of_code()

Related

Get a single character in Python as input without having to press Enter (Similar to getch in C++)

First of all, I am totally new in Python, having just started to learn it. I know a lot of stuff about C++ however and I am just trying to implement some of those in Python.
I have done quite a search on it but I couldn't find any solution that fits my requirement. Please see the following code,
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except:
print("Error!")
def __call__(self): return self.impl()
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
def mainfun():
check = fh = True
while check:
fh = True
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print ("Welcome to Tic Tac Toe Game!!!\n\n")
print("Enter 1 to Start Game")
print("Enter 2 to Exit Game")
a = _Getch()
if a == "1":
while fh:
os.system("cls")
drawboard()
playermove()
fh = checkresult()
elif a == "2":
break
As you can see, What I am trying to do here is asking the user to press a number from 1 and 2 and then store that number in "a" and then use it for my requirements.
Now, I first tried using this,
input('').split(" ")[0]
But this didn't work. It required me to always Press Enter after having typed 1 or 2. So, that didn't work.
Then I found this class of Getch and I implemented it. Long story short, it entered me into a never ending loop and my result is something like this now,
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
And it is a never ending loop... Even if I press any key like "1" or "2", it still doesn't stop and keep on performing this and don't enter any function.
What I want is a function similar to this,
It should work on PYCHARM Console (I am practicing and I don't want to practice on Terminal. I am used to using the console of the IDE I am working on)
It pauses and waits for the user to enter any input (like input does)
It accepts and stores the very first key entered by the user into the variable. Like in this case, if user presses "1" then it should store that character in "a" and simply move on. You don't have to Press "ENTER" to move on.
If the user presses any other button like "a" or "b" or anything like this, it will simply not do anything and keep on asking for the input until the required number "1" or "2" is entered (and I think that can very easily be handled in this while loop)
In other words, I just want an alternative to getch() command of C++ in Python. I have tried a lot to find it, but I couldn't. Please refer to me a question which provides a solution to this exact question or provide a solution here. Thank you.
Edit: Please note this isn't the complete code. I have only provided the code which is relevant. If anyone needs to see the whole code, I am happy to share that as well.
Complete code is as follows,
import os
import keyboard
def getch():
alphabet = list(map(chr, range(97, 123)))
while True:
for letter in alphabet: # detect when a letter is pressed
if keyboard.is_pressed(letter):
return letter
for num in range(10): # detect numbers 0-9
if keyboard.is_pressed(str(num)):
return str(num)
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
playerturn = 1
def drawboard():
global playerturn
print("Player 1 (X) - Player 2 (O)\n")
print("Turn: Player " + str(playerturn))
print("\n")
for i in range(3):
print (" ", end='')
for j in range(3):
print(arr[i][j], end='')
if j == 2:
continue
print(" | ", end='')
if i == 2:
continue
print("")
print("____|____|____")
print(" | | ")
def playermove():
global playerturn
row = col = 0
correctmove = False
print("\n\nMake your Move!\n")
while not correctmove:
row = int(input("Enter Row: "))
col = int(input("Enter Col: "))
if (3 > row > -1) and (-1 < col < 3):
for i in range(3):
for j in range(3):
if arr[row][col] == 0:
correctmove = True
if playerturn == 1:
arr[row][col] = 1
else:
arr[row][col] = 2
playerturn += 1
if playerturn > 2:
playerturn = 1
if not correctmove:
print ("Wrong Inputs, please enter again, ")
def checkwin():
for player in range(1, 3):
for i in range(3):
if arr[i][0] == player and arr[i][1] == player and arr[i][2] == player: return player
if arr[0][i] == player and arr[1][i] == player and arr[2][i] == player: return player
if arr[0][0] == player and arr[1][1] == player and arr[2][2] == player: return player
if arr[0][2] == player and arr[1][1] == player and arr[2][0] == player: return player
return -1
def checkdraw():
for i in range(3):
for j in range(3):
if arr[i][j] == 0:
return False
return True
def checkresult():
check = checkwin()
if check == 1:
os.system('cls')
drawboard()
print("\n\nPlayer 1 has won the game!!\n")
elif check == 2:
os.system('cls')
drawboard()
print("\n\nPlayer 2 has won the game!!\n")
elif check == 3:
os.system('cls')
drawboard()
print("\n\nThe game has been drawn!!\n")
else:
return True
return False
def mainfun():
check = fh = True
while check:
os.system("cls")
fh = True
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print ("Welcome to Tic Tac Toe Game!!!\n\n")
print("Enter 1 to Start Game")
print("Enter 2 to Exit Game")
a = getch()
if a == "1":
while fh:
os.system("cls")
drawboard()
playermove()
fh = checkresult()
elif a == "2":
break
print ("Press any key to continue...")
getch()
mainfun()
EDIT2: Problem is resolved by using Keyboard module... The next issue here is how do I remove the data stored in input buffer after the getch() function is called? Because the data in buffer is getting displayed on the next input (when I am taking in the row and column) and I don't want that to happen. I fonud a solution for Linux but not for Windows (or for Pycharm)
It looks like this feature isn't in the standard python library but you can recreate it.
First, install the module 'keyboard'
$ pip3 install keyboard
Then you can use keyboard.is_pressed() to see if any one character is pressed.
import keyboard # using module keyboard
import string # use this to get the alphabet
print("Input a character")
def getch():
alphabet = list(string.ascii_lowercase)
while True:
for letter in alphabet: # detect when a letter is pressed
if keyboard.is_pressed(letter):
return letter
for num in range(10): # detect numbers 0-9
if keyboard.is_pressed(str(num)):
return str(num)
answer = getch()
print("you choose " + answer)
Edit: For unix you need to run with the script with sudo. This code should work fine on windows.
For EDIT-2:
Use below code to flush the screen:
sys.stdout.flush()

Code end up in an endless loop. Can't see why

I am working on a simple function to let the user select the language.
But for some reason, I can't see my mistake and the while loop never breaks.
def chooseLanguage():
"""Simple function to let the user choose what language he wants to play in"""
if game["language"] == "en_EN":
import res.languages.en_EN as lang
elif game["language"] == "de_DE":
import res.languages.de_DE as lang
else:
while game["language"] is None:
print ("Hello and welcome! Please select a language.")
print ("1. German / Deutsch")
print ("2. English")
langC = input ("Your choice: ")
if inputValidator(1, langC) == 1:
game["language"] = "de_DE"
break
elif inputValidator(1, langC) == 2:
game["language"] = "en_EN"
break
if game["language"] is None:
chooseLanguage()
else:
pass
Evidently the infinite loop was caused by inputValidator returning a value that was neither equal to 1 or 2. Thus the exit conditions of the loop were never met. And so it continues.

My display menu repeats multiple times when an input is entered

I'm practice classes and inheritance in a program idea that I came up with myself. Basically Im making an arcade game menu simulator that can play two modes, single player and multiplayer. Every time I enter a choice, either 1 or 2, the menu displays a couple times and then it proceeds to accept the input, I only want the menu to be displayed once. Heres my code:
# Suppose you are at an arcade and you and your friend want to play a multiplayer game that requires UI.
# Make the game ask for the users name and age to see if they can play, make the program so that it can add a friend.
# If any of the players are under the age of 18, they are not allowed to play, otherwise proceed.
# **EXTRA CREDIT** --> Add a functionality which adds the players to a list until the list reaches 4 players, then stop adding to the list.
# arcade_game.py
import sys
# give the user a greeting
import self as self
lst = []
class menu:
def __init__(self, ready):
self.ready = ready
#display menu
#classmethod
def display_menu(self):
print("Pick from one of the choices below, type in the corressponding number")
print("1. single player \n"
"2. Multiplayer")
choice = int(input("Enter your choice here: "))
return choice
# ready or not function to see if the user is ready to play
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
# add players class
class player(menu):
# add a default player to __init__(), **(since there has to be at least one player)**
def __init__(self, ready, player1):
super().__init__(ready)
self.player1 = player1
# single player method
def set_name(self):
self.player1 = input("Enter your name for single player mode")
print("Lets play! ", self.player1)
# multiplayer method
def set_names(self):
try:
self.player1 = input("Enter your name to begin")
lst.append(self.player1)
# add another player to continue
while len(lst) <= 4:
add = input("Add player here: ")
lst.append(add)
if len(lst) == 4:
print("Player limit reached!")
break;
except ValueError:
print("You didnt enter valid input, please try again")
# get the names of the players only if 1 is picked from display_menu() above, including player1
def check_choice(self):
if self.display_menu() == 1:
self.set_name()
elif self.display_menu() == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
m = menu("yes")
m.ready_or_not()
p = player("yes", "test")
p.check_choice()
ready_or_not calls self.display_menu():
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
check_choice also calls self.display_menu() at least once, and twice if you type anything other than 1 the first time:
def check_choice(self):
if self.display_menu() == 1:
self.set_name()
elif self.display_menu() == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
Your top-level code calls ready_or_not() on one menu instance:
m = menu("yes")
m.ready_or_not()
… and check_choice() on another:
p = player("yes", "test")
p.check_choice()
So, your program displays the menu twice, and then a third time if you type anything but 1.
If you don't want the menu displayed two or three times, don't call the method two or three times.
If you want to display the menu only once and remember the choice, instead of displaying it two or three times, you need to use that self.ready attribute that you create in ready_or_not, instead of calling the method again.
However, that still isn't going to work as-is, because your class design is weird. You've made two separate instances, m and p, each of which has its own independent attributes. I'm not sure why player inherits from menu in the first place (or why display_menu is a #classmethod, or why it calls its parameter self rather than cls if it is one, and various other things), but, given that a player is a menu in your design, you probably just want a single player instance, like this:
p = player("yes", "test")
p.ready_or_not()
p.check_choice()
And then, you can change check_choice like this:
def check_choice(self):
if self.choice == 1:
self.set_name()
elif self.choice == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
Took me a while to figure out, but it seems like when you are done with display_menu() your calling ready_or_not() so you need to remove display_menu() from ready or not like this
# ready or not function to see if the user is ready to play
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
# self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
EDIT
looks like im late to the party

Create a text menu in Python3x that is always available

I am new to python and learning quickly. Thank you all for the help.
I am attempting to create a text menu that will always run in the background of a storytelling text rpg. I have searched and cannot find an explanation of how to create an "always on" menu or how one would work.
I would like the player to be able to hit "m" at any time in the game and have the menu prompt show up.
So far, I have created a "userinput" function as well as a "menu" function that will be deployed each time the game prompts the user/player for input.
def menu():
print('Press "1" for map >>> "2" for stats >>> "3" for exit')
choice = input()
if choice == '1':
print('map needs to be made and shown')
elif choice == '2':
print('stats need to be made and assinged to choice 2 in def menu')
elif choice == '3':
print('You are exiting the menu. Press "M" at any time to return to the menu')
return
else:
print('I did not recognize your command')
menu()
def userinput():
print('Press 1 to attack an enemy >>> 2 to search a room >>> 3 to exit game')
print('Press "M" for menu at any time')
inputvalue = input()
if inputvalue == 'm':
menu()
elif inputvalue == '1':
print('attack function here')
elif inputvalue == '2':
print('search function here')
elif inputvalue == '3':
exit
else:
userinput()
This does not appear to be an ideal solution because the user cannot choose to view a map or exit the game at any time they want.
Is there a way to have a menu always running in the background?
I thought of using a while loop that would never close and all of the game would be held within that while loop but that doesn't seem economical by any means.
Any thoughts or help would be appreciated.
I took a stab at it. This is perhaps not the best structure for doing what you're looking for but I don't want my reply to get too complicated.
The "standard" approach for anything with a UI is to separate the model, the view and the control. Check out MVC architecture online. While it adds complexity at the start it makes life much simpler in the long run for anything with a non trivial UI.
Other points of note are:
you're not stripping whitespace from your input (potentially problematic "3 " won't do what you want)
you're input is case sensitive (you ask for "M" but check for "m") .. maybe use choice = choice.strip.lower()??
there's a difference between the way raw_input and input work between Python 2 and Python 3 which means your code doesn't work in python 2. What's the difference between raw_input() and input() in python3.x? I've changed my example to use raw_input. You may want to use this work around http://code.activestate.com/recipes/577836-raw_input-for-all-versions-of-python/ near the top of your code for portability.
Some code
# flag we set when we're done
finished = False
def finish():
# ask the user for confirmation?
global finished
finished = True
return
def handle_menu_input(choice):
handled = True
if choice == '1':
print('map needs to be made and shown')
elif choice == '2':
print('stats need to be made and assinged to choice 2 in def menu')
else:
handled = False
return handled
def menu():
finished_menu = False
while not finished_menu:
print('Press "1" for map >>> "2" for stats >>> "3" for exit')
choice = raw_input() # NOTE: changes behaviour in Python 3!
if handle_menu_input(choice):
# done
pass
elif choice == '3':
print('You are exiting the menu. Press "M" at any time to return to the menu')
finished_menu = True
else:
print('I did not recognize your command')
menu()
return
def userinput():
print('Press 1 to attack an enemy >>> 2 to search a room >>> 3 to exit game')
print('Press "M" for menu at any time')
choice = raw_input() # NOTE: changes behaviour in Python 3!
if choice == 'm':
menu()
elif choice == '1':
print('attack function here')
elif choice == '2':
print('search function here')
elif choice == '3':
finish()
# elif handle_menu_input(choice):
# # delegate menu functions?? ..
# # do this if you want to see maps anytime without going through the menu?
# # otherwise comment this elif block out.
# # (Problem is 1, 2 etc are overloaded)
# pass
else:
print('I did not recognize your command')
return
def main():
# main loop
while not finished:
userinput()
return
if __name__ == "__main__":
main()

python -- Crash when trying to deal with unexpected input

So, I'm just fooling around in python, and I have a little error. The script is supposed to ask for either a 1,2 or 3. My issue is that when the user puts in something other than 1,2 or 3, I get a crash. Like, if the user puts in 4, or ROTFLOLMFAO, it crashes.
EDIT: okay, switched it to int(input()). Still having issues
Here is the code
#IMPORTS
import time
#VARIABLES
current = 1
running = True
string = ""
next = 0
#FUNCTIONS
#MAIN GAME
print("THIS IS A GAME BY LIAM WALTERS. THE NAME OF THIS GAME IS BROTHER")
#while running == True:
if current == 1:
next = 0
time.sleep(0.5)
print("You wake up.")
time.sleep(0.5)
print("")
print("1) Go back to sleep")
print("2) Get out of bed")
print("3) Smash alarm clock")
while next == 0:
next = int(input())
if next == 1:
current = 2
elif next == 2:
current = 3
elif next == 3:
current = 4
else:
print("invalid input")
next = 0
Use raw_input() not input() the latter eval's the input as code.
Also maybe just build a ask function
def ask(question, choices):
print(question)
for k, v in choices.items():
print(str(k)+') '+str(v))
a = None
while a not in choices:
a = raw_input("Choose: ")
return a
untested though
since the input() gives you string value and next is an integer it may be the case that crash happened for you because of that conflict. Try next=int(input()) , i hope it will work for you :)

Categories

Resources