-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathttt.py
196 lines (147 loc) · 4.85 KB
/
ttt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import random
from browser import window
from browser.html import *
class Tile(DIV):
def __init__(self, text, x=0, y=0, width=0, height=0, display='inline',
opacity=1, axis=('left', 'top'), font_size='24px', **kw):
for k, v in (
(axis[0], x), (axis[1], y),
('width', width), ('height', height),
('display', display), ('opacity', opacity),
('box-sizing', 'border-box'), ('position', 'absolute')):
self.style[k] = v
super().__init__(DIV(text,
style={
'position': 'absolute',
'left': '50%', 'top': '50%',
'transform': 'translate(-50%, -50%)',
'font-size': font_size}))
@property
def text(self):
return self.children[0].text
@text.setter
def text(self, value):
self.children[0].text = value
def popup(root, width='auto', height='auto'):
if isinstance(root, (tuple, list, str, int, float, set, dict)):
root = DIV(root)
d = DIALOG(root)
root.style['width'] = width
root.style['height'] = height
def on_click(ev):
d.remove()
d.bind('close', on_click)
doc <= d
d.showModal()
return d
#---------------------------------
# nims
tile_size = 500/5
# 5 random 2 to 5 long heaps
stacks = {x:
Tile('|', width=tile_size, height=tile_size,
x=x[0]*tile_size, y=x[1]*tile_size)
for x in (((j, i) for j in range(random.randint(2, 5))) for i in range(5)) for x in x}
# bind click events
def on_click(ev):
# find index of clicked element
idx = next(k for k, v in stacks.items() if ev.target.inside(v))
# remove the clicked one on to the end of the row
for i in range(idx[0], 5):
if (i, idx[1]) not in stacks:
break
stacks[i, idx[1]].remove()
del stacks[i, idx[1]]
# if you remove the last stick, you lose
if not stacks:
window.alert('You lose')
for i in stacks.values():
i.bind('click', on_click)
popup(list(stacks.values()), 500, 500)
# tic tac toe
# Check pattern for possible wins.
check_pattern = ((0, 4, 8), (2, 4, 6), (0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8))
width = 3
tile_size = 500/3
grid = tuple(
Tile('', height=tile_size, width=tile_size,
x=i%width*tile_size, y=i//width*tile_size)
for i in range(9)) # 9 tiles in the game
turns = ['x', 'o'] # these flip as the turns go by
done = []
def on_click(ev):
if done: # if done, stop
return
idx = next(idx for idx, i in enumerate(grid) if ev.target.inside(i))
target = grid[idx]
if target.text: # if tile taken, stop
return
# set text of UI element, then change turns
target.text = turns[0]
turns[:] = turns[1], turns[0]
# check for win
for i in check_pattern:
if grid[i[0]].text and grid[i[0]].text == grid[i[1]].text == grid[i[2]].text:
window.alert(f'{turns[1]} has won!')
done.append(True) # the game is over, no more playing
for i in grid:
i.bind('click', on_click)
popup(grid, 500, 500)
# ---
# war
#cards
import random
class Card:
__slots__ = 'face', 'suit', 'value'
def __init__(self, face, suit, value):
self.face, self.suit, self.value = face, suit, value
class Player:
__slots__ = 'name', 'cards', 'deck'
def __init__(self, name, cards, deck):
self.name, self.cards, self.deck = name, cards, deck
def draw(player, count=1):
player.cards.extend(player.deck[:count])
del player.deck[:count]
player_count = 3
players = [Player(f'p{i+1}', [], []) for i in range(player_count)]
deck = [Card(f, s, fi*100+si)
for fi, f in enumerate(('ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jack', 'queen', 'king'))
for si, s in enumerate(('clubs', 'diamonds', 'hearts', 'spades'))]
random.shuffle(deck)
card_count = len(deck)//player_count
for i in players:
i.deck = deck[:card_count]
del deck[:card_count]
# put remainder of deck into player 1
if deck:
players[0].deck.extend(deck)
MAX_ROUNDS = 1000
round = 0
while round < MAX_ROUNDS:
round += 1
if not round%25:
for i in players:
random.shuffle(i.deck)
# draw card to each player
for p in players:
draw(p)
# only draw 3 once, and if all players tie
if len(set(i.cards[-1].face for i in players)) == 1:
for p in players:
draw(p, 3)
winner = max(players, key=lambda i: i.cards[-1].value)
for i in players:
winner.deck.extend(i.cards)
for i in players:
i.cards.clear()
loser = [i for i in players if not i.deck]
if loser:
for i in loser:
print(f'{i.name} has lost')
players.remove(i)
if len(players) == 1:
print(f'{players[0].name} has won.')
break
print(winner.name, [(len(i.deck), i.name) for i in players])
else:
print(f'No winner after {MAX_ROUNDS} rounds')