проблема с заполнением правильной ячейки сетки в tkinter - PullRequest
0 голосов
/ 24 октября 2019

я пытаюсь сделать игру на линкоре на python, используя tkinter, минимальный воспроизводимый пример:

from tkinter import *
from random import randint
import time

tk = Tk()


class player:
    def __init__(self, master):
        self.master = master
        self.placedships = []
        self.bombed = []
        self.sunk = []
        self.ship_sizes = [5, 4, 3]
        self.player_canvas = Canvas(master, height=300, width=300, highlightbackground='black', highlightthickness=0.5)
        self.ai_canvas = Canvas(master, height=300, width=300, highlightbackground='black', highlightthickness=0.5)
        self.player_canvas.grid(row=1, column=0, padx=50)
        self.ai_canvas.grid(row=1, column=1, padx=50)
        self.direction = 'v'
        self.shipChosen = 0

        gridLabel_player = Label(master,text="Your grid \nA       B       C       D       E       F       G       H       I       J ")
        gridLabel_player.grid(row=0,column=0)
        gridLabel_ai = Label(master,text="AI's grid \nA       B       C       D       E       F       G       H       I       J ")
        gridLabel_ai.grid(row=0,column=1)

        for x in range(10):
            for y in range(10):
                self.player_canvas.create_rectangle(x * 30, y * 30, 300, 300, fill = 'white')
                self.ai_canvas.create_rectangle(x * 30, y * 30, 300, 300, fill = 'white')

        #variables to store data for cells on game grid
        #         # self.player_ocean = 10 * [10 * [0]]
        #         # self.ai_ocean = 10 * [10 * [0]]
        self.player_ocean = []
        self.ai_ocean = []
        temp = []
        for i in range(10):
            for y in range(10):
                temp += [0]
            self.player_ocean += [temp]
            self.ai_ocean += [temp]
            temp = []
        self.selectedCoord = [0,0] # [0] = x coord, [1] = y coord




    def placeShip(self):
        def moveShip(event):
            if event.keysym == 'Down' and self.selectedCoord[1] != 9:
                self.selectedCoord[1] += 1
            elif event.keysym == 'Up' and self.selectedCoord[1] != 0:
                self.selectedCoord[1] -= 1
            elif event.keysym == 'Left' and self.selectedCoord[0] != 0:
                self.selectedCoord[0] -= 1
            elif event.keysym == 'Right' and self.selectedCoord[0] != 9:
                self.selectedCoord[0] += 1
            print('selected coord:',self.selectedCoord)

        def selectPlacement(event):
            col = self.selectedCoord[0]
            row = self.selectedCoord[1]
            if self.direction == 'v':
                v_range_start = row - self.ship_sizes[self.shipChosen] + 1
                for y in range(v_range_start, row+1):
                    '''insert validation to reject ship clashing'''
                    self.player_ocean[y][col] = 1
                    self.placedships += [y,col]
                self.refresh_ocean()




        self.master.bind("<Up>", moveShip)
        self.master.bind("<Down>", moveShip)
        self.master.bind("<Left>", moveShip)
        self.master.bind("<Right>", moveShip)
        self.master.bind("<Return>", selectPlacement)

    def refresh_ocean(self): # 1s turns to green
        for y in range(10):
            for x in range(10):
                if self.player_ocean[y][x] == 1:
                    self.player_canvas.itemconfig(self.player_canvas.create_rectangle( (x+1) * 30, (y-1) * 30,x * 30, y * 30, fill='green'))


player1 = player(tk)
player1.placeShip()
tk.mainloop()

проблема, с которой я столкнулся, заключается в том, что если я нажимаю стрелку вниз, пока выбранная координата не станет [0,9], код должен закрашивать 6–10-е поле сверху вниз в первом столбце, но окрашивает 5–9-е поле.

Я попытался отладить его, проверив, были ли неправильные координаты x и y, использованные в последней функции refresh_ocean, но они были, как и ожидалось

Ответы [ 2 ]

0 голосов
/ 24 октября 2019

Итак, короткое и простое исправление - изменить (y-1) to (y+1).

Тем не менее, я сделал несколько изменений:

  1. Переписал некоторые из ваших имен, чтобы они следовали PEP8руководство по стилю.

  2. Преобразовал ваш метод refresh_ocean для обработки начального и всех последующих зарисовок. А также добавили delete('all'), чтобы очистить игровое поле, чтобы мы не рисовали поверх предыдущих объектов. Это предотвратит использование большего количества памяти по ходу игры.

  3. Очистил импорт и изменил from tkinter import * на import tkinter as tk. Это поможет предотвратить перезапись других вещей в пространстве имен.

  4. Написав свой refresh_ocean для обработки всего рисунка, мы можем указать, что нужно рисовать с помощью таких тегов, как 'player1' и 'ai'.

  5. Изменено += на .append() для генерации списка, так как append() в два раза быстрее '+=. См. Этот пост: Разница между «.append ()» и «+ = []»?

  6. Изменили одну метку заголовков в цикле для создания каждогомаркируйте равномерно. Это позволит получить более точный заголовок, чем пытаться вручную установить пробелы в одной строке.

  7. Наконец, потому что вы уже проверяете ключ, это одна из 4 клавиш со стрелками, которые мы можем использоватьодна привязка к '<Key>' и получение тех же результатов, что и для всех 4 привязок.

