Wednesday, 11 June 2014

Tic Tac Toe Solution Walkthrough

A couple of blog posts ago, I interviewed my friend Stuart about his new job as an app developer. As part of his interview, he was given a week to program a simple 2-player tic-tac-toe game using a programming language of his choice.  This seems to be a common homework problem for computer programming students and I thought it would be good practice to see if I could write my own version in Python. Here is an example of a tic-tac-toe programming assignment I found from a google search:

You are to implement the two player game of Tic Tac Toe. The program should display the board and prompt each user a move. The program should validate each move and handle any incorrect input. The entire user interaction should be command line based. Upon winning or a draw of the game, an appropriate message should be displayed acknowledging such condition.


Not a valid win.
Through the Computer Science 101 course I did with Udacity.com, there was a very good segment on "How to solve problems" that I've found useful as a framework to tackle programming projects.  At the risk of stating the obvious, the heart of the framework is just pure good old-fashioned common sense, but it's often sooooo tempting to just jump straight into the problem.  By breaking down the solution into steps, you can (hopefully) get to a more efficient and elegant solution, which should save time and frustration later on.

So the most important thing is to start off by heeding the zero-th rule! (this is computer programming after all, and everything begins from 0 rather than 1).  The all important zero-th rule is....

0. DON'T PANIC!  Take a deep breath and keep calm... 

It's actually really funny how many times the instructor reminds us to not panic during the Udacity video lesson on Problem Solving.  Computer Science students must be an anxious bunch.
So after our chill pill, the next thing to do is to make sure we understand the problem - what are the possible inputs and what are the desired outputs.  The solution is getting to a procedure that takes those inputs and maps these to the outputs defined by the job spec.

1. What are the inputs? 

  • Which player (X or O) is playing
  • The position that the player wants to play 
We need to consider how the inputs are represented -I chose to go with inputs passed in as numerical coordinates (e.g. the user enters the number of the row and column they wish to place their move).  Whenever a program uses user input, we also need to program "defensively", i.e. take into account invalid inputs by the user such as inputting letters instead of numbers or coordinates on the board that don't exist or are already occupied.  

2. What are the outputs?  

  • Print out the board after each move
  • Return when a game is complete; who won or if there was a stalemate.

3. Solve the problem!  


Working out the relationship between the inputs and outputs is clearly the hardest part (at various points, you may need to remind yourself of step 0). Some good advice is to start off by working out some examples and test cases by hand, consider what could a win looks like? What does a stalemate look like?Everyone has played tic tac toe so I won't bother going through the mechanics of the game here. Once you think systematically about how a human would play the game, we can come up with some "pseudocode" for our solution (i.e. an algorithm that describes the processes you want your code to run).  The aim of this is to get down a draft of an idea for the solution and see if it makes sense.

