Thursday, February 25, 2010

Now I have finished up the encryption chapter of this book. The entire idea behind the encryption is to shift each character of a string over by a certain amount. Whenever a character of a string exited the parameters of a-z or A-Z, you just add or subtract 26, thus "wrapping" your encryption around and back, so that letters are only encrypted into letters. This took me about 30 minutes total to create. Here is my source code:

The next chapter of this book is here. This chapter goes over the Reversi game. I won't be constructing a program from this chapter as it doesn't really introduce any new concepts. The Ai for the reversi game just runs through each possible move and chooses the one that results in the most points. I will be skipping over chapter 14, and chapter 15, and heading straight into chapter 16. Chapter 16 is going over graphics and animation; I'll be starting to use the Pygame engine.

Wednesday, February 24, 2010

I have finished up creating a game that functions almost the same as the game in this chapter. The game I created is slightly different in how the code works in a few specific areas, but altogether the example code in this chapter, and mine, should be fairly similar. Here is my source code:

if smalld == 0: chests.remove([x, y]) return 'You have found a treasure chest!' else: if smalld < 10: board[x][y] = str(smalld) return 'Treasure has been detected at a distance of %s' % (smalld) else: board[x][y] = '0' return 'Treasure is nowhere to be found within range.'

if sonarDevices == 16: sonarDevices -= 1 if result == False: continue else: if result == 'You have found a treasure chest!': for x, y in previousMoves: makeMove(theBoard, secretChests, x, y) drawBoard(theBoard) print(result) if len(secretChests) == 0: print('You have found all the sunken treasure chests! Congratulations and good game!') break

if sonarDevices == 0: print('We\'ve run out of sonar devices! Now we have to turn the ship around and head') print('for home with treasure chests still out there! Game over.') print(' The remaining chests were here:') for x, y in theChests: print(' %s, %s' % (x, y))

if not playAgain(): sys.exit()

A large difference between my code, and the example code, is the fact that I have support for allowing the player to suffer no negative penalty (a loss of one of the sonar beacons) for trying to place a sonar over an area that was placed during the previous turn. This honestly, took me forever to figure out how to do. I finally decided on creating two copies of all previous turns, and then use these two copies to see if the last values in the two lists equal one another, before the value in the second list had been appended. This way, I compared the value of entered coordinates to the value of previous coordinates, and didn't subtract from the overall sonar amount when this happened.

The math is simple, and the whole Cartesian Plane didn't really teach me anything new. Although, if you don't understand how the math in my makeMove() function doesn't work, you might need to read over this chapter again.

I plan to go other the thirteenth chapter, here, for my next post. This seems rather interesting, as it is about cryptology.

Let me know if you see something I could improve upon in this code. Hopefully my lack of commenting the code isn't detrimental, if it is let me know and I'll add in comments.

Tuesday, February 23, 2010

The name of the game I have created for this post, is the game Bagels. Bagels is a game where the user guesses a three digit number, and the computer responds with "Fermi" for every digit that is in the right place that you guessed, and "Pico" for every digit that you guessed which is in the wrong place, but is still a digit in the secret number.

A nested loop is simply a loop within a loop. This is useful for when you want to iterate something x times, for every time y appears, or something similar.

Hardcoding is a coding practice where the coder codes the program so that changing of simple variables requires changing lots of code. This program was programmed without hardcoding, where a couple constants (variables that do not change while the program is running, which are represented with caps, although, are actually just normal variables in Python) can be changed to change how the game is played.

import random

def getSecretNumbers(numDigits):

numbers = list(range(10)) random.shuffle(numbers)

secretNum = '' for i in range(numDigits): secretNum += str(numbers[i])

return secretNum

def getClues(guess, secretNum):

if guess == secretNum: return 'You have guessed the correct number!'

clue = []

for i in range(len(guess)): if guess[i] == secretNum[i]: clue.append('Fermi') elif guess[i] in secretNum: clue.append('Pico')

if len(clue) == 0: return 'Bagels'

