How to fix tic-tac-toe two player bug - python

I am trying to make a tic-tac-toe game however when I try implement two players, the printed out result (current game state) is not as expected.
for example when I try to put the letter 'x' in box 1 it will add random letters/numbers in different spots. I have already tried this with only one player and it wrks perfectly.
import random
a = ' '
b = ' '
c = ' '
d = ' '
e = ' '
f = ' '
g = ' '
h = ' '
i = ' '
def gamestateboard(a, b, c, d, e, f, g, h, i):
x = [a, b, c]
y = [d, e, f]
z = [g, h, i]
print(x)
print(y)
print(z)
gamestateboard(a, b, c, d, e, f, g, h, i)
def checkwin():
if a == 0 and b == 0 and c == 0:
print('Winner')
if a == 0 and d == 0 and g == 0:
print('Winner')
if g == 0 and h == 0 and i == 0:
print('Winner')
if c == 0 and e == 0 and g == 0:
print('Winner')
if a == 0 and e == 0 and i == 0:
print('Winner')
if c == 0 and f == 0 and i == 0:
print('Winner')
for i in range(1000000):
inputs = str(input('Enter a position: '))
if i%2 == 0:
if inputs == '1':
a = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '2':
b = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '3':
c = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '4':
d = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '5':
e = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '6':
f = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '7':
g = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '8':
h = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '9':
i = 0
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
else:
if inputs == '1':
a = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '2':
b = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '3':
c = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '4':
d = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '5':
e = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '6':
f = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '7':
g = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '8':
h = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()
if inputs == '9':
i = 'X'
gamestateboard(a, b, c, d, e, f, g, h, i)
checkwin()

You are using i as your loop variable but also the name of a variable you use to draw in your game world.
I recommend moving away from having these variables and using indexes.
gameworld =[ [' ',' ',' '] for i in range(3)]
def draw_world():
for i in range(3):
print(gameworld[i])
then you can ask for coordinates or divide and use the modulus to use a single value like you did before. 4 // 3 = 1 4 % 3 = 1 position 4 is at [1][1]
This means you don't need your giant if input == list.
edit: Oh yeah you probably also want to do a loop with something like
no_winner = True
while no_winner:
...
you can set no_winner to False if check_win returns true and then you game doens't go on forever
edit 2:
Almost forgot you have an indenting error with the else for i%2==0 though I'm guessing that may be just from when you copied and pasted into your question. You also never check to see if someone else has already taken a square so when your code does actually work a player can overwrite another player's move.

Related

How to reduce multiple sets of possible character mappings?

I am running a slide attack on a cipher to determine the cipher's key. I want to know if there is an existing mathematical/programmatic-based representation I could use within this attack. Below is a list of mapping relationships compiled by comparing various outputs and their respective inputs. It reads as follows, where '->' is used to represent a mapping from the lhs to the rhs:
If b->d... then z->i AND q->f.
Likewise, if z->i AND q->f... then b->d.
Alphabet: 'abcdefghijklmnopqrstuvwxyz_'
Example key: 'uwmsqbhkc_pgvtilnyfexjzarod' (i.e. a shuffled alphabet)
c1 c2 c3 c4
===============
a: t, g | o, t
b: z, q | x, q
c: w, t | c, _
d: i, h | i, f
e: w, y | t, e
f: u, e | e, d
g: w, _ | y, m
h: n, m | z, d
i: i, j | h, f
j: l, h | r, g
k: w, b | t, v
l: r, c | e, b
m: l, u | z, e
n: r, i | x, y
o: g, s | e, a
p: t, f | z, w
q: u, r | z, r
r: s, a | p, o
s: t, _ | c, k
t: n, t | y, c
u: a, o | e, h
v: y, l | g, x
w: x, z | o, n
x: z, n | u, i
y: k, z | f, u
z: t, x | a, o
_: o, s | g, k
Additionally, the character frequencies of c1 and c2 MUST match the character frequencies of c3 and c4, respectively. In pseudo code, len(c1[freq1]) == len(c3[freq1]) and len(c2[freq2]) == len(c4[freq2]). Based on this, I have generated the following frequency "table" (a dictionary[freq: set(chars)] per column) where you can visually confirm this behavior:
c1: {4: {w, t}, 2: {u, i, r, l, z, n}, 1: {a, s, k, x, o, g, y}}
c3: {4: {e, z}, 2: {c, x, t, o, g, y}, 1: {u, i, r, a, f, p, h}}
c2: {2: {_, s, z, t, h}, 1: {n, m, q, b, u, i, r, a, c, f, l, x, e, j, o, g, y}}
c4: {2: {d, f, k, e, o}, 1: {y, n, m, q, b, u, i, a, _, r, c, x, w, v, g, t, h}}
This frequency table is what gives me a start on cracking the cipher. In the case of sets with a single character, we automatically learn the associated character mapping. Otherwise, we need to cross reference to learn mappings. The two methods I used to accomplish this are set intersections and set differences. For example, note that both c1[4] and c2[2] contain the character t. If we take the intersection of their potential mappings (i.e. c3[4] and c4[2]), we are left with the set {e} and thus t->e. Finding mappings via set differences is similar, so I won't give an example. Mappings found here can often be used to derive additional mappings from the first table.
In terms of this program, I am trying to find the best way to reduce the set of possibilities using physically-derived pieces of information via the methods above. Is there an existing mathematical/programmatic-based representation of this process? What's the proper name of this process? Additionally, are there more methods for extracting information that I'm not seeing?
Thanks!
-yuno

