Advertisement

My Very First Game - Made In Python - TICTACTOE

Started by February 16, 2017 10:53 PM
7 comments, last by Clintos 7 years, 10 months ago
I just wanted to say that I have made my first tic-tac-toe game in python and honestly, I know it is VERY poorly coded. I would really like to see what you guys think of it. What has been done good, what can be improved and why would it should be is 100% APPRECIATED :)
Sidenote- A big logical error is that you can replace the other player's input with your own. This is my first game that I am AT SOME EXTENT satisfied with since it was my first time I actually used and manipulated arrays which is what made me very happy. I think it is my first major step. :D


    import time;
    import random;
    import sys;
    
    #variable declaration (pt 1)
    boardVal = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
    
    #boardFunction
    def BoardShown():
        print("===============");
        print(boardVal[0] + "|" + boardVal[1] + "|" + boardVal[2] + "|" );
        print(boardVal[3] + "|" + boardVal[4] + "|" + boardVal[5] + "|" );
        print(boardVal[6] + "|" + boardVal[7] + "|" + boardVal[8] + "|" );
        print("===============");
    
    def player1():
        print("PLAYER ONE'S TURN");
        userIn = int(input("Choose val to change between 1-9:"));
        numChoiceUser = userIn - 1;
        boardVal[numChoiceUser] = "X";
        BoardShown();
    
    
    def player2():
        print("PLAYER TWO'S TURN");
        userIn2 = int(input("Choose val to change between 1-9:"));
        numChoiceUser2 = userIn2 - 1;
        boardVal[numChoiceUser2] = "o";
        BoardShown();
    
    def Turns():
        player1();
        winnerCheck()
        player2();
        winnerCheck()
        player1();
        winnerCheck()
        player2();
        winnerCheck()
        player1();
        winnerCheck()
        player2();
        winnerCheck()
        player1();
        winnerCheck()
        player2();
        winnerCheck()
        player1();
        winnerCheck()
        player2();
        winnerCheck()
        
    def winnerCheck():
        timeShut = 5
        
        if boardVal[0] == "X" and boardVal[1] == "X" and boardVal[2] == "X":
            print("player 1 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[3] == "X" and boardVal[4] == "X" and boardVal[5] == "X":
            time.sleep(timeShut);
            sys.exit()
            print("player 1 wins!");
        elif boardVal[6] == "X" and boardVal[7] == "X" and boardVal[8] == "X":
            time.sleep(timeShut);
            sys.exit()
            print("player 1 wins!");
        elif boardVal[0] == "X" and boardVal[4] == "X" and boardVal[8] == "X":
            print("player 1 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[2] == "X" and boardVal[4] == "X" and boardVal[6] == "X":
            time.sleep(timeShut);
            sys.exit()
            print("player 1 wins!");
        elif boardVal[0] == "X" and boardVal[3] == "X" and boardVal[6] == "X":
            time.sleep(timeShut);
            sys.exit()
            print("player 1 wins!");
        elif boardVal[1] == "X" and boardVal[4] == "X" and boardVal[7] == "X":
            print("player 1 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[2] == "X" and boardVal[5] == "X" and boardVal[8] == "X":
            print("player 1 wins!");
            time.sleep(timeShut);
            sys.exit()
            
        elif boardVal[0] == "o" and boardVal[1] == "o" and boardVal[2] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[3] == "o" and boardVal[4] == "o" and boardVal[5] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[6] == "o" and boardVal[7] == "o" and boardVal[8] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[0] == "o" and boardVal[4] == "o" and boardVal[8] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[2] == "o" and boardVal[4] == "o" and boardVal[6] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[0] == "o" and boardVal[3] == "o" and boardVal[6] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[1] == "o" and boardVal[4] == "o" and boardVal[7] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
        elif boardVal[2] == "o" and boardVal[5] == "o" and boardVal[8] == "o":
            print("player 2 wins!");
            time.sleep(timeShut);
            sys.exit()
            
    
    #tic-tac-toe game
    print("Hello and Welcome to the Tic-Tac-Toe game!");
    print("The rules are simple, you enter your 'X' on one of the 9 tiles displayed below:");
    BoardShown();
    
    #example of the board displayed
    print("You will be up against a computer, so you will need to wait for your turn");
    
    Turns();

Congrats :)

Something that's initially obvious is that there is not much code reuse.

For instance rather than having player2 and player1 functions can you not use a single player function and pass in which player it is. Or reduce the amount of code in Turns, use a for loop for example. For this game it's not going to be a massive issue but as you get much larger complex code bases, avoiding duplicate code helps to make iteration much easier. This would be a great example to practice from. Just to note, the aim is not to make it in the least lines possible as that is not always beneficial and can make codebases harder to read.

Advertisement

Looks nice as first game.

The only thing that's not pythonic in your program, is the use of semi-colon (the ";"). Python has no semi-colon at the end of a line. You do need one if you have more statements at one line, but that is quite not recommended, so in practice, you never type a semi-colon. Other languages like Java or C do use semi-colons at the end of a line, so maybe that's where you got confused.

As for improvements, they are possible if you do checking of the rows/columns separately from claiming victory:


def checkLinesPlayer1():
    if boardVal[0] == "X" and boardVal[1] == "X" and boardVal[2] == "X":
        return "yes"

    elif boardVal[3] == "X" and boardVal[4] == "X" and boardVal[5] == "X":
        return "yes"

    elif boardVal[6] == "X" and boardVal[7] == "X" and boardVal[8] == "X":
        return "yes"

    elif boardVal[0] == "X" and boardVal[4] == "X" and boardVal[8] == "X":
        return "yes"

    elif boardVal[2] == "X" and boardVal[4] == "X" and boardVal[6] == "X":
        return "yes"

    elif boardVal[0] == "X" and boardVal[3] == "X" and boardVal[6] == "X":
        return "yes"

    elif boardVal[1] == "X" and boardVal[4] == "X" and boardVal[7] == "X":
        return "yes"

    elif boardVal[2] == "X" and boardVal[5] == "X" and boardVal[8] == "X":
        return "yes"

    return "no"

def checkLinesPlayer2():
    if boardVal[0] == "o" and boardVal[1] == "o" and boardVal[2] == "o":
        return "yes"

    elif boardVal[3] == "o" and boardVal[4] == "o" and boardVal[5] == "o":
        return "yes"

    elif boardVal[6] == "o" and boardVal[7] == "o" and boardVal[8] == "o":
        return "yes"

    elif boardVal[0] == "o" and boardVal[4] == "o" and boardVal[8] == "o":
        return "yes"

    elif boardVal[2] == "o" and boardVal[4] == "o" and boardVal[6] == "o":
        return "yes"

    elif boardVal[0] == "o" and boardVal[3] == "o" and boardVal[6] == "o":
        return "yes"

    elif boardVal[1] == "o" and boardVal[4] == "o" and boardVal[7] == "o":
        return "yes"

    elif boardVal[2] == "o" and boardVal[5] == "o" and boardVal[8] == "o":
        return "yes"

    return "no"

def winnerCheck():
    timeShut = 5

    player1Won = checkLinesPlayer1()
    if player1Won == "yes":
        print("player 1 wins!")
        time.sleep(timeShut)
        sys.exit()

    player2Won = checkLinesPlayer2()
    if player2Won == "yes":
        print("player 2 wins!")
        time.sleep(timeShut)
        sys.exit()

This does the same as your winnerCheck function, but instead of testing and immediately printing, as you do, this code has separate functions "checkLinesPlayer1()" and "checkLinesPlayer2()", which return "yes" if they found a line for the player, else they return "no". In "winnerCheck", that returned result is tested, and then the player is told that he/she won.

Now you can see that "checkLinesPlayer1()" and "checkLinesPlayer2()" are exactly the same, except one tests for "X", and the other one tests for "o". If you pass that string into the function, you can delete one case, saving more than 20 duplicated lines:


def checkLines(player):
    if boardVal[0] == player and boardVal[1] == player and boardVal[2] == player:
        return "yes"

    elif boardVal[3] == player and boardVal[4] == player and boardVal[5] == player:
        return "yes"

    elif boardVal[6] == player and boardVal[7] == player and boardVal[8] == player:
        return "yes"

    elif boardVal[0] == player and boardVal[4] == player and boardVal[8] == player:
        return "yes"

    elif boardVal[2] == player and boardVal[4] == player and boardVal[6] == player:
        return "yes"

    elif boardVal[0] == player and boardVal[3] == player and boardVal[6] == player:
        return "yes"

    elif boardVal[1] == player and boardVal[4] == player and boardVal[7] == player:
        return "yes"

    elif boardVal[2] == player and boardVal[5] == player and boardVal[8] == player:
        return "yes"

    return "no"

def winnerCheck():
    timeShut = 5

    player1Won = checkLines("X")
    if player1Won == "yes":
        print("player 1 wins!")
        time.sleep(timeShut)
        sys.exit()

    player2Won = checkLines("o")
    if player2Won == "yes":
        print("player 2 wins!")
        time.sleep(timeShut)
        sys.exit()

Again same function as before, but now the test function is named "checkLines", and it takes a 'player' value with the string you want to test for. Now you can use the same "checkLines" function for both players, as you vary what the function tests with the "X" or "o" parameter.

he only thing that's not pythonic in your program, is the use of semi-colon (the ";"). Python has no semi-colon at the end of a line. You do need one if you have more statements at one line, but that is quite not recommended, so in practice, you never type a semi-colon. Other languages like Java or C do use semi-colons at the end of a line, so maybe that's where you got confused.

Thanks for all the helpful insight! I really appreciate it. I just wanted to let you know the reason I am adding the semi-colon at the end is because I want to get used to using it on other high-level languages such as Java and C#. I thought it would be a good habit to get used to.

THANKS FOR ALL THE HELP :)

Congrats :)