clue.sort()

return ' '.join(clue)

def isOnlyDigits(num):

if num == '': return False

for i in num: if i not in '1 2 3 4 5 6 7 8 9'.split(): return False

return True

def playAgain():

print('Do you want to play again? Yes or no.') return raw_input().lower().startswith('y')

NUMDIGITS = 3MAXGUESS = 10

print('I am thinking of a %s-digit number. Try to guess what it is.' % (NUMDIGITS))print('Here are some clues:')print('When I say: That means:')print(' Pico One digit is correct but in the wrong position.')print(' Fermi One digit is correct and in the right position.')print(' Bagels No digit is correct.')

while True: secretNum = getSecretNumbers(NUMDIGITS) print('I have thought up a number. You have %s guesses to get it.' % (MAXGUESS))

if guess == secretNum: break if numGuesses > MAXGUESS: print('You ran out of guesses. The answer was %s.' % (secretNum))

if not playAgain(): break

My code should be pretty much identicle to the code in the example program, as there aren't really any easier ways to code this program; this is a really rather cut and draw program to create.

This part of the program confused me for a moment:

def getSecretNumbers(numDigits):

numbers = list(range(10))
random.shuffle(numbers)

These lines create a list of numbers and then shuffle them. When I first saw these lines, the first one confused me: numbers = list(range(10)). I wasn't sure why the auther was changing the range() to list() inside of the range. Although, in the book it explained that if I wanted to store a list of integers, they needed to be converted from an iterator (value of range) into a list. This made sense, although the author didn't go into detail about exactly what the value of a range was. I assume it's just an amount of iterations to perform, which isn't what I would want if I wanted a list to store variables in.

I plan to run through chapter eleven of this book for my next post. This should be a relatively easy chapter, as it just goes through the basics of a Cartesian coordinate system.

Monday, February 22, 2010

Aha! So I coded up my own version of Tic Tac Toe. I did take a look at my old program that I posted up before (here) in a couple spots where I couldn't pinpoint my own bugs, but other than that I wrote this thing without a reference. This, pretty much just solidified my understanding and familiarity of Python syntax even further. Not much else to explain. Here is my source code:

I had a few troubles throughout the program, and the most annoying one was in the definitions of winning. I had constantly placed a 1 in place of a lower case L, and this resulted in bad things. I also had a couple typos here and there, things like typing = instead of ==, and vise versa.

One thing in particular that I found interesting while creating this program, was the "None" value. Here is a quote from the book "Calls to functions that do not return anything (that is, they exit by
reaching the end of the function and not from a return statement) will
evaluate to None." This was useful in that whenever I wanted the Ai in my simulation to choose a random location to place his letter, say, one of the four corners; if all four of these corners were taken, I could return the value of None instead of one of the values for one of the four corners.

I also learned from this chapter some interesting aspects of list referencing. Take a look at this function:

def makeMove(board, letter, move):
board[move] = letterIt would seem like this function wouldn't do anything due to the change of the board list being of the private scope by default, since it is happening within the function itself. This is because the word "board" isn't actually the list board, it is just a reference to that list passed onto the function as an argument. This means that when we have the line board[move] = letter we aren't modifying the data stored in a variable, but we are modifying the data stored in the list, which is referenced by the word "board". Here is a quote from the book that explains this: "When you assign a list to a variable with the = sign, you are actually assigning a reference to the list. A reference is a value that points to some bit of data, and a list reference is a value that points to a list."

Well, sadly, I have no more time for C++, and I probably won't for a couple months. Things are getting really busy. Although, I have good news; I started a programming club at my highschool that meets once a week, where I teach them all how to code in Python. For the time being, my next posts will be about my learnings of Python.

I chose Python after doing a little bit of research; Python is a language that was created to allow coders to create code quickly and efficiently. Readability of Python was also a concern while developing the Python environment. As such, Python is great for readability and for quickly coding programs. Although Python is great at what it was intended to be used for, Python isn't made to create highly optimized code for intense programming (things like 3D rendering). Although, you can create visual programs that render in 3D, Python code can only be optimized so much.

