1 """ turtle-example-suite:
5 Play nim against the computer. The player
6 who takes the last stick is the winner.
8 Implements the model-view-controller
23 HUNIT
= SCREENHEIGHT
// 12
24 WUNIT
= SCREENWIDTH
// ((MAXSTICKS
// 5) * 11 + (MAXSTICKS
% 5) * 2)
27 HCOLOR
= (255, 204, 204)
28 COLOR
= (204, 204, 255)
31 return random
.randint(MINSTICKS
, MAXSTICKS
)
33 def computerzug(state
):
34 xored
= state
[0] ^ state
[1] ^ state
[2]
36 return randommove(state
)
43 def randommove(state
):
46 z
= random
.randint(0,2)
47 if state
[z
] > (m
> 1):
49 rand
= random
.randint(m
> 1, state
[z
]-1)
53 class NimModel(object):
54 def __init__(self
, game
):
58 if self
.game
.state
not in [Nim
.CREATED
, Nim
.OVER
]:
60 self
.sticks
= [randomrow(), randomrow(), randomrow()]
63 self
.game
.view
.setup()
64 self
.game
.state
= Nim
.RUNNING
66 def move(self
, row
, col
):
67 maxspalte
= self
.sticks
[row
]
68 self
.sticks
[row
] = col
69 self
.game
.view
.notify_move(row
, col
, maxspalte
, self
.player
)
71 self
.game
.state
= Nim
.OVER
72 self
.winner
= self
.player
73 self
.game
.view
.notify_over()
74 elif self
.player
== 0:
76 row
, col
= computerzug(self
.sticks
)
81 return self
.sticks
== [0, 0, 0]
83 def notify_move(self
, row
, col
):
84 if self
.sticks
[row
] <= col
:
89 class Stick(turtle
.Turtle
):
90 def __init__(self
, row
, col
, game
):
91 turtle
.Turtle
.__init
__(self
, visible
=False)
95 x
, y
= self
.coords(row
, col
)
97 self
.shapesize(HUNIT
/10.0, WUNIT
/20.0)
104 def coords(self
, row
, col
):
105 packet
, remainder
= divmod(col
, 5)
106 x
= (3 + 11 * packet
+ 2 * remainder
) * WUNIT
107 y
= (2 + 3 * row
) * HUNIT
108 return x
- SCREENWIDTH
// 2 + WUNIT
// 2, SCREENHEIGHT
// 2 - y
- HUNIT
// 2
110 def makemove(self
, x
, y
):
111 if self
.game
.state
!= Nim
.RUNNING
:
113 self
.game
.controller
.notify_move(self
.row
, self
.col
)
116 class NimView(object):
117 def __init__(self
, game
):
119 self
.screen
= game
.screen
120 self
.model
= game
.model
121 self
.screen
.colormode(255)
122 self
.screen
.tracer(False)
123 self
.screen
.bgcolor((240, 240, 255))
124 self
.writer
= turtle
.Turtle(visible
=False)
129 for col
in range(MAXSTICKS
):
130 self
.sticks
[(row
, col
)] = Stick(row
, col
, game
)
131 self
.display("... a moment please ...")
132 self
.screen
.tracer(True)
134 def display(self
, msg1
, msg2
=None):
135 self
.screen
.tracer(False)
138 self
.writer
.goto(0, - SCREENHEIGHT
// 2 + 48)
139 self
.writer
.pencolor("red")
140 self
.writer
.write(msg2
, align
="center", font
=("Courier",18,"bold"))
141 self
.writer
.goto(0, - SCREENHEIGHT
// 2 + 20)
142 self
.writer
.pencolor("black")
143 self
.writer
.write(msg1
, align
="center", font
=("Courier",14,"bold"))
144 self
.screen
.tracer(True)
148 self
.screen
.tracer(False)
150 for col
in range(self
.model
.sticks
[row
]):
151 self
.sticks
[(row
, col
)].color(SCOLOR
)
153 for col
in range(self
.model
.sticks
[row
], MAXSTICKS
):
154 self
.sticks
[(row
, col
)].color("white")
155 self
.display("Your turn! Click leftmost stick to remove.")
156 self
.screen
.tracer(True)
158 def notify_move(self
, row
, col
, maxspalte
, player
):
161 for s
in range(col
, maxspalte
):
162 self
.sticks
[(row
, s
)].color(farbe
)
164 self
.display(" ... thinking ... ")
166 self
.display(" ... thinking ... aaah ...")
168 for s
in range(maxspalte
-1, col
-1, -1):
170 self
.sticks
[(row
, s
)].color(farbe
)
171 self
.display("Your turn! Click leftmost stick to remove.")
173 def notify_over(self
):
174 if self
.game
.model
.winner
== 0:
175 msg2
= "Congrats. You're the winner!!!"
177 msg2
= "Sorry, the computer is the winner."
178 self
.display("To play again press space bar. To leave press ESC.", msg2
)
181 if self
.game
.state
== Nim
.OVER
:
184 class NimController(object):
186 def __init__(self
, game
):
188 self
.sticks
= game
.view
.sticks
190 for stick
in self
.sticks
.values():
191 stick
.onclick(stick
.makemove
)
192 self
.game
.screen
.onkey(self
.game
.model
.setup
, "space")
193 self
.game
.screen
.onkey(self
.game
.view
.clear
, "Escape")
194 self
.game
.view
.display("Press space bar to start game")
195 self
.game
.screen
.listen()
197 def notify_move(self
, row
, col
):
201 self
.game
.model
.notify_move(row
, col
)
208 def __init__(self
, screen
):
209 self
.state
= Nim
.CREATED
211 self
.model
= NimModel(self
)
212 self
.view
= NimView(self
)
213 self
.controller
= NimController(self
)
216 mainscreen
= turtle
.Screen()
217 mainscreen
.mode("standard")
218 mainscreen
.setup(SCREENWIDTH
, SCREENHEIGHT
)
221 nim
= Nim(mainscreen
)
224 if __name__
== "__main__":