Showing posts with label Tic-Tac-Toe. Show all posts
Showing posts with label Tic-Tac-Toe. Show all posts

April 10, 2015

Week of 04/05/15 - Python Part 26: Finished Up

    This project has taken up a lot of my time. So, to just finish it and move on, what I'm going to do is remove the references to the row and the column, because I can't get them to work outside of the turn() function. So what I'm going to do is have it check every row, column, and diagonal every turn. On Monday, I had tried moving most of the contents of the turn() function to outside it, but I didn't know what it did, so I just reverted everything back. Now, I've made the code look like:

    def column_checker(column, board):
        if board[0][0] == board[1][0] == board[2][0] \
        or board[0][1] == board[1][1] == board[2][1] \
        or board[0][2] == board[1][2] == board[2][2]:
            return 1
        else:
            return 0


    I was testing it with my friend Felipe, who sits next to me in class, and it works how it should. I'm probably going to test it out with a few other people later. But now that I have that project out of the way, I kind of want to move away from Python. I've been doing this for the past semester and a third. I want something new. I want to learn something more lower level. I want to learn C or C++.

    On Friday, the morning was spent figuring out which one to learn; I decided to learn C++ because it can make programs with a GUI, and is a pretty common language. I'm going to learn using the website http://www.learncpp.com because I saw it recommended on several websites, including stackoverflow.

    The tutorial starts out with explanation of instruction sets in binary, assembly, and then higher level languages. For higher level languages it described compilers and interpreters. Then it goes into a history of C itself. I didn't know that because C was so portable, able to compile on many different types of computers, that Ken Thompson and Dennis Ritchie rewrote Unix from assembly to C. A formal standard for C was created by some committee in the 80's, and C++ was developed as an extension to C in 1979, but C++ was only ratified in 1998; a new version, C++03, was ratified in 2003, and C++11 was ratified in 2011. The site says it teaches C++03, and any additions by C++11 will be in the appendix. It also says that C++ is object oriented.

April 6, 2015

Week of 03/29/15 - Python Part 25: Implementation, Among Other Things

    I started out the week by beginning the integration of the new checking function into my code. First, what I needed to do was remove the original checking function, which I did swiftly. Then, I had to set the flag number to be equal to the output of the flag checker function, and then I had to write an if statement for when it equals 1 or if it was more than one. Then, I had to write the congratulations function, for both the string and the ASCII art from the text file. Then, I began to play the game to test if it worked. It worked, in a sense. When I would get multiple rows, the game would print out the congratulations ASCII art, and with singles, it would work correctly, except the bottom-left to top-right diagonal still isn't recognized. When I put in some debugging code, when I add together the row and the column, it returns 0, even though it should return 2. This problem has been going on for a pretty long time. I will fix it next week.

March 30, 2015

Week of 03/22/15 - Python Part 24: Writing Interruption

    On Tuesday, March 24, I could not work on my Python project very much because we had to do a writing piece for the State of Texas. It was supposed to be a hypothetical submission for an art demo. I couldn't really think of what it should be, until my friend reminded me about my use of ASCII art in my project. That gave me the idea of an ASCII animation, and I would use Python to display it. I would convert each frame of a video of a bouncing ball through a conversion program, then save each ASCII frame in a separate text file. Then, using Python, I would open the first frame's file, display it, wait 1/30th of a second, clear the terminal, then show the next one. I would also make it loop. This got me thinking about my use of ASCII in my own Python code. So, instead of cluttering up my code with a bunch of print() statements, I put the ASCII art in a separate text file, and actually wrote the code to display it in both the test file and the main file.

    Next thing I tried to do was make a distinction using html of the post before this one. The original html showed two areas of code where one was an iteration of the other. To show the difference between the two pieces of code, I changed the different part's background color to maroon using another set of <pre> tags. However, apparently the pre tag makes a new paragraph when used, making a space which I don't want there. To fix this, I did some googling and learned how to do it in CSS. But I can't really change the CSS in Blogger, so that's when I learned I could input CSS using html with the <style> tag. Now it looks like this:


March 24, 2015

