ยปCore Development>Code coverage>Lib/turtledemo/nim.py

Python code coverage for Lib/turtledemo/nim.py

#countcontent
1n/a""" turtle-example-suite:
2n/a
3n/a tdemo_nim.py
4n/a
5n/aPlay nim against the computer. The player
6n/awho takes the last stick is the winner.
7n/a
8n/aImplements the model-view-controller
9n/adesign pattern.
10n/a"""
11n/a
12n/a
13n/aimport turtle
14n/aimport random
15n/aimport time
16n/a
17n/aSCREENWIDTH = 640
18n/aSCREENHEIGHT = 480
19n/a
20n/aMINSTICKS = 7
21n/aMAXSTICKS = 31
22n/a
23n/aHUNIT = SCREENHEIGHT // 12
24n/aWUNIT = SCREENWIDTH // ((MAXSTICKS // 5) * 11 + (MAXSTICKS % 5) * 2)
25n/a
26n/aSCOLOR = (63, 63, 31)
27n/aHCOLOR = (255, 204, 204)
28n/aCOLOR = (204, 204, 255)
29n/a
30n/adef randomrow():
31n/a return random.randint(MINSTICKS, MAXSTICKS)
32n/a
33n/adef computerzug(state):
34n/a xored = state[0] ^ state[1] ^ state[2]
35n/a if xored == 0:
36n/a return randommove(state)
37n/a for z in range(3):
38n/a s = state[z] ^ xored
39n/a if s <= state[z]:
40n/a move = (z, s)
41n/a return move
42n/a
43n/adef randommove(state):
44n/a m = max(state)
45n/a while True:
46n/a z = random.randint(0,2)
47n/a if state[z] > (m > 1):
48n/a break
49n/a rand = random.randint(m > 1, state[z]-1)
50n/a return z, rand
51n/a
52n/a
53n/aclass NimModel(object):
54n/a def __init__(self, game):
55n/a self.game = game
56n/a
57n/a def setup(self):
58n/a if self.game.state not in [Nim.CREATED, Nim.OVER]:
59n/a return
60n/a self.sticks = [randomrow(), randomrow(), randomrow()]
61n/a self.player = 0
62n/a self.winner = None
63n/a self.game.view.setup()
64n/a self.game.state = Nim.RUNNING
65n/a
66n/a def move(self, row, col):
67n/a maxspalte = self.sticks[row]
68n/a self.sticks[row] = col
69n/a self.game.view.notify_move(row, col, maxspalte, self.player)
70n/a if self.game_over():
71n/a self.game.state = Nim.OVER
72n/a self.winner = self.player
73n/a self.game.view.notify_over()
74n/a elif self.player == 0:
75n/a self.player = 1
76n/a row, col = computerzug(self.sticks)
77n/a self.move(row, col)
78n/a self.player = 0
79n/a
80n/a def game_over(self):
81n/a return self.sticks == [0, 0, 0]
82n/a
83n/a def notify_move(self, row, col):
84n/a if self.sticks[row] <= col:
85n/a return
86n/a self.move(row, col)
87n/a
88n/a
89n/aclass Stick(turtle.Turtle):
90n/a def __init__(self, row, col, game):
91n/a turtle.Turtle.__init__(self, visible=False)
92n/a self.row = row
93n/a self.col = col
94n/a self.game = game
95n/a x, y = self.coords(row, col)
96n/a self.shape("square")
97n/a self.shapesize(HUNIT/10.0, WUNIT/20.0)
98n/a self.speed(0)
99n/a self.pu()
100n/a self.goto(x,y)
101n/a self.color("white")
102n/a self.showturtle()
103n/a
104n/a def coords(self, row, col):
105n/a packet, remainder = divmod(col, 5)
106n/a x = (3 + 11 * packet + 2 * remainder) * WUNIT
107n/a y = (2 + 3 * row) * HUNIT
108n/a return x - SCREENWIDTH // 2 + WUNIT // 2, SCREENHEIGHT // 2 - y - HUNIT // 2
109n/a
110n/a def makemove(self, x, y):
111n/a if self.game.state != Nim.RUNNING:
112n/a return
113n/a self.game.controller.notify_move(self.row, self.col)
114n/a
115n/a
116n/aclass NimView(object):
117n/a def __init__(self, game):
118n/a self.game = game
119n/a self.screen = game.screen
120n/a self.model = game.model
121n/a self.screen.colormode(255)
122n/a self.screen.tracer(False)
123n/a self.screen.bgcolor((240, 240, 255))
124n/a self.writer = turtle.Turtle(visible=False)
125n/a self.writer.pu()
126n/a self.writer.speed(0)
127n/a self.sticks = {}
128n/a for row in range(3):
129n/a for col in range(MAXSTICKS):
130n/a self.sticks[(row, col)] = Stick(row, col, game)
131n/a self.display("... a moment please ...")
132n/a self.screen.tracer(True)
133n/a
134n/a def display(self, msg1, msg2=None):
135n/a self.screen.tracer(False)
136n/a self.writer.clear()
137n/a if msg2 is not None:
138n/a self.writer.goto(0, - SCREENHEIGHT // 2 + 48)
139n/a self.writer.pencolor("red")
140n/a self.writer.write(msg2, align="center", font=("Courier",18,"bold"))
141n/a self.writer.goto(0, - SCREENHEIGHT // 2 + 20)
142n/a self.writer.pencolor("black")
143n/a self.writer.write(msg1, align="center", font=("Courier",14,"bold"))
144n/a self.screen.tracer(True)
145n/a
146n/a def setup(self):
147n/a self.screen.tracer(False)
148n/a for row in range(3):
149n/a for col in range(self.model.sticks[row]):
150n/a self.sticks[(row, col)].color(SCOLOR)
151n/a for row in range(3):
152n/a for col in range(self.model.sticks[row], MAXSTICKS):
153n/a self.sticks[(row, col)].color("white")
154n/a self.display("Your turn! Click leftmost stick to remove.")
155n/a self.screen.tracer(True)
156n/a
157n/a def notify_move(self, row, col, maxspalte, player):
158n/a if player == 0:
159n/a farbe = HCOLOR
160n/a for s in range(col, maxspalte):
161n/a self.sticks[(row, s)].color(farbe)
162n/a else:
163n/a self.display(" ... thinking ... ")
164n/a time.sleep(0.5)
165n/a self.display(" ... thinking ... aaah ...")
166n/a farbe = COLOR
167n/a for s in range(maxspalte-1, col-1, -1):
168n/a time.sleep(0.2)
169n/a self.sticks[(row, s)].color(farbe)
170n/a self.display("Your turn! Click leftmost stick to remove.")
171n/a
172n/a def notify_over(self):
173n/a if self.game.model.winner == 0:
174n/a msg2 = "Congrats. You're the winner!!!"
175n/a else:
176n/a msg2 = "Sorry, the computer is the winner."
177n/a self.display("To play again press space bar. To leave press ESC.", msg2)
178n/a
179n/a def clear(self):
180n/a if self.game.state == Nim.OVER:
181n/a self.screen.clear()
182n/a
183n/a
184n/aclass NimController(object):
185n/a
186n/a def __init__(self, game):
187n/a self.game = game
188n/a self.sticks = game.view.sticks
189n/a self.BUSY = False
190n/a for stick in self.sticks.values():
191n/a stick.onclick(stick.makemove)
192n/a self.game.screen.onkey(self.game.model.setup, "space")
193n/a self.game.screen.onkey(self.game.view.clear, "Escape")
194n/a self.game.view.display("Press space bar to start game")
195n/a self.game.screen.listen()
196n/a
197n/a def notify_move(self, row, col):
198n/a if self.BUSY:
199n/a return
200n/a self.BUSY = True
201n/a self.game.model.notify_move(row, col)
202n/a self.BUSY = False
203n/a
204n/a
205n/aclass Nim(object):
206n/a CREATED = 0
207n/a RUNNING = 1
208n/a OVER = 2
209n/a def __init__(self, screen):
210n/a self.state = Nim.CREATED
211n/a self.screen = screen
212n/a self.model = NimModel(self)
213n/a self.view = NimView(self)
214n/a self.controller = NimController(self)
215n/a
216n/a
217n/adef main():
218n/a mainscreen = turtle.Screen()
219n/a mainscreen.mode("standard")
220n/a mainscreen.setup(SCREENWIDTH, SCREENHEIGHT)
221n/a nim = Nim(mainscreen)
222n/a return "EVENTLOOP"
223n/a
224n/aif __name__ == "__main__":
225n/a main()
226n/a turtle.mainloop()