0

Im just starting out with my python learning, and having reached my first capstone project (tik_tak_toe) using jupyter notebook, I wondered if there was a cleaner and/more efficient way of running my check to determine a winner. Just to fully clarify for context:

-"board" in a numeric pattern similar to that on a full sized keyboard (top = 7,8,9 middle = 4,5,6 etc)

  • the board is created in a dictionary, with keys 1-9

  • key values are altered by (user = int(input('number')), then board[user] = 'X' / 'Y'

     def result_check(test):
         # VERTICAL WIN_CHECK
     if ('X' in test[1] and test[2] and test[3]) :
         return True
     elif ('Y' in test[1] and test[2] and test[3]):
         return
     elif ('X' in test[4] and test[5] and test[6]):
         return True
     elif ('Y' in test[4] and test[5] and test[6]):
         return True
     elif ('X' in test[7] and test[8] and test[9]) :
         return True
     elif ('Y' in test[7] and test[8] and test[9]):
         return True
         # HORIZONTAL WIN _CHECK
     elif ('X' in test[7] and test[4] and test[1]):
         return True
     elif ('Y' in test[7] and test[4] and test[1]):
         return True
     elif ('X' in test[8] and test[5] and test[2]):
         return True
     elif ('Y' in test[8] and test[5] and test[2]):
         return True
     elif ('X' in test[9] and test[6] and test[3]):
         return True
     elif ('Y' in test[9] and test[6] and test[3]):
         return True
               # DIAGONAL WIN_CHECK
     elif ('X' in test[7] and test[5] and test[3]):
         return True
     elif ('Y' in test[7] and test[5] and test[3]):
         return True
     elif ('X' in test[9] and test[5] and test[1]):
         return True
     elif ('Y' in test[9] and test[5] and test[1]):
         return true
     else:
         return False
    
SlickGT86
  • 23
  • 5
  • 1
    You should look into (nested) [loops](https://wiki.python.org/moin/ForLoop). Btw, if you have working code and you're loking for improvements, you should post your question on https://codereview.stackexchange.com/ instead. – Mike Scotty Dec 09 '20 at 13:42
  • `if ('X' in test[1] and test[2] and test[3]) :` is not doing what you think it does. Try `if ('X' == test[1] and 'X' == test[2] and 'X' == test[3]) :` or `if test[1] == test[2] == test[3] == 'X':` or look into the _all(...) function. – Patrick Artner Dec 09 '20 at 14:01
  • Beside that you got a `true` in there that should give you an error. There are plenty of tic tac toe questions on SO - consider searching and studying them, there is plenty that could be done better – Patrick Artner Dec 09 '20 at 14:04
  • Thanks for the suggestion Mike, hopefully when I finish this project I can post the coding there and get some feedback if Id made any errors – SlickGT86 Dec 09 '20 at 14:39

1 Answers1

0

Since you said you are new to python, are you new to programming in general? If not, is there a reason you have the board as a single list rather than a nested list? And are you aware of loops? Because depending on your knowledge level we can know how into how much detail we should go in explaining.

To illustrate a normal list would be test=["X","X","X","O","O","O","O","O","O"] while a nested list would be test=[["X","X","X"],["O","O","O"],["O","O","O"]]. You would do so because it would make looping over it much easier.

Generally in programming if you have a lot of if-else statements chances are you can automate them using loops. Here's an example of the horizontal check:

def check(inputList):
    for i in range(0,9,3):
        winner=0
        for j in range(3):
            if test[i+j]=="X":
                winner+=1
        if winner==3:
            return True
    return False

How does it work?

  • First we start with a loop that goes from 0 to 9 in steps of 3, so it assumes the following values: (0,3,6). This is basically for each "line"
  • then we use a helping variable to count the amount of "X"es in the line
  • next we use another loop WITHIN that loop that loops from 0 to 3 in steps of 1 so it has the values (0,1,2)
  • now we check every entry in the line and if it's a "X" we add 1 to winner.
  • then after we checked the line if the value of "winner" is 3, we return true.

If you wanted to do the same for a win of "Y" as well, just check for a "Y" and use winner-=1. If winner==-3 after the line you know that "Y" won.

You can do the same for the lines by switching around the loops a bit. For the diagonal test, you can just use if conditions, it's just two checks after all.

HilbertB
  • 352
  • 1
  • 2
  • 12
  • thanks very much, the explaination you gave was very useful and another teachable moment for me :) – SlickGT86 Dec 09 '20 at 14:31
  • thanks very much, the explanation you gave was very useful and another teachable moment for me :) One of the main reasons I used dictionary was because in assumption of my users input value (they would choose from 1-9), with a dictionary I could reference their input to the corresponding key (e.g dict{ '1':"X",'2':"X"....'9':"Y"} whereas with a nested list, the corresponding positions is 0-8 so when input() = 2, I must update the nested list as n_list[0][1] = "X" rather than dict[2] = "X" – SlickGT86 Dec 09 '20 at 14:38
  • That's a reasonable explanation, especially with more basic python code. When things get more complicated I would probably always focus on choosing a good way to store my data first (which would be backend) and then worry later about converting user input into that data structure later. For something as simple as tick-tack-toe it hardly makes a difference, writing loops for a "normal" list is only a little more work than working with a nested one, but for bigger project these advantages start growing. – HilbertB Dec 09 '20 at 14:47