One of my current projects is the Daily Programmer challenge here. It’s a project to write a program to play a version of a hacking minigame from the Fallout series. Here, I’ll work through my design process for a Python 3.4 implementation.
I started by just throwing out a little bit of code. I didn’t expect this to get me anywhere, at least nowhere good. But sometimes, just typing a few things out can help you realize what a project requires that purely thinking through it doesn’t.
I quickly realized I needed a data structure of some sort to hold the list of potential words. A simple list of words would work, but depending on my source wordlist, I might end up with many words longer and shorter than the 4-15 letters the game design specifies. I’d also have to look through the entire list to retrieve the small handful of words that are part of a run of the game. Simply using a list would mean I’d have to account for these issues in many places in the game code, and that’s a problem.
I could use a list, and then have functions I call to work with the list. But then I’d have to worry about global variables and/or passing a list all over the place. That can be quite a mess. Not as bad as repeating my data access code, but still a mess. So I decided to implement it as a class, to package the data and its access code together.
I decided first it needed a way to give the user a list of words of appropriate length. From here, I tried to think of an appropriate internal representation, and the easiest seemed to be a list of lists, indexed by word length. With that, I can use random.sample() to easily get an appropriate length list.
I can also use a function to fill the internal data structure that rejects words with lengths outside the specified limits. There’s no sense having words with length of 16 in the data structure when I never need words that long.
The complete class is as follows:
class HackingGameWordList:
def __init__(self, wordlist):
""" Wordlist is a list of strings, constants determine
what length words I want to pull from the list
"""
self._MIN_LENGTH = 4
self._MAX_LENGTH = 15
self.words = [[] for _ in range(self._MAX_LENGTH)]
self.fill_list(wordlist)
def fill_list(self, wordlist):
""" Breaks up the full wordlist into the internal list of lists
indexed by word length
"""
for word in wordlist:
l = len(word)
if l >= self._MIN_LENGTH and l <= self._MAX_LENGTH:
self.words[l].append(word)
def get_n_words(self, n, l):
""" Return a list of n randomly selected words of length l """
return random.sample(self.words[l], n)