HIGH LEVEL APPROACH
My approach is to first, parse the command line argument and then set up the connection socket depending on the variables passed in. I will have a method that takes in the parameters from the command line and sets up a socket as a global variable in the client file. From there, I will initialize the game by sending the hello message, and storing the ID in a Game object. I will store the connection and will make a method that listens to the response from the server. I'll have a couple conditions for each of the possible responses and deploy logic for each of them. If I know the game is started, I will use my game object to make guesses based on previous game data (which will be stored with the game class under the game ID) and I will then send those guesses back to the server and repeat until I get the 'bye' message. Once I get the 'bye' message, I will close the connection, print the flag, and delete the game instance. If I get an error, I will close the socket and print the error message.
CHALLENGES
The main challenge I believed I faced with this project was learning python as a Java programmer. I built out the high level structure of my code in java before realizing there was no JSON parser in Java 11 that I could use without a dependency. I spoke to my friend Donovan about what languages he thought were best for this class (he took 3700 a while back) and he recommended Python. I have used some python in projects before, however I have never coded entire projects exclusively in Python.
It was also a little challenging figuring out how the sockets/connections worked, but most of my time in this project was spent learning python syntax.
There was a slight issue with receiving the responses from the server as I was getting the error: Failed to decode JSON response: Unterminated string starting at: line 1 column 7 (char 6) However I fixed it by implementing a method to recieve all of the data from the server before moving on. Before, I was just using .recv(4096) and then moving onto decoding, but with the method, I go through the response looking for the json data so I don't have to hope it's quick enough rather I can be sure it's all there to decode.
GUESSING
My strategy for my wordle solver included taking the result array along with the previous word, and mutating the list of all possible words via filtering. I created a game class that allowed me to store the game id as well as a list of all the possible words it could be. Of course, upon initialization of the game, all words are in consideration so I initialized an internal list within my constructor for the class along with the game id. The guess method would filter the internal list based on the return array of the previous guess:
0 Letter does not appear in the secret word
1 Letter appears in the secret word, but not in this position
2 Letter appears in the secret word in this position
For 2, I just simply filtered out all the words that didn't include the letter at that specific index. For 1, I filtered out all the words that DID have that letter at the specific index, plus the ones that didn't include the letter at all.
My original guessing method had a bug where it incorrectly filted out words containing a letter. This is because when I encountered a 0 in the result array, it filtered out all words containing that letter without considering whether it may appear in another position in the word.
def guess(self, word, result):
if (len(self.words_list) == 15918):
return "crane"
if (len(word) != 5 | len(result) != 5):
print('Guess must be 5 characters.')
raise Exception
index = 0
for value in result:
letter = word[index]
if value == 0: # Here is where the error was occuring.
self.words_list = [w for w in self.words_list if letter not in w]
elif value == 1:
self.words_list = [w for w in self.words_list if letter in w and w[index] != letter]
elif value == 2:
self.words_list = [w for w in self.words_list if w[index] == letter]
else:
print('Unexpected value in response string.')
raise Exception
index += 1
return self.words_list[0]What I ended up doing was just simplifying the check for when the value is equal to zero so that it only filters if two separate conditions are met. a/ value = 0, b/ the letter at the index has to appear in the word exactly once. This isn't as efficient as I could possibly make it, but it is a working strategy.
I tested my game strategy by making a very simple mock wordle server so I can set the secret words to whatever I want and see if my logic works out in all of the edge cases (double letter both correct, double letter none correct, double letter one correct, etc). You can run the tests yourself by opening a terminal, navigating to this directory and typing python gametest.py