Я пытаюсь сделать камень-ножницы-бумага с помощью графического интерфейса Tkinter, но по какой-то причине в моей функции «запуск» (незаконченной) player_number
не определено,
def run():
result.grid(column=3, row=1)
if player_number == "1":
rock.grid(column=2, row=2)
add_fillers()
choose_player_number()
run()
хотя я определил это в этих двух функциях (запускаемых кнопками) далее в коде:
def oneplayer():
title.configure(text = "One player")
title.grid(column=3, row=0)
global player_number
player_number = "1"
one_player.destroy()
two_players.destroy()
def twoplayers():
title.configure(text = "Two players")
title.grid(column=3, row=0)
global player_number
player_number = "2"
one_player.destroy()
two_players.destroy()
Я попробовал установить переменные на global
, но это не сработало. Вот весь мой код:
import random
from random import randint
import tkinter as tk
from tkinter import *
window = tk.Tk()
window.geometry("1400x860")
window.title = "Rock paper scissors"
result = Label(window, text= "result will appear here", bg = "green")
def oneplayer():
title.configure(text = "One player")
title.grid(column=3, row=0)
global player_number
player_number = "1"
one_player.destroy()
two_players.destroy()
def twoplayers():
title.configure(text = "Two players")
title.grid(column=3, row=0)
global player_number
player_number = "2"
one_player.destroy()
two_players.destroy()
one_player = Button(window, text = "One Player", command = oneplayer)
two_players = Button(window, text= "Two players", command = twoplayers)
title = Label(window, text = "Rock paper scissors" , bg= "blue", fg = "white", font= "Times")
title.grid(column=3, row=0)
def add_fillers():
filler = Label(window, text = " ")
filler.grid(column=1, row=0)
filler2 = Label(window, text = " ")
filler2.grid(column=0, row=0)
filler3 = Label(window, text = " ")
filler3.grid(column=2, row=0)
def choose_player_number():
one_player.grid(column= 2, row=1)
two_players.grid(column= 4, row=1)
computer_input = ""
def computer_choice():
computer_input = randint("1", "2", "3")
if computer_input == "1":
computer_value = "Rock"
elif computer_input == "2":
computer_value = "paper"
else:
computer_value = "scissors"
computer_result = Label(window, text= "the computer's choice was:" + computer_value)
return computer_input
def win():
result.configure(text= "You Win")
def loose():
result.configure(text= "You loose")
def draw():
result.configure(text= "Draw")
def evaluate_rock():
computer_choice()
if computer_input == "3":
win()
elif computer_input == "2":
loose()
elif computer_input == "1":
draw()
else:
print ("error")
rock = Button(window, text = "Rock", command= evaluate_rock, fg = "green", bg = "blue")
def run():
result.grid(column=3, row=1)
if player_number == "1":
rock.grid(column=2, row=2)
add_fillers()
choose_player_number()
run()
window.mainloop()
choose_player_number
на самом деле мало что делает, он просто размещает кнопки, но затем run()
вызывается до того, как пользователь действительно сможет нажать эти кнопки.
Решение – неполное
Я исправил код, чтобы решить вашу существующую проблему. Поскольку ваш код сам по себе неполный, я не стал работать над его завершением. Кроме того, это позволит вам дополнить код своей собственной идеей.
Что я наделал
player_number, result, one_player, two_players, title и rock — глобальные переменные в вашем коде. Поскольку не рекомендуется использовать глобальные переменные, я сделал приведенные выше имена переменных клавишами dict
. Их значения - я сделал соответствующие значения одинаковыми dict
. Когда и когда нам нужно будет вызвать значение, я назову dct['variable_name']
. Используя этот метод, мы можем легко избежать использования глобального ключевого слова. (Просто проверьте, нужно ли объявлять переменную computer_input
глобальной. Если да, вы можете сделать это так же, как я.)
Над остальной частью кода вам следует работать, исходя из идеи и логики, которые у вас есть в голове.
import random
from random import randint
import tkinter as tk
from tkinter import *
dct = {'player_number' : ''}
def run():
dct['result'].grid(column=3, row=1)
if dct['player_number'] == "1":
dct['rock'].grid(column=2, row=2)
def oneplayer():
dct['title'].configure(text = "One player")
dct['title'].grid(column=3, row=0)
dct['player_number'] = "1"
dct['one_player'].destroy()
dct['two_players'].destroy()
def twoplayers():
dct['title'].configure(text = "Two players")
dct['title'].grid(column=3, row=0)
dct['player_number'] = "2"
dct['one_player'].destroy()
dct['two_players'].destroy()
def add_fillers():
filler = Label(window, text = "")
filler.grid(column=1, row=0)
filler2 = Label(window, text = "")
filler2.grid(column=0, row=0)
filler3 = Label(window, text = "")
filler3.grid(column=2, row=0)
def choose_player_number():
dct['one_player'].grid(column= 2, row=1)
dct['two_players'].grid(column= 4, row=1)
def computer_choice():
computer_input = randint("1", "2", "3")
if computer_input == "1":
computer_value = "Rock"
elif computer_input == "2":
computer_value = "paper"
else:
computer_value = "scissors"
computer_result = Label(window, text= "the computer's choice was:" + computer_value)
return computer_input
def win():
dct['result'].configure(text= "You Win")
def loose():
dct['result'].configure(text= "You loose")
def draw():
dct['result'].configure(text= "Draw")
def evaluate_rock():
computer_choice()
if computer_input == "3":
win()
elif computer_input == "2":
loose()
elif computer_input == "1":
draw()
else:
print ("error")
window = tk.Tk()
window.geometry("1400x860")
window.title = "Rock paper scissors"
dct['result'] = Label(window, text= "result will appear here", bg = "green")
dct['one_player'] = Button(window, text = "One Player", command = oneplayer)
dct['two_players'] = Button(window, text= "Two players", command = twoplayers)
dct['title'] = Label(window, text = "Rock paper scissors" , bg= "blue", fg = "white", font= "Times")
dct['title'].grid(column=3, row=0)
dct['rock'] = Button(window, text = "Rock", command= evaluate_rock, fg = "green", bg = "blue")
add_fillers()
choose_player_number()
run()
window.mainloop()
Глобальные переменные нежелательны в ООП, но в процедурном программировании они необходимы в большинстве случаев. Сейчас глобальный словарь с именем dct
действует так же, как глобальное пространство имен.
@TheLizzard, грань между «процедурным» и «объектно-ориентированным» может быть более размытой, чем вы думаете. Если вы не имеете дело с действительно древним языком, в котором нет struct
и указателей или ссылок, довольно легко написать осмысленные процедурные программы, в которых доступ ко всем данным осуществляется через ссылки/указатели, которые передаются вверх и вниз по стеку. Одинаково легко (во всех «объектно-ориентированных» языках, которые я когда-либо использовал) объявить глобальные переменные. Но ты прав. С точки зрения инженера-программиста, глобальные переменные плохи в любой парадигме программирования.
Я пытаюсь сделать камень-ножницы-бумага с помощью графического интерфейса Tkinter, но для по какой-то причине в моей функции «запуска» (незаконченной) player_number равен неопределенный,
Проблема может быть решена.
Просто добавьте параметр player_number в функцию run()
.
Фрагмент:
def run(player_number):
result.grid(column=3, row=1)
if player_number == "1":
rock.grid(column=2, row=2)
add_fillers()
choose_player_number()
run(1)
Скриншот:
Вы передаете целое число 1 в run()
, но проверяете наличие строки «1» внутри функции.
Да, но ОП еще не закончен. Как пользователь выберет одного игрока или двух игроков?
Это не имеет ничего общего с ОП, это предоставленное вами решение не имеет смысла.
Ни
oneplayer
, ниtwoplayers
не вызывается передrun
, поэтому эффективноglobal player_number
не выполняется.