Week of 03/08/15 - Python Part 23: Adding Nothing

    What I've done now is I have created a new file, a test file, to check if the checker works like it should, because I haven't tested it yet. I just made some variables, and used a board that was already filled in with a winning combination,row and board variables that made sense, and a player number. Now, the first problem I ran into when I ran the test for the first time was that for the diagonal checking functions, they had to have two conditions that were true in order for the function to return a 1, and if they weren't it would return a zero. The code read:
    def diag_bl_tr_checker(row, column, board):
        if row == column:
            if board[0][0] == board[1][1] == board[2][2]:
                return 1
            else:
                return 0

    The problem with the code is the first if statement, which checks if the row is equal to the column, and this was also a problem with the other function, which checked if the row added to the column equaled 2. If the first if statement evaluated to false, the code wouldn't return anything, and its addition into the flag_number variable wouldn't work because it was not a number, so it gave an error.
      flag_number =   column_checker(column, board)
                    + row_checker(row, board)
                    + diag_bl_tr_checker(row, column, board)
                    + diag_tl_br_checker(row, column, board)
    Now, the code has an else statement that returns zero at the end, so now it works.

    def diag_bl_tr_checker(row, column, board):
        if row == column:
            if board[0][0] == board[1][1] == board[2][2]:
                return 1
            else:
                return 0
        else:
            return 0

March 9, 2015

Week of 03/01/15 - Python Part 22: Rewrite

    To fix the issue outlined in last week's post, what I first did was remove each checker from the if statement, and put each checker into it's own function. I also made the function return zero if there are no wins on the board. Then, I removed their ability to distinguish between player, because this checker checks the board after the player places their piece, so the player_number variable should be sufficient for the new checker function. Now what the individual checking functions do is they each return whether or not they evaluate to true, and if so, they return a 1. If it's not, the function will evaluate to 0. I could have used a true or false, but those wouldn't be able to be manipulated in the way I need to.
    def column_checker(column, board):
        if board[0][column] == board[1][column] == board[2][column]:
            return 1
        else:
            return 0

    Now, all of the functions that were written look like the one shown above. Then, for the actual checking function, I add them all up and see if the resulting number is greater than or equal to 1, at which point the game will say congratulations and then it will end. I have also decided to make a little easter egg where if the player gets more than 1 three-in-a-row at the same time, it would print ASCII art to the terminal. I wouldn't make it myself because I don't know how, so I'll find some on the internet.

February 27, 2015

Week of 02/22/15 - Python Part 21: Finding a Solution

    As we all know, alcohol is a solution. However that's not the kind of solution I'm looking for. What I think I can do to see what the problem is, is printing out the row and column variables after they are set, using the print(row) and print(column) functions. From doing this, I found out that the coordinates of the bottom-left to top-right are (0,2), (1,1), and (2,0). These are the expected values that were discussed in last week's post. So, in theory, this code:
    elif (row + column) == 2:
        if board[0][2] == board[1][1] == board[2][0]:
            if board[0][2] == " X ":
                return 1
            elif board[0][2] == " O ":
                return 2
should work. But, for some reason it doesn't. I don't see any problems with the syntax. But now that I've mulled it over, I see something that may cause me a headache down the line: what if both diagonals are completed at the same time? But then i realized that this was a non-issue because it would choose the one that was further up the elif statement tree. This is also the case with the normal edges. Maybe later I should congratulate the player if he gets a double. But that would take some rewriting of my checking function. But, I think re-writing my checking function would be a good idea anyway, because I have no idea why the other diagonal isn't working. Maybe it's because they share an entry, (1,1). In any case, this problem can probably be solved by rewriting the logic behind the checker.

    To fix the issue I'm having, what I think I'll do is related to something that I saw on reddit a few weeks ago. There was a bug in the game "Team Fortress 2", where sentry guns (automatic turrets) could be exploited to turn back on during a humiliation round, a gamemode after a normal round where the members of the losing team can't fight back, just move around. In the humiliation round the sentry guns of the losing team get disabled. However, the exploit is that if, before the humiliation round, the sentry begins upgrading (which disables the sentry) and when it's done upgrading, the sentry comes back on even though the humiliation round should have disabled them.
    The guy on reddit said "I suspect the sentry has a single flag which is set when it is disabled. For example, by a sapper, by humiliation period, by a building animation, or by soldier lasers. The problem is that these conditions can occur simultaneously." So when the sapper is removed, the game still uses the function to restore the sentry at the end, even though there's another condition which should have kept the sentry disabled. The guy on reddit said that you need to set a separate flag for each condition, so that's what I'm going to do; 1 flag for a horizontal or vertical win, and 1 flag for the diagonals. Unless I want to put in and easter egg for getting 2 wins at the same time. In which case, I would have to make a flag for each: vertical, horizontal, and 2 diagonals. I thought about writing a class for it, but that seems unnecessarily difficult. So what I'm going to do is write a new checker.