I spent this weekend reading some of the chapters from this excellent book on programming games in Python, with the Pygame engine. Here is the book I am currently reading: http://inventwithpython.com/chapters/.I am currently on nine.

I am working with Python 2.6, as this has the most up-to-date third party support from things like Pygame and Py2Exe.

I recommend that anyone reading this check out the Pygame.org website, and sift around through the tutorials there, as well as check out the source code for some of the more simple programs that are on display there.

Over the course of chapter nine, I created a game of TicTacToe. The player can choose to play as X's or O's, and I have a functioning Ai.

At this point in time, I do have a working program, although, I created it while using the example code in the book as reference. As an exercise, my next post will be about me trying to create the entire program without reference code whatsoever.

Here is my source code for my program:

import random

def drawBoard(board):#This function draws the board whenever it is called. The board is represented as an array.

def isSpaceFree(board, move):#Return true if the move is available on the board.

return board[move] == ' '

def makeMove(board, letter, move): board[move] = letter

def isWinner(bo, le):# Given a board and a player's letter, this function returns True if that player has won. # We use bo instead of board and le instead of letter so we don't have to type as much.

return ((b[7] == l and b[8] == l and b[9] == l) or # across the top (b[4] == l and b[5] == l and b[6] == l) or # across the middle (b[1] == l and b[2] == l and b[3] == l) or # across the bottom (b[7] == l and b[4] == l and b[1] == l) or # down the left side (b[8] == l and b[5] == l and b[2] == l) or # down the middle (b[9] == l and b[6] == l and b[3] == l) or # down the right side (b[7] == l and b[5] == l and b[3] == l) or # diagonal (b[9] == l and b[5] == l and b[1] == l)) # diagonal

def isBoardFull(board):#Checks to see if the board is full or not.

for i in range(1, 10): if isSpaceFree(board, i): return False

return True

def getComputerMove(board, computerLetter):#Determines how to react depending on which letter (X or O) the computer player has.

if computerLetter == 'X': playerLetter = 'O' else: playerLetter = 'X'

# Check if the computer can win in the next move. for i in range(1, 10): copy = getBoardCopy(board) if isSpaceFree(copy, i): makeMove(copy, computerLetter, i) if isWinner(copy, computerLetter): return i

# Check if the player could win on his next move, and block them. for i in range(1, 10): copy = getBoardCopy(board) if isSpaceFree(copy, i): makeMove(copy, playerLetter, i) if isWinner(copy, playerLetter): return i

# Try to take one of the corners, if they are free. move = chooseRandomMoveFromList(board, [1, 3, 7, 9]) if move != None: return move

# Try to take the center, if it is free. if isSpaceFree(board, 5): return 5

# Move on one of the sides. return chooseRandomMoveFromList(board, [2, 4, 6, 8])

def chooseRandomMoveFromList(board, movesList):# Returns a valid move from the passed list on the passed board. # Returns None if there is no valid move.

possibleMoves = [] for i in movesList: if isSpaceFree(board, i): possibleMoves.append(i)

As you might notice, this code is pretty darn similar to my reference code. As I mentioned, I will as my next project re-write this entire program without any reference.

I would say that the most interesting part of creating this program, was the Ai. The Ai really only cycles through a copy of the currently existing board, and searches for any winning moves from either player. If it finds one, it takes it. If not, it moves to one of the currently open corners, randomly. If all the corners are taken, the Ai moves into the middle space. If that is taken, it moves onto one of the four last spaces, at random. This algorithm is pretty darn simple, but it is effective at playing Tic Tac Toe.

Overall, I would say I gained a better understanding of Python syntax more than anything while writing this program.I tried to include a source file, and my exe, although I'm currently having troubles uploading. I'll try to remember to modify this post with some links, in case anyone wanted to download the exe or the source. Edit: No, I will not be supplying the exe//source code this time ;P