Tic Tac Toe
One of my friends challenged me to program a Tic-Tac-Toe game in as few lines as possible. I chose Python, my all time favorite language. With a little bit of work (and some really messy coding) I managed to get a working game written in 5 lines of Python.
arr = [[" "," "," "] for i in range(3)]
while ("x" if "xxx" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else "o" if "ooo" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else " ") == " ":
inputt = (input( '\n------\n'.join(["|".join(n) for n in arr]) + "\n" + ("o" if "".join(["".join(a) for a in arr]).count("x") > "".join(["".join(a) for a in arr]).count("o") else "x")+ "s turn\n"))
arr[int(inputt[0])][int(inputt[1])] = ("o" if str(arr).count("x") > str(arr).count("o") else "x") if arr[int(inputt[0])][int(inputt[1])]==" " else arr[int(inputt[0])][int(inputt[1])]
print('\n------\n'.join(["|".join(n) for n in arr]) + "\n" + ("x" if "xxx" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else "o" if "ooo" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else " ") + " wins! good game!")
There is no reason why this couldn’t have been done in dramatically less characters if I had rewritten it to check for the winner using a function instead of a one-liner I used twice in the code. However the challenge was line number based, not character based.
Here’s what the code does, line for line:
line 1: initialize the array
arr = [[" "," "," "] for i in range(3)]
Initialize the array to be a three by three array of all spaces.
line 2: loop while the game has not been won
while ("x" if "xxx" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else "o" if "ooo" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else " ") == " ":
I used a one liner to check if the game has been won or not. Basically it’s a ternary operator which checks if “xxx” or “ooo” is inside a string made from combining all elements in the array row by row, then column by column, then adding the diagonals.
line 3: Print the current grid and get input
inputt = (input( '\n------\n'.join(["|".join(n) for n in arr]) + "\n" + ("o" if "".join(["".join(a) for a in arr]).count("x") > "".join(["".join(a) for a in arr]).count("o") else "x")+ "s turn\n"))
Previously I had been printing off the grid after this step, but by combining that step with this one I saved one line. Pythons input function takes a string parameter to prompt the user, so why not print off the current game grid while asking the user for the next move?
line 4: Process the input
arr[int(inputt[0])][int(inputt[1])] = ("o" if str(arr).count("x") > str(arr).count("o") else "x") if arr[int(inputt[0])][int(inputt[1])]==" " else arr[int(inputt[0])][int(inputt[1])]
User input is in the form “RC” where R is the row and C is the column number they wish to move in. If the grid spot at that location is taken, it does not change it. That way one user can’t override the moves of another user.
line 5: Congratulate the winner!
print('\n------\n'.join(["|".join(n) for n in arr]) + "\n" + ("x" if "xxx" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else "o" if "ooo" in (" ".join(["".join([arr[b][a] for a in range(3)]) for b in range(3)]) + " " + " ".join(["".join([arr[a][b] for a in range(3)]) for b in range(3)]) + " " + arr[0][0]+arr[1][1]+arr[2][2] + " " + arr[2][0]+arr[1][1]+arr[0][2]) else " ") + " wins! good game!")
This step isn’t truly necessary, but I think a game is only really finished if the winner gets a message saying they won, otherwise it’s left a bit too ambiguous - did the game crash or did they really win? Granted for Tic-Tac-Toe, the user can tell pretty easily if they’ve won or not - it’s the principle that counts here. But I suppose the game could be written in as few as four lines if this was left off.
If you find a way to write this in fewer than five lines, I’d love to hear it!