February 19, 2015

Week of 02/15/15 - Python Part 20: Debugging

    I have found a bug in my code. The problem is that, when the diagonal, starting from the bottom left and ending in the top right, is completed, the game doesn't register it as a win. For example:

    Turn # 9
       [1] [2] [3]
     1    | X | O 
       -----------
     2  X | O | X 
       -----------
     3  O | X | O 
    Player 1: Enter the column number of your move:

    Even though the bottom-left to top-right diagonal is completed, the game doesn't recognize it. The other diagonal is recognized, and so are the other rows and columns. Now, let's look at the code behind the checker function:

    elif (row + column) == 2:
        if board[0][2] == board[1][1] == board[2][0]:
            if board[0][2] == " X ":
                return 1
            elif board[0][2] == " O ":
                return 2
(I have colored the background of the code blue to signify that this is code, not terminal output.)

    First, I must explain that in order for the board to work, 1 is subtracted from both the row and the column in order to make the row and column numbers correspond with their list entry. With that out of the way,  how my code checks for a win is: after checking the column the move was in, and the row the move was in, it checks if the column was equal to the row. Because the row can only equal the column on a single diagonal, from the top-left to the bottom-right, it checks if those three are equal to each other. Then, after that, the code above checks if the column added to the row is equal to 2 because the (row,column) combinations that are on that diagonal are (0,2), (1,1), and (2,0) and when you add each (row,column) pair you get 2 for each. Then it checks if they're all equal, and then it decides whether to return a 1 or a 2 depending on who's move was in the diagonal. In theory, this should work. In practice, it does not. It just goes to the next turn. Which it shouldn't. I suspect the problem to be in the first line, elif (row + column) == 2:, because the rest of the code is being used in the other elif statements.

February 17, 2015

Week of 02/08/15 - Python Part 19: Lots of Work was Done

     Usually, I don't really do a lot of work in Independent Study. But this week is quite the exception. What I did was finish a game-checking script, so after every move, it checks the entire row, column, and if the move was on one of the diagonals, it would check the diagonals. I got this idea after reading some forums, and figured it would be a great alternative to checking each and every row, column, and diagonal every turn. The checker took a lot of work to write, with me having to define what should happen if player 1 wins or if player 2 wins. Also, instead of putting the checker() function inside of the turn() function, I decided to put the checker function as part of the for-loop instead, and made it so that the checker function only runs when the for-loop reaches 5 or more loops. To do this, I also had to move the variables row and column from the turn function, and made it go from:
def turn(i, playing):        
    Column=0                 
    Row=0                    
    (More code here)         

for i in range(1,10):        
    turn(i, playing)         

To:
for i in range(1,10):
    column = 0
    row = 0
    turn(i, playing, column, row)
    if i >= 5:
        checked = checker(i, playing, column, row, board)

    Next what I did was I combine the two files, main.py and definitions.py. I did this partially because I was having some issues with imported functions not working right, and because I thought it would be easier to debug than two separate files. This came with some renaming and restructuring of the combined file. I also accidentally saved the file to two different directories, but I used the unix command, diff, to figure out which was newer.

February 10, 2015

Week of 02/01/15 - Python Part 18: Problem

     Recently, codingground has been very finicky. I open up it's website, click on "python-3", and instead of redirecting me to it's Python 3 interpreter and IDE, it just refreshes the page and doesn't do anything. And just, now it started working again. I can't handle the fact that sometimes it just doesn't work. Therefore, I'm looking around for a different online interpreter. I was looking at codeanywhere, but after some careful reading, I learned that using it for free was only a week-long trial. I settled on koding, but first I need to figure out how to use it. It seems to me that koding is a virtual machine with a http server, but all I need to use it for is as an executor of python code.

     So what have I done so far on koding? Well, for starters, I finally got the turn number to increment, using the variable used in the for-loop. It used to look like this, with the incrementer (turn_number += 1) being in the turn() function.
if AI_choice == "1":
    turn_number = 0
    for i in range(1,10):
        turn(turn_number, playing)
     But then, I thought that maybe it wasn't incrementing due to a problem with the variable itself. So I decided to try using the variable I used to make the loop, i, in the turn() function itself:
if AI_choice == "1":
    for i in range(1,10):
        turn(i, playing)

    I would post more this week, but on Friday I looked for more html stuff to make my website better. Specifically, I made it so the positioning of my code in the pre tag was centered, so that it looked nicer. Then, on an older post, number 15, I screwed around with the html until I centered the example of the tic-tac-toe board. I learned about html positioning, including absolute and relative positioning.