Обновленный код:

import tkinter as tk


class Player(tk.Tk):
    def __init__(self):
        super().__init__()
        self.placed_ships = []
        self.player_ocean = []
        self.ai_ocean = []
        self.bombed = []
        self.sunk = []
        self.bord_size = list('ABCDEFGHIJ')
        self.selected_coord = [0, 0]
        self.ship_sizes = [5, 4, 3]
        self.direction = 'v'
        self.shipChosen = 0
        wh = 300

        p_label_frame = tk.Frame(self, width=wh, height=30)
        a_label_frame = tk.Frame(self, width=wh, height=30)
        p_label_frame.grid(row=1, column=0, padx=50)
        a_label_frame.grid(row=1, column=1, padx=50)
        p_label_frame.grid_propagate(False)
        a_label_frame.grid_propagate(False)

        for ndex, letter in enumerate(self.bord_size):
            p_label_frame.columnconfigure(ndex, weight=1)
            a_label_frame.columnconfigure(ndex, weight=1)
            tk.Label(p_label_frame, text=letter).grid(row=0, column=ndex)
            tk.Label(a_label_frame, text=letter).grid(row=0, column=ndex)

        self.player_canvas = tk.Canvas(self, height=wh, width=wh, highlightbackground='black', highlightthickness=0.5)
        self.ai_canvas = tk.Canvas(self, height=wh, width=wh, highlightbackground='black', highlightthickness=0.5)
        self.player_canvas.grid(row=2, column=0, padx=50)
        self.ai_canvas.grid(row=2, column=1, padx=50)

        temp = []
        for i in range(10):
            for y in range(10):
                temp.append(0)
            self.player_ocean.append(temp)
            self.ai_ocean.append(temp)
            temp = []

        self.refresh_ocean()
        self.bind("<Key>", self.move_ship)
        self.bind("<Return>", self.select_placement)

    def move_ship(self, event):
        if event.keysym == 'Down' and self.selected_coord[1] < 9:
            self.selected_coord[1] += 1
        elif event.keysym == 'Up' and self.selected_coord[1] > 0:
            self.selected_coord[1] -= 1
        elif event.keysym == 'Left' and self.selected_coord[0] > 0:
            self.selected_coord[0] -= 1
        elif event.keysym == 'Right' and self.selected_coord[0] < 9:
            self.selected_coord[0] += 1
        print('selected coord:', self.selected_coord)

    def select_placement(self, _=None):
        col = self.selected_coord[0]
        row = self.selected_coord[1]
        if self.direction == 'v':
            v_range_start = row - self.ship_sizes[self.shipChosen] + 1
            for y in range(v_range_start, row+1):
                '''insert validation to reject ship clashing'''
                self.player_ocean[y][col] = 1
                self.placed_ships += [y, col]
            self.refresh_ocean(side='player1')

    def refresh_ocean(self, side=None):
        self.player_canvas.delete('all')
        self.ai_canvas.delete('all')

        for y in range(len(self.bord_size)):
            for x in range(len(self.bord_size)):
                if self.player_ocean[y][x] == 1 and side == 'player1':
                    self.player_canvas.itemconfig(self.player_canvas.create_rectangle(
                        (x+1) * 30, (y+1) * 30, x * 30, y * 30, fill='green'))
                else:
                    self.player_canvas.create_rectangle(x * 30, y * 30, 300, 300, fill='white')

                if self.ai_ocean[y][x] == 1 and side == 'ai':
                    self.ai_canvas.itemconfig(self.ai_canvas.create_rectangle(
                        (x + 1) * 30, (y + 1) * 30, x * 30, y * 30, fill='green'))
                else:
                    self.ai_canvas.create_rectangle(x * 30, y * 30, 300, 300, fill='white')


if __name__ == '__main__':
    Player().mainloop()

Результаты:

enter image description here

0 голосов
/ 24 октября 2019

ваш refresh_ocean был отключен с ошибкой 1

def refresh_ocean(self): # 1s turns to green
    for y in range(10):
        for x in range(10):
            if self.player_ocean[y][x] == 1:
                self.player_canvas.itemconfig(self.player_canvas.create_rectangle( x*30, y * 30, x*30+30, y*30+30, fill='green'))

, и при выборе места размещения размещались корабли с отрицательным индексом. я изменил вашу итерацию с range(row-size, row) на range(row, row+size) и добавил проверку границ, но это, вероятно, следует перенести в обработку движения.

def selectPlacement(event):
    col = self.selectedCoord[0]
    row = self.selectedCoord[1]
    if self.direction == 'v':
        if row + self.ship_sizes[self.shipChosen] > 9:
            row = 10 - self.ship_sizes[self.shipChosen]
        for y in range(row, row + self.ship_sizes[self.shipChosen]):
            '''insert validation to reject ship clashing'''
            self.player_ocean[y][col] = 1
            self.placedships += [y,col]
        self.refresh_ocean()

ps: рисование новых квадратов поверх старых квадратов. Вы можете очистить океан перед рисованием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...