Simplify sympy integral expressions

With
x, a, b, c = symbols ('x a b c')
f = Function ('f') (x)
is there a way to simplify
integrate (f, (x, a, b)) + integrate (f, (x, b, a))
and
integrate (f, (x, a, c)) + integrate (f, (x, c, b)) - integrate (f, (x, a, b))
to zero?
Reference: https://en.wikipedia.org/wiki/Integral#Conventions
The first case can be handled by using a traversal that puts the limits in canonical order:
def iss(i):
if isinstance(i, Integral):
s = 1
lim = list(i.limits)
for j, xab in enumerate(lim):
if len(xab) == 3:
x, a, b = xab
if [a,b]!=list(ordered([a,b])):
lim[j] = (x, b, a)
s *= -1
return i.func(i.function, lim).simplify()*s
return i
>>> eq = integrate (f, (x, a, b)) + integrate (f, (x, b, a))
>>> bottom_up(eq, iss)
0
For the second case there are lots of possible expressions to deal with. But to deal with the type you have shown perhaps the following will work:
def collapse_integrals(a):
from collections import defaultdict
if not a.is_Add: return a
i, d = a.as_independent(Integral)
if not d.is_Add:
return a
if i:
return i + collapse_integrals(d)
igls = defaultdict(list)
other = []
for ai in a.args:
c, i = ai.as_independent(Integral, as_Add=False)
if abs(c) != 1:
other.append(ai)
continue
if not isinstance(i,Integral) or not (len(i.limits) == 1 and len(i.limits[0])==3):
other.append(ai)
else:
igls[(c, i.function)].append(i.limits[0][1:])
for k in igls:
if len(igls[k]) > 1:
n = len(igls[k])
lims = igls[k]
cond = []
nul = (None, None)
for i in range(n):
if lims[i] == nul:continue
for j in range(i + 1, n):
if lims[i][0] == lims[j][1]:
cond.append((lims[j][0],lims[i][1]))
elif lims[i][1] == lims[j][0]:
cond.append((lims[i][0],lims[j][1]))
else:
continue
lims[i] = lims[j] = nul
if cond:
igls[k] = cond + [i for i in lims if i != nul]
c, f = k
other.extend([c*Integral(f, l) for l in igls[k]])
return Add(*other)
>>> eq = integrate (f, (x, a, c)) + integrate (f, (x, c, b)) - integrate (f, (x, a, b))
collapse_integrals(bottom_up(eq,iss))
0

Equation in MATLAB and Python given different result

Currently I'm translating my MATLAB code to Python version,
function u = afterslip(A, B, C, D, E, X, Ta, Tb, Tc)
u = A*log(1+X/Ta) + B + C*log(1+X/Tb) - D*exp(-X/Tc) + E;
end
to:
from math import log,exp
def afterslip(A, B, C, D, E, Ta, Tb, Tc):
e = A*log(1+X/Ta) + B + C*log(1+X/Tb) - D*exp(-X/Tc) +
return e
But when I calculated using X=187, Ta=8, Tb=80, Tc=600, A=-27, B=-18, C=56, D=-71, and E=-18 both given different result. Anyone knows why this happened and how to fix it?
The second function misses argument X. See below.
def afterslip(A, B, C, D, E, X, Ta, Tb, Tc):
return A*log(1+X/Ta) + B + C*log(1+X/Tb) - D*exp(-X/Tc) + E

Specific Character Pattern Python

