I am currently doing my CS50 final project problem and have encountered quite a problem. Below is my code and the error message that appears whenever I give it in. Any help as to how to fix an issue that I'm not sure why is there would be great help. My code works as expected, and runs well. However CS50 just isnt working whenever I try. (Please ignore the README errors as that is just a length problem)
My main problem is that it isnt detecting the 3 functions and the main function and the the whole py thing.
from termcolor import colored
import random
def main():
run_game()
#I have the next couple of functions all put into effect in the run_game function. Therefore only need to do run game.
#This function takes a word to print, and an array containing the colours each letter should be printed input
#The first character in the word will be printed in the first colour in the array and so forth
def present_results(word, colours):
if(len(word)==5 and len(colours) == 5):
print(colored(word[0],colours[0]),
colored(word[1],colours[1]),
colored(word[2],colours[2]),
colored(word[3],colours[3]),
colored(word[4],colours[4]))
else:
print('Invalid input to present_results, word or array incorrect length, both should be length 5')
print('[DEBUG] word length:',len(word),'colour array length:',len(colours))
#The following are tests for the present_results and randint functions
word = "PRINT"
colors = ['green','white','yellow','white','yellow']
#present_results(word, colors)
def generate_word ():
words=['thorn','thick','light','might','cabin','paste','vocal','abode','right','urban','ghost',' zebra',
'grail','tower','brave','crave','chase','image','night','print', 'shame','table','fable','diary','train', 'prick', 'stick', 'slice', 'solid',
'space', 'other', 'about' , 'which', 'witch', 'faith', 'clown', 'scowel', 'towel', 'shelf' , 'stone', 'earth', 'extra', 'adieu', 'entry',
'evict', 'clone', 'shady', 'stock', 'corks', 'actor']
#List of 50 words to pick from
index=random.randint(0,49)
return words[index]
#A lot of words thats returned to be the word that is guessed. its a list and using the random generator it is picked randomly and returned
def letter_in_word (string,letter):
if letter in string:
return True
else:
return False
#Straightforward, whether the letter is present in the word of not it returns true/false
def letter_in_place (string,letter,index):
if string[index]==letter:
return True
else:
return False
#similiar to the top one, if it is in the correct or incorrect spot, it returns true/false
def guess_word (answer,guess):
colors=[]
for i in range(len(answer)):
temp=letter_in_place(answer,guess[i],i)
if temp==True:
colors.append('green')
elif temp==False:
temp=letter_in_word(answer,guess[i])
if temp==True:
colors.append('yellow')
elif temp==False:
colors.append('white')
return guess,answer,colors
#Basically colour cordinated function where in a loop if it follows the placement it is green, the letter is present it is yellow, and if none just white. Using the "in place" function and "letter in word" one too.
def run_game():
answer=generate_word()
for i in range(0,6):
guess=input("Enter a guess: ")
if guess==answer:
print("Great Job,",answer, "is the right word!" )
return
guess,answer,colors=guess_word(answer,guess)
present_results(guess,colors)
print("All 6 Attempts Were Used, Try Again!")
#uses all the above functions and puts it all in one to simplify for the main function.
if __name__ == "__main__":
main()
The code runs well and as expected, however the error that pops up is this:
:) README.md exists
Log checking that README.md exists...
:( final project details
Cause
Description is not long enough.
:| project.py exists
Cause
can't check until a frown turns upside down
:| main function exists
Cause
can't check until a frown turns upside down
:| implemented at least 3 top-level functions other than main
Cause
can't check until a frown turns upside down
EDIT:
Below is a copy paste of my README.MD file its roughly 450 words and is quite long and detailed. I am unsure of the problem. Thank you!
#### Video Demo: <https://youtu.be/jVo5LkGE3Mk>
#### Description:
My name is Karim Osman and I wrote for my final project in CS50s intro to python course a game.
TERMLE is a heavily inspired game from the 2020-2021 hit web browser game called WORDLE. It gained such popularity where it was bought by the New York Times.
It follows a basic concept of the user has six attempts to guess the correct word. The user recieves color-coded hints with each guess indicating a letters presence and position. Green for the letter that is in the correct position and present in the letter. Yellow for incorrect position and present letter. Finally grey for letter is not present in the word.
Following these basic guidelines of WORDLE, I made a similiar game called TERMLE. It uses the same colors and the same concepts with a few minor adjustments. One major difference in that the words present are randomly picked from a list of fifty words within the generate_word function using the random library. From these words there are none that have a duplicate letter, I.E: Eagle - Looks. In addition, the user can play as much as they desire, unlike WORDLE where the user is restricted to one session per day, whether correct or incorrect.
I breifly mentioned the beggining of function above. The generate_word function takes from a list of fifty words, all five letters, and uses the imported random task to return a selected string outside of the function. After so, we have two quite similiar and simple functions called letter_in_place and letter_in_word. The word one sees if the character is present in the returned string, and claims it either as True or False. The place one follows a similiar concept. If the letter is present in the word at a specific placement I.E: "i" is present in brick[2], it will return True, otherwise False.
Using the two above functions we create the next and more important function guess_word. This begins to take into account the placement and present characters in the returned word of the game. Alongside so, it begins color responding to the users input. With the append function, starting with green if the letter and placement is correct it will become true, otherwise it will move to yellow where only the letter is correct, then finally it will go grey where neither the placement or the letter is correct.
Finally, condensing all the above functions into use in the run_game function. This is where the user is prompted an input and the sole call in the main function due to how pratical it is. Prints according to whether the user wins or loses, and uses the presents_results function to properly display the answers.
I am unsure if the formatting is wrong or if I should create it on github and not the project folder. I am very lost here.
I'm pretty sure that the 2nd line (Cause Description is not long enough.) has nothing to do with your code and means 1 of 2 things:
Your README.MD isn't long enough, or
You didn't you follow the instructions about using Markdown syntax under How to Submit .
For reference, my project README word count was 467 and line count was 51. Also, here is the Markdown syntax you need use to to mark your Description.
# YOUR PROJECT TITLE
#### Video Demo: <URL HERE>
#### Description:
TODO
Related
I'm currently doing a dice game for my school programming project, and it includes the rules: 'Stores the winner’s score, and their name, in an external file' and 'Displays the score and player name of the top 5 winning scores from the external file.' I've done everything in my game apart from the leaderboard. I am able to write the name and score of the user into the txt file, but I am unsure of how to then sort it, and would also like when people first start the program can use the menu to go to the leaderboard where it would then read the txt file and print the top 5 scores in order including the names.
I've checked loads of over questions similar to mine, but none of them exactly worked for my code as I kept on getting errors implementing other people's code into mine which just weren't compatible with my layout.
(deleted)
Thanks in advance, I've never used stack overflow to ask a question so I apologize if there's anything I've done wrong in my post.
You did good on the question. You stated the problem clearly and, most importantly, you added enough code to run the code so we can have a look at how the program behaves and what's going wrong. In this case nothing is going wrong which is good :)
Considering you mention that this is a school project I will not give you a fully copy/paste solution but will explain hopefully enough details on how to solve this on your own.
Now according to the question, you don't know how to sort your leaderboard. I ran the program a few times myself (after removing the sleeps because I am impatient 😋) and see that your leaderboard file looks like this:
90 - somename
38 - anothername
48 - yetanothername
To display this you must do two things:
Open the file and read the data
Convert the data from the file into something usable by the program
The first step seems to be something you already know as you already use open() to write into the file. Reading is very similar.
The next step is not so obvious if you are new to programming. The file is read as text-data, and you need to sort it by numbers. For a computer the text "10" is not the same a the number 10 (note the quotes). You can try this by opening a Python shell:
>>> 10 == 10
True
>>> 10 == "10"
False
>>> "10" == 10
False
And text sorts differently to numbers. So you one piece of the solution is to convert the text into numbers.
You will also get the data as lines (either using readlines() or splitlines() depending on how you use it. These line need to be split into score and name. The pattern in the file is this:
<score> - <name>
It is important to notice that you have the text " - " as separator between the two (including spaces). Have a look at the Python functions str.split() and str.partition(). These functions can be applied to any text value:
>>> "hello.world".split(".")
['hello', 'world']
>>> "hello.world".partition(".")
('hello', '.', 'world')
You can use this to "cut" the line into multiple pieces.
After doing that you have to remember the previous point about converting text to numbers.
As a last step you will need to sort the values.
When reading from the file, you can load the converted data into a Python list, which can then be sorted.
A convenient solution is to create a list where each element of that list is a tuple with the fields (score, name). Like that you can directly sort the list without any arcane tricks.
And finally, after sorting it, you can print it to the screen.
In summary
Open the file
Read the data from the file as "lines"
Create a new, empty list.
Loop over each line and...
... split the line into multiple parts to get at the score and name separately
... convert the score into a number
... append the two values to the new list from point 3
Sort the list from point 3
Print out the list.
Some general thoughts
You can improve and simplify the code by using more functions
You already show that you know how to use functions. But look at the comments #THIS IS ROUND1 to #THIS IS ROUND5. The lines of code for each round are the same. By moving those lines into a function you will save a lot of code. And that has two benefits: You will only need to make a code-change (improvement or fix) in one place. And secondly, you guarantee that all blocks behave the same.
To do this, you need to think about what variables that block needs (those will be the new function arguments) and what the result will be (that will be the function return value).
A simple example with duplication:
print("round 1")
outcomes = []
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
outcomes.append("A")
else:
outcomes.append("B")
print("round 2")
outcome = ""
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
outcomes.append("A")
else:
outcomes.append("B")
Rewritten with functions
def run_round(round_name):
print(round_name)
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
return "A"
else:
return "B"
outcomes = []
result_1 = run_round("round 1")
outcomes.append(result_1)
result_2 = run_round("round 2")
outcomes.append(result_2)
As you can see, the second code is much shorter and has no more duplication. Your code will have more function arguments. It is generally a challenge in programming to organise your code in such a way that functions have few arguments and no complex return values. Although, as long as it works nobody will look too closely ;)
Safe way to ask for a password
You can use getpass() from the module getpass() to prompt for a password in a secure manner:
from getpass import getpass
password = getpass()
Note however, if you are using PyCharm, this causes some issues which are out of scope of this post. In that case, stick with input().
Sleeps
The "sleep()" calls are nice and give you the chance to follow the program, but make it slow to test the program. Consider to use smaller values (comma-values are possible), or, even better, write your own function that you can "short-circuit" for testing. Something like this:
import time
ENABLE_SLEEP = True
def sleep(s):
if ENABLE_SLEEP:
time.sleep(s)
print("some code")
sleep(1)
print("more code")
sleep(4)
You will then use your own sleep() function anytime you want to wait. That way, you can simply set the variable ENABLE_SLEEP to False and your code will run fast (for testing).
This is the code I have so far, my teacher wants the game to "flip the X's over" when you guess a number and when they match the numbers stay but when the numbers are different the numbers "flip back over" and become X's again. And he wants the game to say that "you win" when all the numbers have been exposed.
import random
visual=[['X','X','X','X','X'],['X','X','X','X','X'],['X','X','X','X','X'],['X','X','X','X','X'],['X','X','X','X','X']]
data=[[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5]]
random.shuffle(data[0])
random.shuffle(data[1])
random.shuffle(data[2])
random.shuffle(data[3])
random.shuffle(data[4])
while True:
print(visual[0])
print(visual[1])
print(visual[2])
print(visual[3])
print(visual[4])
user_input_1 = int(input('enter a number 0 thru 4 to pick your first X position: '))
user_input_2 = int(input('enter a number 0 thru 4 to pick your first Y position: '))
user_input_3 = int(input('enter a number 0 thru 4 to pick your second X position: '))
user_input_4 = int(input('enter a number 0 thru 4 to pick your second Y position: '))
if data[user_input_1][user_input_2] == data[user_input_3][user_input_4]:
visual[user_input_1][user_input_2] = str(data[user_input_1][user_input_2])
visual[user_input_3][user_input_4] = str(data[user_input_3][user_input_4])
print(visual[0])
print(visual[1])
print(visual[2])
print(visual[3])
print(visual[4])
print('Congratulations you won the game!')
break
Here are the discrete steps in the game as I understand it:
Initialize the board and data.
Shuffle the data
Enter Loop
Print the board
Ask user for their first guess
Ask user for their second guess
Print the board with reveals
Cover them back up if user missed
Check win condition (everything revealed?)
Loop back or print win
Your code successfully initializes the board (step 1), shuffles the data (2), enter loop (3), prints board (4), and asks for the guesses (5)(6).
Here is some guidance on the pieces you are missing:
After you get the inputs, you always want to print the board with the reveals (7). To do this you need to update visuals first with the piece you have written:
visual[user_input_1][user_input_2] = str(data[user_input_1][user_input_2])
visual[user_input_3][user_input_4] = str(data[user_input_3][user_input_4])
and then print your visuals. This does not need to happen with an if statement, because you always want to do a print of the revealed board.
Afterwards, you want to do the swap back to X's if the user misses (8). You have this condition already basically written. You need to check if it's a miss in the data board and swap those visuals back to X's if true:
if data[user_input_1][user_input_2] != data[user_input_3][user_input_4]:
visual[user_input_1][user_input_2] = 'X'
visual[user_input_3][user_input_4] = 'X'
Side Note: Ideally, you want to clear the previous board print of the reveals to test memory. This part is kind of tricky. There are no simple ways to clear the print of the reveals without using operating system commands which are almost certainly beyond the scope of your class. I would check with your teacher about expectations around flipping back over.
If you are interested in how this is achievable using operating system command in Python here is a relevant StackOverflow post. You would need to import os and import time. After you print reveal, use time.sleep(number_of_seconds) to give the user however many seconds to try to memorize placements and then use os.system('clear') for linux/mac os or os.system('CLS') for windows to clear the screen. Again, it's very unlikely that this is what your teacher is looking for.
Now let's deal with the win condition (9). Currently you are using a "while True:" with a break. While this may be functional in this case, using "while True:" should be almost always avoided (there are many reasons why-- here is a post that addresses one reason). Loop structures like "while", "do-while", and "for" have built-in stopping conditions which will be checked each time you loop. In this program, your stopping condition is that the board is completely revealed (that is how you know the game is over and user no longer needs to guess). So, until this happens you want your while loop to keep going. This looks like this:
while #win condition is not met#:
#stuff you want to loop#
#congrats, you have met your win condition#
There are multiple ways to check your win condition is not yet met. One option is that you know you have not won yet if the visual board is still not the same as data board:
while visuals != data:
#stuff you want to loop#
print(congrats....)
In summary, TLDR:
import random
visuals = [...]
data = [...]
#shuffle
while visuals != data:
#print visuals
#get input
#update the inputted visuals with reveals
#print visuals with reveals
if #not a match:
#update the inputted visuals back to X's
print("Congratulations you won the game!")
There are a handful of smaller points that could improve your code as well if you're interested: be very vigilant about indents, a do-while loops is more appropriate here (can you think of why?), you can write functions and loops that reduce a lot of the repeating code (like when you print the visuals). But this should be enough for you to grapple with.
Some suggestions for your code:
Since you display the board so often, you may want to write a separate function that takes the variable visual as input and prints the content. Then you can just call the function instead of writing all of those print statements.
In your current code, you only display the cards when there's a match. One of the whole strategies for playing a memory game is that if you overturn two cards and see "5" and "2" for example, it's not a match, but if you overturn a new pair of cards and one of them is another "5", you might remember where that first "5" was you overturned in your previous turn and thus know how to make a match. So perhaps you should do this: update and display visual after selecting the first card, then do the same with the second card. If there's a match, then leave visual as is. If they don't match, then replace the two spots back with 'X' and go back to the top of the loop.
Your code seems to consider a single match a "win". Shouldn't it be considered won once all of the cards have been matched? In this case, you can follow up the previous step by checking to see if 'X' shows up anywhere in visual. If it doesn't, then that means all of the cards have been uncovered, thus the player has won.
enter image description here
Please excuse me that I'm posting my code as an image.
This is a simple guessing game expression.
When you look at the last line of the code,
there is 'tries += 1' code to count how many times it's looped.
So my question is,
the result is changing when I put 'tries += 1' right under
the code line 'guess = input("What is your lucky number?")'.
So what is the difference between
putting it at the last line of the code block and right under the start of while loop code.
Thanks for helping :)
Wouldn't it have been far easier to just copy in the text than to print-screen and crop the image? The number of tries is initialized to 1 which is misleading as at that point in the program there hasn't been any tries. Logically it makes more sense to initialize tries to 0 and place the increment immediately after the user input. But because the program hasn't been structured in this way, tries must be incremented after comparing the guess to the target; otherwise, in the case when the user's guess is correct, the output would show a number of tries one greater than the actual number of tries.
What you're misunderstanding is the order in which your code executes. There are three important events inside your loop:
You ask the user for their guess
You process their guess, and if they get it right you display the current value of the variable tries
You increment the variable tries, in the statement tries += 1
These execute in exactly that order. So, when the user guesses correctly, they're told the value of tries before it is incremented again. If you put the line tries += 1 right after the input statement, then that value is now being increased before it is printed. Thus, the displayed value is different.
This is one part of a two part question (other part is here)
So I'm working with wxPython and PyEnchant trying to get some fancy features going. Specifically, I want my text controls to change the color of mispelled words. I can do this if I bind the following code to a button. (where input is a wx.TextCtrl)
chkr = SpellChecker("en_US",self.input.GetValue())
words = self.input.GetValue().split()
wrongWords = [err.word for err in chkr]
self.input.ChangeValue("")
for word in words:
if not word in wrongWords:
self.input.SetDefaultStyle(wx.TextAttr(wx.BLACK))
self.input.AppendText(word+" ")
else:
self.input.SetDefaultStyle(wx.TextAttr(wx.RED))
self.input.AppendText(word+" ")
This works exactly how I want it, except that I do not want to have to bind it to a button.
This is where the second question comes in. I want it to happen automatically after the user has finished editing. You can see the other question for a full discussion of whhat that means, but in the scope of this question, all it means is that I must do the above operation without generating an EVT_TEXT event.
ChangeValue() is identical to SetValue(), but it does not generate EVT_TEXT, so is there an analogous function to AppendText() which does same? Or failing that, is there a way to suppress EVT_TEXT when it is generated by AppendText() or someway to determine if the event came from AppendText()? Thanks in advance.
EDIT: I've managed to get a work around going by using Unbind(), but I'm still open to a better method if anyone can find one
I develop plugin for sublme text 3. I need code for getting nearest to cursor word.
For example if I got cursor as on image...
... this plugin should return word run
....or at least number 10 which corresponds position of char u in line 4:
And then I will be able to get word run from number 10 and text of line 4.
But now I only can get linetext on which I got cursor:
import sublime, sublime_plugin
class line_nearest_to_cursor_wordCommand(sublime_plugin.WindowCommand):
def run(self):
print('line_nearest_to_cursor_word called')
view = self.window.active_view()
region1 = view.sel()[0]
line = view.line(region1)
linetext = view.substr(line)
print(linetext)
When I print region1 it gives two numbers, but they are wierd:
print (region1) # prints (113, 113), but 113 is not position of char "u" in line " def run(self):"
So problem reduced to writing method getXcoordPositionOnLine...
xCoord = getXcoordPositionOnLine(region1)
print xCoord
... which will give me x position of cursor on line.
Or maybe there is a better solution.
I answered a similar question for you yesterday. Looking at the docs, if you simply replace line in yesterday's answer with word, I believe you will get what you are looking for.
view = self.window.active_view()
word = view.word(view.sel()[0])
wordtext = view.substr(word)
As #skuroda suggests, this is easily answered by looking at the documentation. It isn't that difficult to understand.
Though I suppose the formatting leaves something to be desired, please try to take a look at the API documentation. A large number of your questions can likely be answered by exploring the docs. These are available here for ST3. With that being said, take a look at view#word(point) and view#word(region) in the documentation.
Here's what I think region1 being (113, 113) means, how you might be able to use it with the API to get what you want, or at least provide you with enough information to be able to write something like a getXcoordPositionOnLine() function yourself.
The API documentation says a sublime.Region has two properties, a and b, which represent the first and second ends of the region. I believe these are just two integer offsets from the beginning of the text buffer, and the reason they're the same in this case is because the region is empty (i.e. no characters are actually selected by it since they're the same value, which mean it's effectively the position of a cursor).
To illustrate that below is a screenshot of the code snippet shown in your question in another editor in which I've selected all the text from the beginning to the point between the "r" and the "u" in the word "run". This editor has an indicator near the bottom right that shows shows the total of Bytes/Lines currently selected. Notice that this is displaying 113/4 -- meaning that the "r" is 113th character in the text buffer and it's on the 4th line because there are 3 newline characters preceding it.
sublime.Regions also have an xpos property which sounds like it represents the offset of the character from the last newline (and would be something like 10 in this case I guess). Further reading of the documentation leads me to suspect you might be able to get the closest word to the cursor represented by region1 is the value returned from view.substr(view.word(region1).