Pseudocode:
  • Decide which player is going first
  • Ask for that player's first move and check if it's legal (e.g. that it's on a 3x3 board, and in an empty space)
  • Has a win or a stalemate occurred?
  • If not, it's the next player's go
  • Keep going til we get to a win or stalemate


Once you get to a process of a sensible-looking solution that you're happy with, the next part is to decide which part of the code to write first.  In general, the advice is to write the simple cases first and worry about special cases at a later date - don't optimise too early.  Write small bits of code, test them and understand fully what they do before adding to it.  Obviously it depends on the problem in hand, but it's good to make a start and make your code flexible to incorporate potential changes.  I like writing a little welcome message to really get me in the mood!

print "Welcome to Tic Tac Toe, in order to play please enter your row and column numbers between 1 and 3"  

Here is my full code on Github (it is written for a 2player as well as a 1player game where the computer chooses its moves randomly among the available spaces): https://github.com/ttz21/TicTacToe/blob/master/TicTacToe.py

I probably should have commented it a bit better, but below is a little bit more of a step-by-step walkthrough of how I went about solving it (Disclaimer: it's clearly not the only solution and hopefully in future, with a bit more experience I'll have time to revisit this problem and improve it).

So I started out by deciding that I would have the tic tac toe board as an array in the program, and wrote the code that would go through each entry in the array and “print” out the board on the screen:

board = [[" "," "," "],[" "," "," "],[" "," "," "]]

def print_board(board):
    for i in range(0,3):
        print " "+board[i][0]+" : "+board[i][1]+" : "+board[i][2]
        if i<=1:
            print "..........."

Next, I thought about how moves would be recorded to the board array using the raw_input() function, and how to account for invalid inputs from the user (i.e. if something other than a 1,2 or 3 was entered as a co-ordinate value).  The function get_player_input() below asks for either the row or the column coordinate and returns the player’s entry –e.g. get_player_input( “X”, “row”) will ask player X for the row coordinate on their move.  During gameplay, this “helper” function is then used to alternately between player X and O to get their moves and store them in the board array.

def get_player_input(player_name, coordinate):
    correct_input=False
    while(not correct_input):
        value = raw_input("Player "+player_name+", it is your go, enter your desired "+coordinate+": ")

        try:
            value=int(value)
        except ValueError:
            print "That is not a valid input!"
             
        if value>3 or value<1:
            print "Co-ordinate must be a number between 1 and 3"
        else:
            correct_input=True
    return value


Besides inputting invalid numbers as co-ordinates, a player could also enter a co-ordinate that is already filled, so we also need another helper function that checks whether a particular cell is empty and returns either True or False (otherwise known as a boolean).

def valid_cell(board, row_value, col_value):
    if(board[row_value-1][col_value-1]==" "):
        return True
    else:
        return False

This can then be combined with the get_player_input() function in order to write the user’s input to the board and then display the board on the screen:

def check_player_input(player_name):
    valid=False
    while(not valid):
        row_value = get_player_input(player_name,"row")
        col_value = get_player_input(player_name,"col")

        if(valid_cell(board, row_value, col_value)):
            board[row_value-1][col_value-1]=player_name
            print_board(board)
            valid=True
        else:
            print "That cell is already taken!"
                      

After these steps, it was time to write what a win looks like in tic tac toe.  The function below returns a Boolean (True/False) by first checking whether a player has filled the cells diagonally and then loops through the rows and columns to check for horizontal and vertical wins.

def check_for_win(board, player_name):
    if (board[0][0]==board[1][1]==board[2][2]==player_name):
        return True
    if (board[0][2]==board[1][1]==board[2][0]==player_name):
        return True
    for i in range(0,3):
        if(board[i][0]==board[i][1]==board[i][2]==player_name):
            return True
        if(board[0][i]==board[1][i]==board[2][i]==player_name):
            return True
    return False

In addition to a win, the game can also be stopped by a stalemate if the board is full – the function below loops through the entries in the board searching for empty cells.

def board_full(board):
    for i in range(0,3):
        for j in range(0,3):
            if board[i][j]==" ":
                return False

    return True

Finally, we just need to alternate between the players until there is a win or the board is full.  I also added some extra functions to allow players to choose whether X or O would go first, and later on, I put in a computer player that would make moves at random – you can see the code for this on the github link above, but I won’t go into it in detail in this post.

def determine_play_mode():
    mode = raw_input("Would you like a 1 or 2 player game? ")
    return mode

def determine_first_go():
    go= raw_input("Who would like to go first? (X, O, or flip a coin?)")
    if(go.upper()=="X"):
        return["X", "O"]

    elif(go.upper()=="O"):
        return ["O", "X"]

    else:
        if(random.randint(0,1)==0):
            return ["O", "X"]
        else:
            return ["X", "O"]

gameplay = True
num_gos = 0

play_order = determine_first_go()
play_mode = determine_play_mode()

while gameplay:

    if(num_gos%2==0):
        check_player_input(play_order[0])

    else:
        if(play_mode == 2):
            check_player_input(play_order[1])
        else:
            print "Computer thinking..."
            get_AI_input(play_order[1])

    if(check_for_win(board,"X")):
        print "Congratulations Player X, you have won!"
        gameplay=False

    elif(check_for_win(board,"O")):
        print "Congratulations Player O, you have won!"
        gameplay=False

    elif(board_full(board)):
        print "This round was a draw..."
        gameplay=False

    if(not gameplay):
        again = raw_input("Would you like to play again? Enter Y to play again, or any other entry to quit: ")
        if (again.upper()=="Y"):
             gameplay = True
             board = [[" "," "," "],[" "," "," "],[" "," "," "]]
             play_order = determine_first_go()
             play_mode = determine_play_mode()
             num_gos=-1
              


    num_gos=num_gos+1



Saturday, 17 May 2014

Keep Calm and Git over it!




Many programming languages have funky names and (semi) interesting stories behind why those names were chosen.  Python was so-named due to the creator’s love of Monty Python comedy.   Java pays homage to the dependency of programmers on one of the most widely used addictive (yet legal!) drugs on the planet.  Groovy, I’m guessing, was written by some fun-loving dudes who wish they were still living in the psychedelic-seventies.   There is also a very bemusing Wikipedia article on a whole host of “joke” programming languages – my favourites are LOLCODE (designed to imitate lolcats memes) and Chef (where the programming instructions resemble cooking recipes!)

When I first heard of Git, one of the world’s most popular version control systems ,  I immediately wondered why someone would choose to use such a name.  I suppose any word in the English language could stand for something rude or nonsensical in another, but this seemed to be a very weird choice of name for anything – this is what urban dictionary has tosay about the word!   It turns out that Git was invented by Linus Torvalds, who also came up with the Linux operating system.  Apparently Torvalds once said “ I'm an egotistical b*stard, and I name all my projects after myself. First 'Linux', now 'git'”!

In my previous blog post, where I interviewed a friend who had recently become an app developer, I received some advice to get a GitHub account ASAP.  It seemed pretty sound guidance, as GitHub provides a free online way to track changes being made to files and projects.  Up until now, I thought the only program that had a “Track Changes” feature was Microsoft Word and for the Udacity homeworks and mini-programs I had written myself, I had just been saving multiple versions on my computer whenever I added new code.  Little did I know that, although the first steps of creating a GitHub account and installing the software were easy as pie, the path ahead was one rocky road.

Unlike the many tutorials out there for Python or HTML/CSS,  it took A LOT of digging to find a tutorial that started from the very beginning.  I was surprised at how many assumed some familiarity with the basic git-related terminology from page 1, while I was still asking what “commit” even meant (no, this is not related to being a commitment-phobe in real life!)

“Repository”, “Commit”, “Fetch”, “Push”….you what???

The best (free) tutorials for complete Git – newbs I found were the following:


After reading these multiple times and following the steps one-by-one, plus A LOT of trial and error from playing around with different commands from the official Git documentation (and often failing), I finally think I understand some of the basics.  As usual with a lot of programming related problems, while you are experimenting around it can sometimes feel like you are hitting your head against a brick wall, when you do get a breakthrough, there’s a real sense of achievement.

I started off with uploading a web application that functions as a basic blog that I built as part of Udacity’s Web Development course (review to hopefully come in a later blog post).  Then later, through a tech-related mailing list I’m on, I found out about an open-source project that I could easily contribute to.  I have mentioned previously that I live in London near an area that is called the Silicon Roundabout due to the fact that there are many tech startups in close proximity to Old Street roundabout.  There is an organisation called TechHub that has been set up to help support these growing businesses and they have set up a website that acts as a guide to where to eat, drink, sleep and workout near the Silicon Roundabout.

The web address is simply http://techhub.london and they have put the html and relevant css and javascript files into their GitHub account (TechHubLondon.github.io) so that others can clone this project onto their own computers, make edits and then send a request for these edits to be merged with their master file (and of course, eventually appear on the website).  I used this article to find out about how to contribute to other people’s GitHub project.

One of my favourite things to do is put on my geeky spectacles and an assortment of brightly coloured clothes from American Apparel, go out in Shoreditch and eat way too  much food.  So when I saw this project, I knew I could contribute in some way and using basic HTML knowledge, I could understand how to add my recommendations of places to eat and drink with friends or entertain investors.

You can find my GitHub account at https://github.com/ttz21 and you can see the simple edits I made, as well as my other mini-projects, which I will hopefully be expanding upon in this blog at some point in future!

Saturday, 26 April 2014

With a little help from my friends…


Much to the disgust of my nearest and dearest, I am not the greatest fan of the Beatles, however, I am happy to use this particular lyric of theirs as the title for this blog post title because can definitely relate to this song.


Awww, fwend!!
I am fortunate to know some cool people who already work as computer programmers and who have helped me at various stages of this adventure to try to become one myself.  In my previous post, I wrote about my decision to take a conversion course at university in order to start my path of becoming a programmer, however, many people have taken alternative routes into the industry that have not involved formal computer science qualifications.   Having never been a journalist or reporter of any sort, I thought it would be fun to try my hand at interviewing one of my closest friends who has recently become a developer and turning it into a blog post! 

Quick Profile


How we met: At the first day of university, we were put into the same “college family” - this was kind of like a mini-social-network, set up by our college so that freshers would get to know at least a handful of other freshers (“siblings”) .  Our “parents” were second year students, who were meant to look after us and help us settle in to university life.  Like some families, we have not done a good job of keeping in touch with most other family members, but this brother and sister have been firm friends since our first family gathering.

Programming experience: Dabbled in HTML and CSS as a teenager, some C and Matlab as part of university courses, less than 1 year of Python and Java.

Job Description: Android app developer at Detroit Labs

Life before becoming a developer: Studied a lot of Mathematics – first at the University of Cambridge (undergraduate), and then at the University of Arizona (postgrad).

Favourite dessert: Banoffee pie 

Other blogs you follow:
  • Android Developers Blog (http://android-developers.blogspot.com/) - official Android news and announcements. 
  • Android Weekly (http://androidweekly.net/) - weekly newsletter, combines platform news with tips & tricks. 
  • Colossal (http://www.thisiscolossal.com/) - really inspiring art/photography blog. 
  • James Allen on F1 (http://www.jamesallenonf1.com/) - my sporting fix. 
  • Gamasutra (http://www.gamasutra.com/) - video game industry news, tech articles and opinions.

Newb_girl: How did you get into computer programming and what was your learning path like?

Stuart: I’ve always enjoyed tinkering with programming. I remember using Logo a lot in primary school! When I was 15, I picked up HTML and CSS for fun and built a few websites in Notepad. These included a site for my local scout group, and a page where you could download a P2P version of the board game, Kensington that my friend Steve wrote in Visual Basic.  


During undergrad, we had the opportunity to work on computing projects in C designed to test both our mathematical and programming skills. This was my first exposure to a 'serious' programming language (though we were provided with a customized library that shielded us from some of the lower-level functionality). I completed as many of these optional projects as possible, because I liked that (a) progress was easily measurable, and (b) programming both required and rewarded a structured and logical approach to problem-solving.



In grad school, I used the MATLAB programming language and environment daily in my research. The MATLAB language is procedural and relatively high level programming language, which allows mathematicians, physicists and engineers to simulate model problems without needing extensive computer science backgrounds.



After graduating, I decided to leave academia in pursuit of a career path involving more immediately applicable work. I like to feel I have achieved or created something at the end of every single day. Based on my previous experiences with coding, I felt that working as a developer would satisfy this desire.


After my PhD, the first widely used programming language I learnt was Python (as I knew it was extensively used in the scientific community) and I made a few small projects of my own.  I used the same Codeacademy and Udacity courses as you, as well as the internet at large.
 
Newb_girl: How did you land your current job, and why do you think they picked you for your current role?


Stuart: After moving to Detroit last year, I simply googled companies in the area to get a feel for what the pool of employers looked like.  Not surprisingly, the Detroit area is home to a lot of companies related to the automotive industry, but I also found out that there is a vibrant tech scene comprised of many younger companies. I was wary of applying to very early start ups, since I assumed they wouldn’t be able to spend the time training someone from (almost) scratch, so I decided to target slightly more mature tech firms.

A month or so into my job search, I came across a tech teaching initiative in Detroit called Grand Circus that hosts 1-2 technical seminars each month.  I attended an evening talk on the architecture of the internet, purely out of intellectual curiosity (I did not really anticipate that this would eventually lead to a job!).  The talk was run by Nathan Hughes (co-founder of Detroit Labs, where I now work) who was an excellent instructor and obviously passionate about his field.  After the talk, I checked out Nathan online and discovered his association with Detroit Labs. Labs makes an explicit point of not being hung up on resumes, instead prioritising cultural fit and the ability to pick up new concepts when assessing prospective employees. The cultures outlined on their website definitely resonated with me, and I felt their approach to hiring would suit my planned transition into software development. Attending a second talk by Nathan soon after, titled "Life of an App Developer", confirmed my positive impressions of the field in general and Detroit Labs in particular. I applied there soon after.

The application procedure at Detroit Labs is not totally standard.  The first step involves sending an email saying hello, and filling in a “get-to-know-you” questionnaire rather than a resume, which is then emailed to every employee to gauge your cultural fit with the company.  If the reaction to the get-to-know-you is positive, then you are invited for a cultural interview with existing team members to talk about life and your motivations, and to find out a bit more about the company.  Having now conducted some of these interviews myself, I would like to stress the importance of researching the company you are applying to before heading in to an interview. When I prepped for interview at Labs, I made sure I was familiar with their app portfolio, listened to podcasts the co-founders had recently been guests on, etc. If candidates don't do this, it's hard to believe they are excited about joining us.


If you are deemed a good cultural fit, then the last step is a technical interview.  This typically involves some relatively straightforward pre-interview coding exercises that are extended in the actual interview. The objective is really for the interviewers to see how a candidate approaches new problems and to check out their coding fundamentals (good code structure, refactoring, logical approach to implementing several new features at once, etc.).  During the interview this seemed like a daunting task, but because I had written clean code (broken into smaller methods, with checks for invalid input) I was able to incorporate the changes relatively easily. This is another must-do for interviews - if you are writing code, make sure it is structured and commented very well!
 
Newb_girl:  Tell us a bit about a client project you've worked on 

Stuart: I'm currently working on an app for an energy company that allows customers to pay their bills, report power outages and receive updates on their services.  I've only been on the project for a couple of weeks, so I've had to spend a fair bit of time familiarising myself with the existing codebase.  I've been asking lots of questions and trying to figure out why previous developers chose the structure and implementations they did. So far most of my work has been on bug fixes, but we are now beginning an overhaul of the entire app design.

Besides learning Java, the Android framework, and a bunch of other tools oft-used by programmers (e.g. version control), I've also had to learn a bit about the world of business, how companies work and what they are driven/motivated by.  It's also interesting to see how the decision making process differs within a large company vs at the very agile Detroit Labs.

Newb_girl:  And now for the cliched closing question: what do you wish you knew before you did your career change and what advice would you give to programming newbies?


Stuart:  I think my advice would differ depending on how much people know already.  For someone who knows absolutely nothing: I would say it's best to sample lots of online learning resources, and find one that teaches in a way that complements how you learn.For someone who knows a little bit already: when I was at that stage, what I found difficult was bridging the gap between writing a Tic Tac Toe game and understanding/working as part of a project that has thousands of files and moving parts.  I would suggest searching for user groups (programmer meetups, often categorized by language or application area) in your area, and then attending a few meetings to see how your language of choice is used by professionals.  It’s fine to not understand what is going on at first, but immersing yourself in the environment will help you learn (and make connections), just like living in a foreign country helps you learn and absorb a new language.  

Also, sign up for a free GitHub account and familiarise yourself with Git – this is a popular version control used to track code changes and enable multiple developers to collaborate on codebases.  Add your personal projects to GitHub repositories to (1) get used to the workflow and commands, and (2) build a portfolio to demonstrate enthusiasm and commitment when applying for jobs.  Because many open source projects, both large and small, host their code on GitHub, you will also be able to check out custom libraries for your primary language and begin to contribute bug fixes and suggestions to real projects.

Newb_girl: Thanks for sharing your advice, bro!