I am trying to achieve the following;
Write a program that produces the following output giving an integer input n.
The result should be the following;
n=1 n=2 n=3 n=4
+ A+B AA+BB AAA+BBB
+E+ A+E+B AA+E+BB
C+D +EEE+ A+EEE+B
C+E+D +EEEEE+
CC+DD C+EEE+D
CC+E+DD
CCC+DDD
I am having issues solving this problem.
When I enter 2 I am currently getting the following but unable how to make it look like the above.
Current result;
A+
B+
E+
C+
D
Here is my code;
def specific_pattern(n):
addition = "+"
alp = "A, B, E, C, D"
# myList = ["A, B, C, D, E"]
newList = []
for j in range(0, n):
for i in range(0, j):
if n == 1:
print(addition)
else:
letters = alp.split(", ")
for letter in range(len(letters)):
newList.append(letters[letter]*j+addition)
newchar = "".join(newList)
print(newchar[:-1])
n = int(input("Enter a number: "))
specific_pattern(n)
You can use simple iteration to create both the top and bottom of the desired diamond:
def sequence(d):
c, l = 0, 1
while c < d - 1:
if l%2:
yield l
c += 1
l += 1
def make_pattern(d):
t, b, r = f'{"A"*(d-1)}+{"B"*(d-1)}', f'{"C"*(d-1)}+{"D"*(d-1)}', list(sequence(d))
body = '\n'.join(f'{"A"*((r[-1]-i)//2)}+{"E"*i}+{"B"*((r[-1]-i)//2)}' for i in r[:-1]) + \
f'\n+{"E"*r[-1]}+\n'+'\n'.join(f'{"C"*((r[-1]-i)//2)}+{"E"*i}+{"D"*((r[-1]-i)//2)}' for i in r[:-1][::-1])
return f'{t}\n{body}\n{b}'
def diamond(d):
return {1:lambda _:'+', 2:lambda _:'A+B\n+E+\nC+D'}.get(d, make_pattern)(d)
print(diamond(3))
print('-'*5)
print(diamond(4))
Output:
AA+BB
A+E+B
+EEE+
C+E+D
CC+DD
-----
AAA+BBB
AA+E+BB
A+EEE+B
+EEEEE+
C+EEE+D
CC+E+DD
CCC+DDD

whats wrong with this while loop in Python?

Ok so I have spent hours trying to resolve this and I feel its some simple error but I cannot find a way to resolve this.
the section I am having issues with is the second half of the code. There seems to be an infinite loop somewhere among the 2 nested while loops. If anyone is able to help, this would be great, thanks in advance.
import sympy as sym
import random
A, B, C, D, E, F, G, H, I, J = sym.symbols('A, B, C, D, E, F, G, H, I, J')
picks_a_person = [A, B, C, D, E, F, G, H, I, J] #List of people picking a name from a hat
person_gets_picked = [A, B, C, D, E, F, G, H, I, J] # List of names drawn from a hat
def re_draws(p):
n = 0
count = 0
while n < 1000: #Repeats the test 1000 times for an accurate percentage
n += 1
random.shuffle(person_gets_picked) #Chooses a random order of the list of names drawn
for i in range(p):
if person_gets_picked[i] == picks_a_person[i]: #Checks for all 'p' elements of the lists are different
count = count + 1
print("count = " + str(count)) #Returns the number of times a re-draw was not required
import numpy as np
from collections import Counter
total = []
while len(total) < 1000:
order = []
picks_a_person = [A, B, C, D, E, F, G, H, I, J]
person_gets_picked = [A, B, C, D, E, F, G, H, I, J]
while len(order) < 10:
a = person_gets_picked[random.randint(0, (len(person_gets_picked)-1))]
if a != picks_a_person[0]:
order.append(a)
person_gets_picked.remove(a)
del picks_a_person[0]
total.append(order)
Counter(np.array(total)[:,1])
While there are a lot of odd things about your code, this is where it gets into an infinite loop:
picks_a_person = [A, B, C, D, E, F, G, H, I, J]
person_gets_picked = [A, B, C, D, E, F, G, H, I, J]
while len(order) < 10:
a = person_gets_picked[random.randint(0, (len(person_gets_picked)-1))]
if a != picks_a_person[0]:
order.append(a)
person_gets_picked.remove(a)
del picks_a_person[0]
total.append(order)
Let's do some rubber duck debugging - what happens when your random.randint(0, (len(person_gets_picked)-1)) returns a number larger than 0 nine times in a row (worst case scenario)? All person_gets_picked elements except A get removed and added to the order list (which is still under 10 elements to break away from the while loop).
At that point we have a state as picks_a_person = [A] and person_gets_picked = [A]. random.randint(0, (len(person_gets_picked)-1)) will, thus, always return 0, a will always be set to A and since picks_a_person[0] == A the condition if a != picks_a_person[0] will never be evaluated as True, hence the order will never get its 10th element and therefore you got yourself an infinite loop.
It doesn't even have to be nine positive numbers in a row for this to occur - all it needs to happen is for A to remain as one of the last two picks and for random to land on the other option.
So why don't you write your whole loop as:
persons = [A, B, C, D, E, F, G, H, I, J]
persons_num = len(persons)
total = [random.sample(persons, persons_num) for _ in range(1000)]
And you're done.

Categories