Something that's initially obvious is that there is not much code reuse.

For instance rather than having player2 and player1 functions can you not use a single player function and pass in which player it is. Or reduce the amount of code in Turns, use a for loop for example. For this game it's not going to be a massive issue but as you get much larger complex code bases, avoiding duplicate code helps to make iteration much easier. This would be a great example to practice from. Just to note, the aim is not to make it in the least lines possible as that is not always beneficial and can make codebases harder to read.

Thanks for all the helpful feedback. It really pleases me to know that there are people out there willing to help. I had a hunch (hehe) that there was a large issue with iteration and code reusability, but it was just that I didn't know how to apply them. "Practice makes perfect" is very much true when it comes to programming. I guess its back to doing homework on what I need to work on which is EXACTLY what you guys gave me! THANKS FOR ALL THE HELP BRO

A big logical error is that you can replace the other player's input with your own.

Fix it.

You might think "but it's only a small thing, and it doesn't matter that much -- the game is 90% done, isn't that good enough?", or similar, but the last 10% of any game will most likely teach you a lot.

You've done well to get this far, but you can do better. Learning how to finish things is a very valuable skill.

Hello to all my stalkers.

Advertisement

I thought it would be a good habit to get used to.
Believe me, you will learn very fast, as those compilers tend to react violently to missing semi-colons :)

While languages look a lot like each other if you read them, they are in fact deeply different from each other. Trying to push a language into the ideas of another language doesn't do justice to both languages.

Instead, approach each language with an open mind asif it's the only language in the world, and use it like its designers aimed it to be used. It's the happiest code path, giving you the best possible quality of code in that language, and the best way to experience each language.

That in turn makes it possible to make a fair judgement between languages.

Fix it. You might think "but it's only a small thing, and it doesn't matter that much -- the game is 90% done, isn't that good enough?", or similar, but the last 10% of any game will most likely teach you a lot. You've done well to get this far, but you can do better. Learning how to finish things is a very valuable skill.
@[member='Lactose'],

Great idea! Thank you

I thought it would be a good habit to get used to.
Believe me, you will learn very fast, as those compilers tend to react violently to missing semi-colons :)

While languages look a lot like each other if you read them, they are in fact deeply different from each other. Trying to push a language into the ideas of another language doesn't do justice to both languages.

Instead, approach each language with an open mind asif it's the only language in the world, and use it like its designers aimed it to be used. It's the happiest code path, giving you the best possible quality of code in that language, and the best way to experience each language.

That in turn makes it possible to make a fair judgement between languages.

Thanks for the tip :D

This topic is closed to new replies.

Advertisement