January 23, 2015

Week of 01/18/15 - Python Part 17: I Guess it's Tic-Tac-Toe

     A week with two class days isn't nearly long enough to do very much with my project, but I did get a few things done. First thing I did on Wednesday was I changed the turn() function so that instead of blacklisting all of the inputs except for the ones that I wanted, I made a whitelist of the possible values. It made it easier, seeing as there were only three things to whitelist, but every other input to blacklist.

     Next, I tried executing my code, but I had a problem: when I input a 3, it would give me an out-of-range error. But I figured that I forgot to subtract 1 from the row and one from the column input, because in Python, lists start at the zeroth term.

     Then I created a function to check if the input coordinate was already occupied by a piece. Or, more accurately, I created a function that checks if the coordinate is not blank, reducing the amount of code I need to write. I also wrote the code which actually changes the board and print the changed board so that I'm not looking at a blank board every time.

     A problem with my code that I found while trying to run my turn() function was that the turn number didn't increment for some reason, and I'm still not sure why it does that. This is important because I use the turn number to calculate which player is currently playing. I might be able to instead increment the variable with a while loop, but I'm not sure.

January 17, 2015

Week of 01/11/15 - Python Part 16: A New Year, an Old Project

     Now that we are in the new semester, I think it's time I began working on the tic tac toe game again. I want to finish it, without the time constraint of a midterm. I began by renaming a few variables, and reading through my code to figure out what I was doing two week ago. I began to write code to actually play the game in turns, when I realized I could save a lot of time by writing a function for taking turns. What it does is it increments the turn number, finds out which player should be playing, prints the board,. It then prints the board with the column numbers highlighted and prompts for input for the column number, and does the same for the row number. However, while writing and testing the turn function, I ran into an error where it said "int object not callable". I couldn't figure out what was causing this, but adding a few variables as arguments into some functions and renaming a few variables seems to have fixed the problem. Another thing I had to do was move some global variables into the functions file, because apparently I can't use the variables as arguments without them being in the same file. After I'm done, I'll probably re-merge the files just so the code is all in one place. Currently they're separated for organizational purposes.

     Next, what I did was put the inputs into loops, so that the game wouldn't keep playing if the player input the letter "a" instead of a coordinate. All of this took a while to do, but finally, the player can take turns and input coordinates.

December 19, 2014

Week of 12/14/14 - Python Part 15: Mid-Term

    For my midterm, I decided what I would do is make a game of tic-tac-toe on codingground. First, I didn't know exactly what I was doing, so I imported the random library, because I had used that before in the battleship post. Then I made the function randint(a,b) and made it to reference random.randint(a,b) because I forgot I could import specific functions from a library and make them native functions, but hey it worked at the time. I went on to make a function to print out the game board, because I knew I'd need one. It went through several iterations of what it looked like, and I got enough whitespace and padding into the board that it looked... not bad. Here's how it looks:
               
    1   2   3  
 1    |   |    
   ----------- 
 2    |   |    
   ----------- 
 3    |   |    
               
     The numbers are there to serve as a reference to the player because I don't know how to do click-based input. Later on, I decided I would need to highlight the numbers on each axis depending on which axis I was prompting the player for, so I made it so that they were in brackets. It took a while for me to be able to get the spacing right and all the parts of the board lined up, but I got it.

     Later, I decided that I would have to clear the board (because looking at the past stuff entered into the terminal would look sloppy and unprofessional, which I didn't know that I could do when I was working on the battleship game). So, after searching on stackexchange, I found what I was looking for; a function that would invoke the Unix terminal's "clear" command, blanking the screen.

     Next I decided that all the functions that I had made made my code look all messy. So after searching some forums, I found out how to put all my functions into a separate .py file, and imported everything from it. Then, I wrote the code to make the back end of the board, using several lists. Next was to make the loops that would allow the game to be played over and over until you decide to stop. I had to use while loops using a single variable that I wouldn't change, because I didn't know how to just make thing loop. I used a global variable for this, because I would use it in other loops as well. I went on to ask the player whether he wanted to play against a friend or computer, and made it so that if they chose computer, the console would print that that feature was not implemented yet, and when they picked a friend, it would clear the screen and print out the board. Getting the choosing thing to work was hard, and took up a lot of time, but it worked by the end. I had considered creating a checking function to check if the game was won or not, but it was too difficult. Here are the files if you want to upload them to codingground and try it yourself.