Форум сайта python.su
Есть немного.
Комментарии моя слабость. :(
Только:
1) Ни одной лишней функции не наследует.
4) Даже не знаю как она там оказалась : ))
Офлайн
Controll.py
class ExitException(Exception):
pass
class Controll:
@staticmethod
def ask_user_to_throw():
ask = 0
while not (ask in ("Y", "N", "E")):
ask = raw_input("Are you want to throw the bone again? (Y/N or E to end the game): ").upper()
if ask == "E":
raise ExitException()
return True if ask == "Y" else False
@staticmethod
def ask_user_name():
return raw_input("Enter your name:\n")
@staticmethod
def ask_for_opponent(opponents):
x = None
s = ""
keys = opponents.keys()
keys.sort()
for k in keys:
s += "\n" + " - ".join([k, opponents[k]])
print "Chose your opponent:", s
while not (x in keys):
x = raw_input()
return int(x)
@staticmethod
def show_bone(number):
print "Bone stops at %s." % number
@staticmethod
def show_winner(name, points):
print "And the winner is %s with %s points!" % (name, points)
@staticmethod
def show_user_points(name, points):
print "%s have %s points." % (name, points)
@staticmethod
def show_user_turn(name):
print "\n%s turn:" % (name)
import random
import time
from Controll import *
class Gamer:
def __init__(self, name="noname"):
if name == "":
name = "Unnamed"
self.name = name
# Number of attempts.
self.try_count = 0
# Sum of points per one attempt.
self.try_points = 0
# Sum of all points per game.
self.game_points = 0
def throw_bone(self):
"""Throws the bone. Returns number or False."""
curr_val = random.randrange(1, 7)
self.try_count += 1
self.try_points += curr_val
return curr_val
def stop(self):
"""Stops an attempt."""
self.game_points += self.try_points
self.try_count = 0
self.try_points = 0
def whant_throw_again(self, *args):
return Controll.ask_user_to_throw()
def __cmp__(self, user):
return 1 if self.game_points > user.game_points else -1
class Computer(Gamer):
def __init__(self, name, difficulty=1):
Gamer.__init__(self, name)
# Предпологается, что вероятность того, что компьютер согласится на следущий ход
#равна 100 - a * <количество бросковза раз> - b * <набранные в попытке очки>.
#При этом если набрано некое максимальное количество, вероятность снижается до 20%,
#или меньше если по формуле меньше.
#Алгоритм придуман наобум, так что :) Может быть и получется регулировать сложность.
difficulty_level = {1: {"max": 10, "a": 5, "b": 1, "if_less": 20, "if_more": -20},
2: {"max": 20, "a": 10, "b": 2, "if_less": 20, "if_more": -20},
3: {"max": 25, "a": 5, "b": 3, "if_less": 30, "if_more": -10}}
self.dif = difficulty_level[difficulty]
def whant_throw_again(self, highest_points):
# Calculate a chance.
chance = 100 - self.dif["a"] * self.try_count - self.dif["b"] * self.try_points
# If more than max value, set chance to 20%
if self.try_points > self.dif["max"]:
chance = min(20, chance)
# If my points less then some other player increase a chance.
if self.game_points < highest_points:
chance += self.dif["if_less"]
# And if not, don't risk.
else:
chance += self.dif["if_more"]
# Pretending that we think.
time.sleep(0.5)
# Are you lucky?
return random.randrange(1, 101) <= chance
from Controll import *
from Users import *
import time
class Game:
def __init__(self, players, max_points=100):
# Max points in a game.
self.max = 100
# Can be any number of players.
self.players = players
self.p_count = len(players)
# Select a random player.
self.curr_gamer = random.randrange(self.p_count)
# The highest points.
self.highest_points = 0
def next_user(self):
self.curr_gamer += 1
if self.curr_gamer == self.p_count:
self.curr_gamer = 0
return self.players[self.curr_gamer]
def start(self):
user = self.next_user()
try:
while user.game_points < self.max:
user = self.next_user()
time.sleep(1)
# User turn begin.
Controll.show_user_turn(user.name)
while True:
num = user.throw_bone()
Controll.show_bone(num)
if num == 1:
user.try_points = 0
if num == 1 or not user.whant_throw_again(self.highest_points):
user.stop()
if user.game_points > self.highest_points:
self.highest_points = user.game_points
Controll.show_user_points(user.name, user.game_points)
break
except ExitException:
pass
finally:
# End of the game.
self.stop()
def stop(self):
print "\n"
for user in self.players:
Controll.show_user_points(user.name, user.game_points)
winner = max(self.players)
Controll.show_winner(winner.name, winner.game_points)
if __name__ == "__main__":
u1 = Gamer(Controll.ask_user_name())
comps = {"1": "Josh", "2": "Ben", "3": "Griffon"}
x = Controll.ask_for_opponent(comps)
u2 = Computer(comps[str(x)], x)
game = Game((u1, u2))
game.start()
Отредактировано (Апрель 21, 2010 22:22:04)
Офлайн
GriffonБольше всего мне нравится код, которому комментарии не нужны :)
Комментарии моя слабость. :(
GriffonЭто временно :)
1) Ни одной лишней функции не наследует.
Офлайн
Вообще не нужен.
Я просто его создал ещё до того как разбил на модули. Но можно смело его убрать.
Вообще мой подход (а соответственно и код) в корне неправильные. Я исключил планирование. :) Всё писалось по наитию без перерывов от и до, за кратчайший промежуток времени.
Как я вижу всю модель:
Для всех классов присущ единный интерфейс, так? класс человека обладает минимальным интерфейсом, так как остальной это и есть сам человек. Потому имеет смысл наследовать именно класс человека, и переопределять методы где человек принимает решение.
Компьютер конечно же должен оперировать всей историей и рассчитывать исходя из этого вероятности. Я же, взял первую промелькнувшую мысль, которая хоть как-то могла бы влиять на вероятность принятия решения лично мною.
И действительно если и развивать идею, то нужна платформа. Ибо один топик форума не лучшая форма. Для таких вещей надо как минимум ветка на проект с отдельными топиками обсуждения теории, реализациями программ и т.д.
Офлайн
Было бы интересно посмотреть на альтернативную реализацию. ;)
Офлайн
whant_throw_again
whantGrammar Nazi в бешенстве! :E
Офлайн
Заметил это ещё в тот день когда написал, при тестировании. И даже исправил. Но при переносе, сразу после тестирования, случайно взял версию до теста. Оттого и max = 100, оттого и whant. Но я рад что вам понравилось. :) Там есть и другие ошибки.
Кстати .Serj., можно и уважение проявить к собеседникам. Как это сделал lorein.
Офлайн
GriffonДумаю, более верный термин - проектирование. Но предполагаю, что вышло бы примерно то же самое. Тут надо иметь какие-то принципы. Например, использовать шаблоны GRASP.
Я исключил планирование.
GriffonЯ думаю, что тут вполне хватило бы следующей связки: тема форума + репозиторий для кода + wiki (или подобный ресурс для документации) + возможно, канал в IRC. Но, для этого надо заводить отдельную роль - инструментальщика, который бы это организовывал, следил за текущим состоянием. С этой ролью могут быть проблемы - никто не захочет её выполнять.
И действительно если и развивать идею, то нужна платформа. Ибо один топик форума не лучшая форма. Для таких вещей надо как минимум ветка на проект с отдельными топиками обсуждения теории, реализациями программ и т.д.
Офлайн
GriffonНу, не реализацию (не имею права ей заниматься как автор ТЗ), а некоторую заготовку могу выложить. Тут я прикидывал, как будет выглядеть и использоваться объект-Таблица, о которой я говорил выше. Игрок-Человек не используется, зато компьютерных игроков - 3. Стратегии нет - просто бросают кость по 2 раза.
Было бы интересно посмотреть на альтернативную реализацию. ;)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import time
from copy import deepcopy
class Interface:
pass
class Line:
def __init__(self):
self.data = []
self.score = 0
def add_number(self, number, sum_flag=True):
self.data.append(number)
if sum_flag:
self.score += number
else:
self.score = 0
class MainLine(Line):
def set_number(self, number):
if self.data:
self.data[-1] = number
self.score = sum(self.data)
class Page:
def __init__(self):
self.lines = []
self.mainLine = MainLine()
def make_new_line(self):
self.lines.append(Line())
self.mainLine.add_number(0)
def add_number(self, number, sum_flag=True):
if self.lines:
self.lines[-1].add_number(number, sum_flag)
self.mainLine.set_number(self.lines[-1].score)
class Table:
def __init__(self):
self.__pages = {}
def make_new_line(self, id):
if id in self.__pages:
self.__pages[id].make_new_line()
else:
self.__pages[id] = Page()
def get_page(self, id):
return deepcopy(self.__pages[id])
def add_number(self, id, number, flag):
self.__pages[id].add_number(number, flag)
def id_enable(self, id):
return id in self.__pages
def get_score(self, id):
if self.id_enable(id):
return self.__pages[id].mainLine.score
else:
return 0
class GameTable(Table):
CLEAR_SUM_NUMBER = 1
MAX_SUM = 100
def write_roll_result(self, id, points):
if self.id_enable(id):
flag = self.calc_flag(points)
self.add_number(id, points, flag)
return flag and (not self.player_wins(id))
def player_wins(self, id):
return self.get_score(id) > self.MAX_SUM
def calc_flag(self, points):
return points != self.CLEAR_SUM_NUMBER
class Player:
def __init__(self, id, table):
self.id = id
self.table = table
def roll_dice(self):
return self.table.write_roll_result(self.id, random.randint(1, 6))
class CompPlayer(Player):
def make_turn(self):
self.table.make_new_line(self.id)
for i in xrange(2):
if not self.roll_dice(): break
class HumanPlayer(Player):pass
class Game:
def __init__(self):
self.table = GameTable()
self.players = [CompPlayer(name, self.table) for name in (
"First Player", "Second Player", "Third Player")]
def play(self):
while True:
for player in self.players:
player.make_turn()
time.sleep(0.1)
page = self.table.get_page(player.id)
print player.id, '\t:', page.mainLine.data, page.mainLine.score
if self.table.player_wins(player.id):
print player.id, 'wins!'
return
def main():
game = Game()
game.play()
if __name__ == "__main__":
main()
Офлайн
Как-то поутихло всё. Пока возникла пауза, расскажу предысторию.
Идея учебных проектов преследует меня давно. Первый такой проект назывался “Адресная книга”. В основном его делали 3 человека. Проект был поделён на 3 части и каждый делал свою часть. Использовался язык программирования C++. Весь код выкладывался прямо в тему форума. Вначале в виде сообщений, потом в виде прикрепленных архивов.
Затем был создан гугловский репозиторий.
https://code.google.com/p/neat-address-book/
Однако, на этом проект и заглох. Скорее даже не из-за этого, а потому что один из участников тянул, медленно делал свою часть. Трудно сказать.
В любом случае, я стал придумывать, как сделать так, чтобы проект был более живой, пусть даже менее организованный. Пришёл к тому, что куски кода (а может и весь код) должны выкладываться прямо в тему форума. А чтобы это не выглядело слишком многословно, я выбрал Python вместо C++. Кроме того, в нём проще изучать Unit-тесты, проще применять рефакторинг (благодаря лаконичности и сборщику мусора).
Теоретически вроде бы всё складно вышло, на практике тоже всё затихло. Хотя началось хорошо :)
Офлайн