Прошу указать на явные ошибки, которые в больших приложениях сильно сказались бы на скорости.
Прошу подсказать, как избавиться от global 'ов.
Ну и стиль… Хотя я старался соответствовать рекомендациям.
Это игра “Быки и коровы” со словами.
Написана на 2.6. GUI на TKinter.
Текущая версия вполне играбельна, хотя, возможно, имеет некоторое количество багов.
По ссылке ниже отдельно выложены файлы словарей + иконки для окон + исходник. Папка DATA должна лежать вместе со скриптом в одном каталоге.
Ну и для удобства оценки - исходник во врезке:
# -*- coding: utf-8 -*-
from Tkinter import *
import Tkinter
from ScrolledText import *
from random import randrange
import os
ALPHABET = [u'а', u'б', u'в', u'г', u'д', u'е', u'ё', u'ж', u'з', u'и', u'й', u'к', u'л',\
u'м', u'н', u'о', u'п', u'р', u'с', u'т', u'у', u'ф', u'х', u'ц', \
u'ч', u'ш', u'щ', u'ъ', u'ы', u'ь', u'э', u'ю', u'я']
SPECSYMB = [u'.', u':', u'!'] #символы командного режима
word_secret = ''#загаданное слово. get_new_word() - функция для дёрганья его из файла
bad_cha_show = ''#какие символы из алфавита показывать в качестве "плохих"
enter_temp = '' #тут храним последний ввод, при котором строка не начиналась c
#символа команды
hard_level = 4 #тут уровень сложности (количество букв в загаданном слове)
loop=1 #loop это номер хода (номер строки)
def start(event):
global enter_temp
global loop
#получаем слово, которое было введено
enterus = mainbox.get(str(loop)+'.0', END)[:-1]
if enterus in '!magic':
mainbox.insert(END,' --->'+word_secret+'<---') #чит :Р
if enterus[0] == '.': #если введённая строка начинается с точки
if enterus == '.': #и вообще, она и есть точка, то
bad.delete(1.0, END) #в качестве "плохих" выводим предыдущий ввод
bad.insert(END, badchars(enter_temp))
else:
bad.delete(1.0, END) #а если она не заканчивается точкой, то соответственно,
bad.insert(END, badchars(enterus[1:])) #текущий ввод суём в "плохие" буквы
if enterus[0] == ':':
good.delete(1.0, END)
#заменяем ' ' на '-' и суем в поле для хранения пользовательского варианта слова
good.insert(END, enterus[1:].replace(' ', ' - '))
if enterus[0] not in SPECSYMB: #если ввод не начинается с символа команды
enter_temp = enterus #тут храним последнюю введённую строку
#передаём в процедурину содержимое поля ввода в нижнем регистре,
#заменив "ё" на "е", это ведь ода буква...
cows, bulls = cow_bull(enterus.lower().replace(u'ё', u'е'))
cow_i, bull_i = len(cows), len(bulls)
if cow_i == 0: cow_st = '' # тут выбираем красивое окончание
elif cow_i == 1: cow_st = 'а'
elif cow_i <= 4: cow_st = 'ы'
elif cow_i >= 5: cow_st = ''
if bull_i == 0: bull_st = 'ов'
elif bull_i == 1: bull_st = ''
elif bull_i <= 4: bull_st = 'а'
elif bull_i >= 5: bull_st = 'ов'
#формируем вывод со всеми циферками и правильными окончаниями:
mainbox.insert(END, "--> Тут {cowi} коров{cowst} и {buli} бык{bulst}."\
.format(cowi = cow_i, cowst = cow_st, buli = bull_i, bulst = bull_st)) #красивенько все выводим в большое окно
if len(bulls) == len(enterus):
mainbox.insert(END, "\n\n\nПоздравляю, вы отгадали слово!\n")
mainbox.see(END)
loop+=4
mainbox.see(END)
loop += 1
def get_new_word(hl): #hl = hard level фактически-количество букв в слове
with open('DATA\\dict\\'+str(hard_level)) as f:
wordlist = f.readlines()
return unicode(wordlist[randrange(0,len(wordlist))][:-1], "cp1251")
def cow_bull(word_enter):
#Количество быков и коров в введённом слове
#word_enter введённое слово
#word_secret загаданное слово
cows = [] #Это "буквы-коровы"
bulls = [] #Это "буквы-быки"
if len(word_enter) > len(word_secret): #если введённое больше загаданного
word_enter = word_enter[0:len(word_secret)] #отрезаем лишнее
for i in range(len(word_enter)): #перебор по всем буквам введенного
if word_enter[i] in word_secret: #если буква есть в загаданном слове
if (word_enter[i] == word_secret[i]): #и стоит на своем месте
bulls.append(word_enter[i]) #она бык
else: #если не на своем месте
cows.append(word_enter[i]) #корова
return cows, bulls
def badchars(word):
string = '' #тут будем хранить строку для возврата
global bad_cha_show
for i in word: #по всем буквам переданного слова
if not i in bad_cha_show: #если буква отсутствует среди "плохих" букв
bad_cha_show += i #то добавляем её туда
for i in ALPHABET: #теперь по алфавиту:
if i in bad_cha_show: #если буква есть среди "плохих"
string += i+' ' #добавим его в строку
return string
def print_badcha(event): #выводит буквы, которых в слове нет в окошко bad
if mainbox.get(1.0,END)[:0]:
bad.delete(1.0, END)
bad.insert(END, badchars(enterfill.get()))
else:
bad.delete(1.0, END)
bad.insert(END, badchars(enter_temp))
enterfill.delete(0, END)
def print_goodcha(event): #выводит вариант слова в окошко good
good.delete(1.0, END)
good.insert(END, enterfill.get().replace(' ', '-'))
enterfill.delete(0, END)
def start_new_game(): #диалоговое окошко для начала новой игры
def return_and_die(event): #типа начать игру
global hard_level
global word_secret
global loop
loop = 1
hard_level = hardlist.get() #устанавливает уровень сложности
word_secret = get_new_word(hard_level) #вызывает процедурку, которая и подсунет само слово в переменную word_secret
mainbox.delete(1.0, END)
bad.delete(1.0, END)
good.delete(1.0, END)
good.insert(END, 'Длинна слова {0} знаков'.format(hard_level)) #сообщает длинну слова
dialog.destroy() #героически умирает
dialog = Toplevel()
dialog.title("Новая игра")
label = Label(dialog, text=u"Выберите количество букв в слове:")
hardlist = Scale(dialog, orient=HORIZONTAL, from_=3, to=10,\
tickinterval=1, resolution=1)
btn_go = Button(dialog, text="Начать")
label.pack(side=TOP)
hardlist.pack(side=TOP)
btn_go.pack(side=RIGHT)
btn_go.bind("<Button-1>", return_and_die)
def info(): #окошко "о программе"
info = Toplevel()
info.title("Информация")
info.iconbitmap("DATA\\img\\info.ico")
infoblank = Canvas(info, width=370, height=200, bg="grey")
infoblank.create_text(190, 100, justify=CENTER, text="Text here")
infoblank.pack()
#---------------------------------------------------------------------------------------------
root = Tk() # окно
#root.style.theme_use("alt")
root.title("Быки и коровы")
root.iconbitmap("DATA\\img\\bull.ico")
frame_1 = Frame(root) #Рамки
frame_2 = Frame(root)
main_menu = Menu(root) #меню
root.config(menu=main_menu)
root_menu = Menu(main_menu)
main_menu.add_cascade(label="Меню", menu=root_menu)
root_menu.add_command(label="Новая игра", command=start_new_game) #Начать новую игру функцией start_new_game
root_menu.add_command(label="О программе", command=info)
root_menu.add_separator()
root_menu.add_command(label="Выход", command=root.destroy)
mainbox = ScrolledText(frame_1, width=47, height=25, font=('Tahoma', 10)) #Окно вывода
bad = Text(frame_2, width=8, height=10, font=('Tahoma',25,'bold')) #Буквы, которых нет в слове
good = Text(frame_1, height=1, width=50, font=('Tahoma', 10)) #Окошко для хранения варианта загаданного слова
btn_submit = Button(frame_2, width=8, text="Ввод")
btn_badchar = Button(frame_2, text="В список")
btn_goodchar = Button(frame_2, width=8, text="Вариант")
frame_1.pack(side = LEFT)
frame_2.pack(side = LEFT)
good.pack(side = TOP)
mainbox.pack(side = TOP)
bad.pack(side = TOP)
btn_submit.pack(side = LEFT)
btn_badchar.pack(side = RIGHT)
btn_goodchar.pack(side = RIGHT)
btn_submit.bind("<Button-1>", start)
btn_badchar.bind("<Button-1>", print_badcha)
btn_goodchar.bind("<Button-1>", print_goodcha)
mainbox.bind("<Return>", start)
word_secret = get_new_word(hard_level)
good.delete(1.0, END)
good.insert(END, 'Длинна слова '+str(hard_level)+' знаков')
root.mainloop()
При запуске программа загадает слово из 4 букв.
Слова из другого количества букв доступны в менюшке “новая игра”
Ввод варианта и вывод осуществляется через основное окно. При нажатии кнопки “вариант” текущее введённое слово будет отображено в поле вверху окна, при этом пробелы в слове будут заменены на “ - ”. Это нужно для отображения вашего варианта слова (удобно, когда он перед глазами). При нажатии кнопки “в список” Текущее слово будет разбито на буквы и добавлено в поле с правой стороны. Это поле для букв, которых по вашему мнению в слове нет. Опять таки удобно держать их перед глазами. Функции кнопок продублированы командным режимом: ввод “:варинт” отобразит введённое слово в строке варианта. Ввод “.буквы” отобразит буквы “б, в, к, …” в поле для букв, которых в слове нет.
Коротко о правилах игры. Вы вводите слово. В ответ вы получаете сообщение о количестве быков и коров. Бык - буква которая присутствует в загаданном слове и В ВАШЕМ слове она присутствует и стоит на правильной (относительно загаданного слова) позиции. Корова - буква есть, но стоит на неверной позиции. Подробности в интернете…
http://slil.ru/29151670 - ZIP; 27 Кб