How to code win/tie conditions in TicTacToe game in python - python-3.x

I have made the main-game mechanics for the TicTacToe game; however, I don't know a way to code the end-game win conditions, i.e. How to find when someone wins/ties.
I tried using the all() function, but either this did not work, or I used it incorrectly (probably the latter).
Here is the full code, and the list of variables for the code (as there are no comments):
def get_grid():
r1 = ['-','-','-']
r2 = ['-','-','-']
r3 = ['-','-','-']
return r1, r2, r3
def get_coords():
x = 0
y = 0
while True:
try:
x = int(input("x coord : "))
y = int(input("y coord : "))
except ValueError:
print("Must be an integer")
if x < 0 or x > 3 or y < 0 or y > 3:
print('Both values must be in the grid!')
else:
break
return x, y
def pgrid(x, y, r1, r2, r3, player):
rdict = {1:r1, 2:r2, 3:r3}
if x != 0 and y != 0:
while True:
if rdict[y][x-1] == '-':
rdict[y][x-1] = player
break
else:
print("Invalid Space!")
x, y = get_coords()
print('\t1\t2\t3')
print(' 1 |', end = '\t')
for i in r1:
print(i, end = ' | ')
print()
print(' 2 |', end = '\t')
for i in r2:
print(i, end = ' | ')
print()
print(' 3 |', end = '\t')
for i in r3:
print(i, end = ' | ')
print()
def main():
r1, r2, r3 = get_grid()
players = ['X', 'O']
pgrid(0, 0, r1, r2, r3, None)
win = False
while win == False:
for i in players:
x, y = get_coords()
pgrid(x, y ,r1 ,r2 , r3, i)
Variables
r1, r2 and r3 are the first, second, and third rows for the board. List
x and y are the coordinates where the 'X' or 'O' is placed. Integer
rdict navigates between the y value entered and the row of the board. Dictionary
player is the player. String
players is a List of the players ('X' and 'O')
win is true when a player has won / the game has tied. Boolean
The win variable is what needs to change in answers to this question, I just need the code or at least an idea on how to code it (because I don't have any!).
Thanks in advance!

What's the simplest way to check if three of the same letters are in a row or column? For the first column take r1[0], r2[0] and r3[0] and check if they all contain the same letter:
if r1[0] == 'X' and r2[0] == 'X' and r3[0] == 'X':
print('First column meets victory conditions', 'X')
Now it would be a bit cumbersome to do this for all rows and columns and both letters, but fortunately we can just let some for loops do the work for us.
for letter in 'XO':
for i in range(3):
if r1[i] == letter and r2[i] == letter and r3[i] == letter:
print('Column', i, letter)
For the rows just iterate over (r1, r2, r3) instead of the range(3) and check:
if row[0] == letter and row[1] == letter ...
And of course you can also use the all function and a list comprehension or generator expression to see if all letters are equal.
for row in (r1, r2, r3):
if all(item == letter for item in row):

You can try my function :
def check_who_won(board):
for letter in 'xo':
if all(col == letter for row in board for col in row):
return True
for col in range(3):
if all(board[row, col] == letter for row in range(3)):
return True
if (board[2, 0] and board[1, 1] and board[0, 2]) in letter:
return True
if all(board[index, index] == letter for index in range(3)):
return True
return False

Related

Counting weighted average doesn't work properly sometimes

I've made a program that counts weighted average and required weighted value to average being equal to our preference. If I want the average be equal to 85 from (the first value in the list is the weight of next values) [[4,72,78],[3,56],[6,93]] and x value of 6 weight it does not output the right value.
def choice(x):
c = 0
Choice = True
choices = []
while Choice:
if choices == []:
if x != 0:
fill = "weight of required value"
else:
fill = "weight of next values"
else:
if x != 0:
fill = "value of wanted weighted average"
else:
fill = "value"
try:
c = input("Give {}\n" .format(fill))
except:
continue
if isinstance(c, str):
if c == "":
Choice = False
if choices == []:
choices = False
break
else:
try:
choices.append(float(c))
except:
continue
if x != 0 and len(choices) == x:
break
c = 0
return choices
def av(x):
c = 0
alist = x[:]
alist.pop(0)
for a in alist:
c += a*x[0]
return c
def average(k,args):
c = 0
n = 0
for y in range(len(args)):
for a in range(len(args)):
c += (av(args[a]))/2
for b in range(len(args)):
n += (args[b][0]*(len(args[b])-1))/2
if k == 1:
return ([float("{0:.2f}".format(c/n)),c,n])
else:
j = float("{0:.2f}".format(c/n))
print("Weighted average {} from {}" .format(j,args))
def rmark(q,args):
alist = average(1,args)
a = float("{:.2f}" .format((((q[1]*(alist[2]+q[0]))-alist[1])/q[0])))
print("To get weighted average {}, u have to add the value equal to {} of weight {}" .format(q[1],a,q[0]))
# return a
Continue = True
list_choices = []
while Continue:
x = 0
x = choice(0)
if isinstance(x, list):
list_choices.append(x)
elif x == False:
break
print(list_choices)
rmark(choice(2),list_choices)
average(0,list_choices)
Let me break it down for you.
av function is reducing the size of your lists (x1, x2 and x3) to 1 by popping (alist.pop(0)) one element.
Hence, value of len(x1)-1 is 0, which means value of all multipliers in the denominator of (av(x1) + av(x2) + av(x3))/((x1[0]*(len(x1)-1)) + (x2[0]*(len(x2)-1)) + (x3[0]*(len(x3)-1))) is 0. Thus, the error divide by zero.

Issues with 'movement' across multi-dimensional array, text-based game

I'm currently messing around with the code right now to solve some issues in movement. Ideally, i want to be able to move the character to any spot in the array(worldMap) containing ' ', and marking the player's position with 'P'.
I'm lost to what the issue I am running into is, and some of the issues I am running into are as follows...
- when I move E it always goes to worldMap[3][3]
- N only moves up from worldMap[3][x] to worldMap [2][x]
- S doesn't work
Below is my current code...
import math
import random
import sys
import os
import time
gameplay= True
#world map lay out, X--> wall, player can't go that way. ' ', possible area for player to move, 'P', player indicator.
worldMap = [['X','X','X','X','X'],
['X',' ',' ',' ','X'],
['X',' ',' ',' ','X'],
['X','P',' ',' ','X'],
['X','X','X','X','X']]
west=str("w" or "W")
east=str("e" or "E")
north=str('n' or 'N')
south=str('s' or 'S')
for row in worldMap:
for column in row:
print(column, end=' ')
print()
while gameplay == True:
x=str((input("\nWhat direction would you like to move?\n ")))
if x==west:
for row in worldMap:
for i, column in enumerate(row):
if column == 'P':
if((i>0) and (i<4) and row[i-1]) == ' ':
row[i-1] = 'P'
row[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
elif x==east:
for row in worldMap:
for i, column in enumerate(row):
if column == 'P':
if((i>0) and (i<4) and row[i+1]) == ' ':
row[i+1] = 'P'
row[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
elif x == north: #move north
for column in worldMap:
for i, row in enumerate(column):
if row == 'P':
if((i>0) and (i<4) and column[i-1]) == ' ':
column[i-1] = 'P'
column[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
elif x== south: #move south
for column in worldMap:
for i, row in enumerate(column):
if column == 'P':
if((i>0) and (i<4) and column[i+1]) == ' ':
column[i+1] = 'P'
column[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
else:
for row in worldMap:
for column in row:
print(column, end=' ')
print()
print("\nCan't do that.\n")
I have tided up your code a bit. A good clue to needing to refactor your code is if you have written the same thing alot in your code. In those cases its better to write a function and then call the function from your code. The below code is just an example to help set you on the right path.
In this example instead of scanning the whole map for the player, i just keep track of the players position and calculate the new position and if its a space then move the player. We can easily move the player by adding or subtracting 1 to the x or y co-ordinate of the player.
I also cleaned up the print map function and its now only called at the start of each loop.
from random import randint
def generate_map(size):
# world map lay out, X--> wall, player can't go that way. ' ', possible area for player to move, 'P', player indicator.
world_map = [[wall for _ in range(size)]]
for i in range(1, size - 1):
world_map.append([wall])
for j in range(1, size - 1):
#generate random walls in our map (currently set to genearete spaces 90% of the time
if randint(1,100) < 90:
world_map[i].append(space)
else:
world_map[i].append(wall)
world_map[i].append(wall)
world_map.append([wall for _ in range(size)])
return world_map
def print_map():
for row in worldMap:
print(" ".join(row))
def move_player():
x, y = player_position
if direction == "W":
y -= 1
elif direction == "E":
y += 1
elif direction == "N":
x -= 1
elif direction == "S":
x += 1
if worldMap[x][y] == space:
worldMap[player_position[0]][player_position[1]] = space
worldMap[x][y] = player
player_position[0] = x
player_position[1] = y
else:
print("Cannot more there")
#Genearte a map and position the player
wall, space, player = "X", " ", "P"
map_size = 10
worldMap = generate_map(map_size)
player_position = [1, 1]
worldMap[player_position[0]][player_position[1]] = player
#Run the game
gameplay = True
while gameplay:
print_map()
direction = input("\nWhat direction would you like to move? ").upper()
if direction:
move_player()
else:
break

Why aren't the values from my arrays passing though my full bit adder

# 8-bit-binary adder
#if you have questions about the code just ask
# arrays and funtions
Array1 = []
Array2 = []
#Input A and Validation
def vaildNumberA():
a = int(input("Enter your A value:"))
if (a < 0):
print("Please Enter A Valid Number For Input A")
elif (a > 255):
print("Please Enter A Valid Number For Input A")
else:
Array1 = [int(x) for x in list('{0:08b}'.format(a))]
#Input B and Validation
def vaildNumberB():
b = int(input("Enter your B value:"))
if (b < 0):
print("Please Enter A Valid Number For Input B")
elif (b > 255):
print("Please Enter A Valid Number For Input B")
else:
Array2 = [int(x) for x in list('{0:08b}'.format(b))]
# and gate
# AND Gate
def AND (a,b):
if (a == 1 and b == 1):
return 1
else:
return 0
# or gate
#OR Gate
def OR(a,b):
if (a == 1 or b == 1):
return 1
else:
return 0
# XOR GATEE
#XOR Gate
def XOR (a,b):
if (a == b):
return 0
else:
return 1
#carry formula
def carryformula(a,b,c,d):
return OR(AND(a,b), AND(c,d))
# this is where the calculation should be done
#formula for sum
def calculateSum(Array1,Array2):
carry = ""
sumof = []
for index, in range(len(Array1)):
list2 = Array2[index]
sec_xor_form = XOR(Array1[index],Array2[index])
sumof.append(XOR(sec_xor_form,carry))
carry = carryformula(Array1[index],Array2[index],sec_xor_form,carry)
return list(reversed(sumof))
calculateSum(Array1,Array2)
def main(Array1,Array2):
vaildNumberA()
vaildNumberB()
while True:
a = Array1
b = Array2
total = calculateSum(list(reversed(Array1)),list(reversed(Array2)))
print(total)
quit = input("if want to quit type q: ")
if quit == 'q':
break
main(Array1,Array2)
in the send it prints 0
The only problem in your code is that you need to return Array1 and Array2 from your functions and assign them inside the while true loop, once you do that the code works fine.
The updated code will be
# 8-bit-binary adder
#if you have questions about the code just ask
# arrays and funtions
Array1 = []
Array2 = []
#Input A and Validation
def vaildNumberA():
Array1 = []
a = int(input("Enter your A value:"))
if (a < 0):
print("Please Enter A Valid Number For Input A")
elif (a > 255):
print("Please Enter A Valid Number For Input A")
else:
Array1 = [int(x) for x in list('{0:08b}'.format(a))]
#Return the array
return Array1
#Input B and Validation
def vaildNumberB():
Array2 = []
b = int(input("Enter your B value:"))
if (b < 0):
print("Please Enter A Valid Number For Input B")
elif (b > 255):
print("Please Enter A Valid Number For Input B")
else:
Array2 = [int(x) for x in list('{0:08b}'.format(b))]
#Return the array
return Array2
# AND Gate
def AND (a,b):
if (a == 1 and b == 1):
return 1
else:
return 0
#OR Gate
def OR(a,b):
if (a == 1 or b == 1):
return 1
else:
return 0
#XOR Gate
def XOR (a,b):
if (a == b):
return 0
else:
return 1
#carry formula
def carryformula(a,b,c,d):
return OR(AND(a,b), AND(c,d))
# this is where the calculation should be done
#formula for sum
def calculateSum(Array1,Array2):
carry = ""
sumof = []
for index in range(len(Array1)):
list2 = Array2[index]
sec_xor_form = XOR(Array1[index],Array2[index])
sumof.append(XOR(sec_xor_form,carry))
carry = carryformula(Array1[index],Array2[index],sec_xor_form,carry)
return list(reversed(sumof))
#No need of a main function
while True:
#Call the function from within the while True loop
Array1 = vaildNumberA()
Array2 = vaildNumberB()
total = calculateSum(list(reversed(Array1)),list(reversed(Array2)))
print(total)
quit = input("if want to quit type q: ")
if quit == 'q':
break
And the output will look like
Enter your A value:5
Enter your B value:5
[0, 0, 0, 0, 1, 0, 1, 1]
if want to quit type q: 7
Enter your A value:9
Enter your B value:8
[0, 0, 0, 1, 0, 0, 0, 1]
....

How can I update my number in while loop? (Number guessing game)

I am going to write a guessing game with the computer.
I choose one number in my head and the Computer is going to find it out, and it can guess between a range.
The problem is I don’t know how can I update this range during the program run.
import random
x = 1
y = 99
guess= random.randint(x,y)
print(guess)
play='true'
while play=='true':
a=x
b=y
results = input()
if results == 'd':
play='false'
else:
if results == 'b':
a=guess
print('My number is bigger!')
newguess= random.randint(a,b)
print (newguess)
elif results == 'k':
b=guess
print('My number is smaller!')
newguess= random.randint(a,b)
print (newguess)
print ('Wooow , computer you did it! ')
Sorry about all the explanations in the code but this is a version of the game that I did a while ago. What I did was I wanted to shrink the guessing range each time the user said high or low. e.g. if the computer chooses 50, and the user says 'High' then the program will not chose a number greater than 50, the same applies for 'Low". Enjoy
import random
count = 0 #Number of attemps. how many times while loop runs.
guess = random.randint(1,100)#The guess generator
(l,u) = (0,100)
lower_guess = l
upper_guess = u
n = 0
print('Chose a number between ', l, ' and ', u , '.' )
#The game. These are outside the function so that they don't print in every loop because they are unwanted for some Y inputs.
print('Is it ' + str(guess))
Y = input('Low = L, High = H and Yes = Y:')#User states
#The function
while n != 'guess':
count +=1 #adds 1 to count each time loop runs
if Y == 'L':
lower_guess = guess+1
guess = random.randint(lower_guess , upper_guess)#Redifining guess to eliminate irrelevant guesses from the range
print('Is it ' + str(guess))
Y = input('Low = L, High = H and Yes = Y:')
elif Y == 'H':
upper_guess = guess - 1
guess = random.randint(lower_guess, upper_guess)#Redifining guess to eliminate irrelevant guesses from the range
print('Is it ' + str(guess))
Y = input('Low = L, High = H and Yes = Y:')
elif Y == 'Y':
print('I guessed it in ' + str(count) + ' attempts')
break
else:
count = 0
lower_guess = l
upper_guess = u
guess = random.randint(1,100)
print('That input was invalid. The game has restarted.')
print('You can chose a new number or keep your old one.')
print('Is it ' + str(guess))
Y = input('Low = L, High = H and Yes = Y:')

Connect 4 Like Game

I am making a connect four like game in python, what I have so far is creating the board and implementing game play against the computer. I am running into the issue that does not allow me to play past the second row. Any ideas on why?
#Define the board
row = int(input("Please enter # of rows: ")) #User input Rows
column = int(input("Please enter # of columns: ")) #User input Columns
board = [] #empty board
space = ' '
p1 = 'x'
p2 = 'o'
#create board based on user input
for i in range(0,row):
board.append([])
for j in range(0, column):
board[i].append(space)
print(board)
#print board with character decorations
for i in board:
line=''
print('+'+'-+'*len(i))
for j in range(len(i)):
line = line + '|'+i[j]
line = line + '|'
print(line)
print('+'+'-+'*len(i))
print(len(board))
while True:
#User input column
myC = int(input("Player 1, choose your column: "))
i = len(board)-1
x = len(board)-1
while i >= 0:
if board[x][myC] == space:
i = i+1
board[x][myC] = 'x'
break
elif board[x][myC] == p1 or p2:
i = i+1
x = x - 1
print(x)
board[x][myC] = 'x'
break
# print the board!
for i in board:
line=''
print('+'+'-+'*len(i))
for j in range(len(i)):
line = line + '|'+i[j]
line = line + '|'
print(line)
print('+'+'-+'*len(i))
#Computer input column
from random import randint
theC = randint(0, len(board)-1)
print("Computer's Turn: Column " , theC)
i = len(board)-1
x = len(board)-1
while i >= 0:
if board[x][theC] == space:
board[x][theC] = 'o'
i = i+1
break
elif board[x][theC] == p1 or p2:
i = i+1
x = x - 1
print(x)
board[x][theC] = 'o'
break
# print the board!
for i in board:
line=''
print('+'+'-+'*len(i))
for j in range(len(i)):
line = line + '|'+i[j]
line = line + '|'
print(line)
print('+'+'-+'*len(i))
I believe I figured out what's going on. Your x is always initialized to len(board)-1 and then if the space is occupied it is reduced by one. If you make a (>2)x(>2) board and row 0 is occupied then this will always force x = 2.
This is close to correct, but what you actually need is to iterate through all rows until you find the first unoccupied row. I created a loop that will find the first row and assign that to the value of x. I tested it out and I'm now able to play passed 2 rows.
#Define the board
row = int(input("Please enter # of rows: ")) #User input Rows
column = int(input("Please enter # of columns: ")) #User input Columns
board = [] #empty board
space = ' '
p1 = 'x'
p2 = 'o'
#create board based on user input
for i in range(0,row):
board.append([])
for j in range(0, column):
board[i].append(space)
print(board)
#print board with character decorations
for i in board:
line=''
print('+'+'-+'*len(i))
for j in range(len(i)):
line = line + '|'+i[j]
line = line + '|'
print(line)
print('+'+'-+'*len(i))
print(len(board))
while True:
#User input column
myC = int(input("Player 1, choose your column: "))
i = len(board)-1
x = len(board)-1
while i >= 0:
if board[x][myC] == space:
i = i+1
board[x][myC] = 'x'
break
# Find last empty row for new piece
elif board[x][myC] == p1 or p2:
for j in range(x-1,-1,-1):
if board[j][myC] == space:
x = j
break
i = i+1
#x = x - 1
print(x)
board[x][myC] = 'x'
break
# print the board!
for i in board:
line=''
print('+'+'-+'*len(i))
for j in range(len(i)):
line = line + '|'+i[j]
line = line + '|'
print(line)
print('+'+'-+'*len(i))
#Computer input column
from random import randint
theC = randint(0, len(board)-1)
print("Computer's Turn: Column " , theC)
i = len(board)-1
x = len(board)-1
while i >= 0:
if board[x][theC] == space:
board[x][theC] = 'o'
i = i+1
break
# Find last empty row for new piece
elif board[x][theC] == p1 or p2:
for j in range(x-1,-1,-1):
if board[j][theC] == space:
x =j
break
i = i+1
#x = x - 1
print(x)
board[x][theC] = 'o'
break
# print the board!
for i in board:
line=''
print('+'+'-+'*len(i))
for j in range(len(i)):
line = line + '|'+i[j]
line = line + '|'
print(line)
print('+'+'-+'*len(i))

Resources