python - turtle - código de dibujo de tabla para mover un óvalo
turtle python 3 (2)
Estoy trabajando en un juego de damas python para la universidad. Tengo el tablero dibujado, usando tk, pero parece que no puedo implementar una función de movimiento para las piezas. Si alguien ve algún error en mi código, o puede ofrecer ayuda, lo agradecería. Aquí está la fuente completa. Gracias por adelantado.
Sé que esto dibuja las fichas. No sé cómo volver a dibujar las piezas, sin eliminar las otras piezas. Miré en línea la función de movimiento e intenté con una prueba simple que funcionó, pero no he podido utilizarla en mi código.
Sí sé de recursión, sin embargo, necesito la función básica para trabajar, es decir, mover una pieza en la pantalla, antes de implementar más funciones.
lst2 = []
#counter variable
i=0
#board variable is what stores the X/O/- values.
# It''s a 2D list. We iterate over it, looking to see
# if there is a value that is X or O. If so, we draw
# text to the screen in the appropriate spot (based on
# i and j.
while i < len(board):
j=0
while j < len(board[i]):
if board[i][j] == 2:
lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
(j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
(j+1)*width + width/2 - 15, fill="Red",outline=''Black''))
elif board[i][j] == 4:
lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
(j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
(j+1)*width + width/2 - 15, fill="Red",outline=''Black''))
elif board[i][j] == 1:
lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
(j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
(j+1)*width + width/2 - 15, fill="Black",outline=''Black''))
elif board[i][j] == 3:
lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
(j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
(j+1)*width + width/2 - 15, fill="Black",outline=''Black''))
j+=1
i+=1
Puede mover un elemento en un lienzo utilizando los coords y / o mover los métodos para cambiar las coordenadas de lo que son a lo que quiere que sean.
Aquí hay un ejemplo simple que muestra cómo crear y mover un elemento en un lienzo:
import Tkinter as tk
class Example(tk.Frame):
''''''Illustrate how to drag items on a Tkinter canvas''''''
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# create a canvas
self.canvas = tk.Canvas(width=400, height=400)
self.canvas.pack(fill="both", expand=True)
# this data is used to keep track of an
# item being dragged
self._drag_data = {"x": 0, "y": 0, "item": None}
# create a couple of movable objects
self._create_token((100, 100), "white")
self._create_token((200, 100), "black")
# add bindings for clicking, dragging and releasing over
# any object with the "token" tag
self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)
def _create_token(self, coord, color):
''''''Create a token at the given coordinate in the given color''''''
(x,y) = coord
self.canvas.create_oval(x-25, y-25, x+25, y+25,
outline=color, fill=color, tags="token")
def on_token_press(self, event):
''''''Begining drag of an object''''''
# record the item and its location
self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
def on_token_release(self, event):
''''''End drag of an object''''''
# reset the drag information
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
def on_token_motion(self, event):
''''''Handle dragging of an object''''''
# compute how much the mouse has moved
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
# move the object the appropriate amount
self.canvas.move(self._drag_data["item"], delta_x, delta_y)
# record the new position
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
6ª EDICIÓN: Aquí hay dos soluciones para ti:
- (como sugiere Bryan) o recordar la ubicación anterior de la pieza movida, desenrústelo allí (=> dibujarlo en color de fondo), redibujarlo en una nueva ubicación
- el más simple: borrar y volver a dibujar todo el tablero
5ª EDICIÓN: Ok, gracias por quitar el código.
Explique exactamente cuál es el problema con el código de dibujo de la placa. ''¿La pieza movida no se borró de la ubicación anterior''? ''Todas las piezas están dibujadas con coordenadas o colores incorrectos''? ...? No es aceptable seguir publicando el código y diciendo "Este código no funciona".
"No sé cómo volver a dibujar las piezas, sin eliminar las otras piezas". Creo que ese es tu problema allí mismo. Si declara y llama a
redrawBoard()
, debería volver a dibujar TODAS las piezas (!), No solo la pieza movida. ¿De acuerdo? es decir, debe iterar sobre todo el tablero [] [] y llamar a drawPiece () en cada pieza. Pero su código parece hacer eso ya?
Permítame sugerirle cómo limpiar su código existente de dibujo de la placa, y en ese proceso seguramente encontrará su error. Obviamente, necesita borrar y volver a dibujar la pantalla cada vez que hay un movimiento (o promoción), ¿realmente lo hace? Declare un fn redrawBoard()
para eso. Si no lo haces, luego de un movimiento, la pieza se mostrará en sus ubicaciones antiguas Y nuevas, lo que obviamente sería incorrecto. (El comentario sobre Frecuencia de cuadros es la frecuencia con la que se actualizará el lienzo por segundo. Me pregunto cuándo volverás a dibujar, no es necesario volver a dibujar 10 veces por segundo, a menos que también tengas un reloj u otros datos variables. Pero, oye, eso también funciona.)
En primer lugar, sugiero encarecidamente que utilice una enumeración para autoeditar los valores utilizados en el tablero [] []
class Checkers():
EMPTY=0
RED_PIECE=1
RED_KING=2
BLACK_PIECE=3
BLACK_KING=4
A continuación, puede limpiar en gran medida el código de dibujo de la placa. Dado que todos los casos de dibujo de 4 piezas llaman a un caso común, conviértalo en fn, y haga que el fn quede despejado:
def drawPiece(i,j,fillColor,outlineColor):
"""Draw single piece on screen."""
x = (i+1)*width + width/2
y = (j+1)*height + height/2
lst2.append(canvas.create_oval(x+15,y+15,x-15,y-15,fill=fillColor,outline=outlineColor))
Ahora bien, el código de dibujo del tablero que los llama estrictamente realmente solo tiene dos casos: (2,4) o (1,3) suponiendo que tienes la enum correcta:
y por cierto, nunca use un ciclo while en el que un bucle for sea más legible:
for i in range(len(board)):
for j in range(len(board[i])):
if board[i][j] in (RED_PIECE,RED_KING):
drawPiece(i,j,''Red'',''Black'')
elif board[i][j] in (BLACK_PIECE,BLACK_KING):
drawPiece(i,j,''Black'',''Black'')
¿Esa descomposición no es infinitamente más fácil de leer y depurar? Es auto documentado. Ahora tu error prácticamente debería saltar sobre ti.
(Por cierto, actualmente estás dibujando reyes exactamente igual que las piezas, pero creo que lo arreglarás más tarde).
4ª EDICIÓN: Nos hiciste ver el fns equivocado, grr ... dices que tu error está realmente en el código de dibujo del tablero . ¿Podría corregir el título que todavía dice "Implementar una función de movimiento" ?
RESPUESTA ORIGINAL: lo que dijo el anhelo de la máquina, esto no es una pregunta, todavía no: cuéntanos qué intentas actualmente y por qué no funciona. Además, elimine todos los códigos no relacionados.
Parece que tienes dificultades con la función moveTo(i,j)
, pero ¿qué es exactamente? (La segunda señal GlobalPass, señal de segunda posición que podría estar teniendo problemas ... ¿sabes recursión? Si no, no te preocupes).
Además, como algo estilístico, y para facilitarle la vida, esta implementación no es OO, los globals gritan una mala descomposición. Intente volver a escribir como una clase de Checkers
, haga que la junta, etc., sea miembro, escriba un método init()
. Cambiaría el nombre de la grid(x,y)
función grid(x,y)
para initialize(nrows,ncols)
.
(¡Y tos, tos! Señales de que lo has adaptado de otra persona ...)
#Frame rate is how often canvas will be updated
# each second. For Tic Tac Toe, 10 should be plenty.
FRAME_RATE = 10