Skip to content

Instantly share code, notes, and snippets.

@phirework
Last active December 15, 2015 09:29
Show Gist options
  • Select an option

  • Save phirework/5239284 to your computer and use it in GitHub Desktop.

Select an option

Save phirework/5239284 to your computer and use it in GitHub Desktop.
Here's a command-line game I wrote for my Hacker School app. (It's also my first independently-written Python script, hurray.)
from sys import exit
from collections import defaultdict
from random import randint
import time
# Create a list with 9 spaces in it
grid = []
for x in range(0, 9):
grid.append(' ')
# Define the win conditions for Tic-Tac-Toe
win_cond = [
[0,1,2], [3,4,5], [6,7,8],
[0,3,6], [1,4,7], [2,5,8],
[0,4,8], [2,4,6]]
# Print out a visual representation of the board
def board():
board = " %s | %s | %s \n----------- \n %s | %s | %s \n----------- \n %s | %s | %s"
print board % tuple(grid)
# Initializes the game
def start():
# Print the intro banner for the game
print start_msg
enter = raw_input("Press Enter to continue. ")
# Resets the grid
for x in range(0,9):
grid[x] = x+1
# Prints the current board
board()
# Generate either 0 or 1 randomly to decide which way the "coin" came down
if coin_toss() == randint(0,1):
print start_first
your_turn()
else:
print start_second
computer_turn()
## Create a function that simulates a coin toss to decide who goes first
def coin_toss():
print coin_toss_msg
starter = raw_input("> ")
if starter == heads:
return 1
elif starter == tails:
return 0
else:
print coin_error
coin_toss()
## Start the player's turn
def your_turn():
print your_turn_msg
turn()
## The actual player input part - separated from your_turn() to avoid reprinting instructions when it hits an error
def turn():
player_move = raw_input("> ")
try:
play = int(player_move)
# If the player entered something other than a number, prompt them again
except ValueError:
print value_error
turn()
# If the player entered a number out of range, prompt them again
if play > 9 or play < 1:
print range_error
turn()
# If the player is trying to play on a space that's already taken, prompt them again
elif isinstance(grid[play-1], int) == False:
print taken_error
turn()
# If everything is correct, set the grid to the player character O and check to see if there are any ties/wins
else:
grid[play-1] = "O"
check_win()
check_tie()
print "\n"
board()
computer_turn()
## Start the computer's turn
def computer_turn():
print computer_turn_msg
# Check if the center spot is taken. If not, take it.
if isinstance(grid[4],int):
grid[4] = "X"
# If it is taken, see if there are any rows that have two strings of the same kind in it
else:
almost()
computer_end()
your_turn()
## Check if there are any rows that have two strings of the same kind in it
def almost():
# For each set of win conditions in the win condition
for win in win_cond:
# Set a to the first position in the set
a = win[0]
# Set b to the second position in the set
b = win[1]
# Set c to the third position in the set
c = win[2]
# Create an list made up of entries a, b, and c
line = [grid[a], grid[b], grid[c]]
# See if there are duplicate entries in the list
# The number of unique entires will be different from the number of total entries
if len(line) != len(set(line)):
# If Yes, see if each position is empty, and take it if so.
# End the computer's turn and pass it onto the player after something has been played
if isinstance(grid[a],int):
grid[a] = "X"
computer_end()
your_turn()
elif isinstance(grid[b], int):
# if yes, take it
grid[b] = "X"
computer_end()
your_turn()
elif isinstance(grid[c],int):
grid[c] = "X"
computer_end()
your_turn()
# If there are no duplicate entries in this set of win conditions, it goes on to check the next one
# If there are no rows that have two strings of hte same kind in it, make a regular move
computer_move()
## These are the regular moves the computer can choose from if there are no imminent threats
## Or chances for winning
def computer_move():
# If the middle square is a computer-occupied square, use the random_move() algorithm
if grid[4] == "X":
random_move()
# If this is the first move the computer is making, and the middle square is taken
# Play one of the corner positions and end the turn after something has been played
elif not ('X' in grid):
outside = [0,2,6,8]
for pos in outside:
if isinstance(grid[pos], int):
grid[pos] = "X"
break
computer_end()
your_turn()
# If this is not the first move the computer is making, use the same_row() algorithm
else:
same_row()
# Once same_row() has been executed, end the computer's turn
computer_end()
your_turn()
## This picks the first available spot to play. It's undiscriminating because it only gets
## executed if the center square belongs to the computer, and it will form a line either way
def random_move():
for x in range(0,9):
if isinstance(grid[x], int):
grid[x] = "X"
computer_end()
your_turn()
## If there is already an X on the board, and the center square is not the computer
## place an X in another corner that lines up with the first one
def same_row():
# Find where the current X is
position = grid.index('X')
# Define the two corresponding corners for each corner
outer = [(0,2),(0,6),(2,0),(2,8),(6,0),(6,8),(8,2),(8,6)]
same_row = defaultdict(list)
for key, value in outer:
same_row[key].append(value)
for key in same_row:
# Find the two corresponding corners that match the current position of X
if position == key:
remainder = same_row[key]
# Place an X on the first available corresponding corner
for pos in remainder:
if isinstance(grid[pos],int):
grid[pos] = "X"
# Once same row has been executed, go back to computer_move() which will end the computer's turn
## This ends the computer's turn and shows the new board
def computer_end():
check_win()
check_tie()
print think_msg
time.sleep(.75)
board()
## Checks whether or not there is a winner after each turn
def check_win():
# Iterate the 3 positions of each set of win conditions
for win in win_cond:
a = win[0]
b = win[1]
c = win[2]
# Create a list of the current values of the 3 positions
line = [grid[a], grid[b], grid[c]]
# If the list is all 'X', then the computer has won
if line == ['X', 'X', 'X']:
board()
print you_lose
again()
# If the list is all 'O', then the player has won
elif line == ['O', 'O', 'O']:
board()
print you_win
again()
## Checks whether or not there is a tie after each turn
def check_tie():
# If each position in the grid is a string (X or O) and check_win didn't find a winner
# Then declare a tie and offer to play again
tie = all(isinstance(x, str) for x in grid)
if tie == True:
print we_draw
again()
## Resets the game at the end of the game
def again():
print play_again
again = raw_input("> ").lower()
if again == "y":
start()
else:
print thanks_msg
exit()
start_msg = """
#############################################################################
# #
# TIC: Tac T.O.E #
# #
# Telnet Intrusion/Compromise: Tactical training & Online Evaluation #
# #
#############################################################################
> Good, you're here. That means you've made it all the other obstacles we've
set you. This is your final test before you can move onto the big leagues.
We've created an advanced simulation of a real-world scenario in which you
are the only thing that stands between crafty Martian hackers and the
integrity of our network security. We'll need you to activate the final
defense system to ward them off.
Unfortunately, we were a little...overzealous in our interface design. You
can't just flip a switch. You'll need to activate three nodes in a linear
pattern to create a virtual firewall. And while you're racing to complete
this task, the hackers are worming into gaps in the protection.
Google ain't gonna help you here. Good luck. """
heads = "1"
tails = "0"
coin_toss_msg = """
> To test your nerves and dumb luck we're going to see if you can predict
the outcome of this randomly generated binary variable. Is it %s? Or %s? """ % (heads, tails)
coin_error = """
> That wasn't one of the options. You're not starting off too well here, I
gotta say. """
start_first = """
> Huh, you were right. Who would've thought. Don't waste your chance. """
start_second = """
> Good going, hero. The Martians get to make the first move. """
your_turn_msg = """
> Okay kid, time to shine. You know how it goes - enter a number from 1-9. """
value_error = """
> Uh, that's not a number. How did you even make it this far?
1-9, base 10. Don't try anything clever. """
range_error = "\n> Dude, do you even know how to count? 1-9."
taken_error = """
> Come on now, that switch is clearly taken. I'll overlook it this time. """
computer_turn_msg = """
> Now you get to wait as foreign intruders ruin your life's work. Not to be
hyperbolic or anything. """
think_msg = "\nStanding by...\n"
you_lose = """
> Welp, the intruders have managed to gain access to your system. Too bad,
kiddo. Looks like you're not quite ready for the big leagues. Better luck
next time. """
you_win = """
> Congratulations, you have successfully fended off the foreign intruders and
completed this evaluation. Please report to HS headquarters in New York City
for the next stage of your training. We hope to see you soon. """
we_draw = """
> It would seem that you have reached a stalement in this exercise. That's...
unusual. Are you always this much trouble? """
play_again = "\n> Do you think you can handle this challenge again? Y/N"
thanks_msg = "gg ttyl kthxbye"
start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment