-
Notifications
You must be signed in to change notification settings - Fork 5
/
hangman.py
102 lines (74 loc) · 2.44 KB
/
hangman.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import random
import flask
from flask_sqlalchemy import SQLAlchemy
app = flask.Flask(__name__)
# Database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hangman.db'
db = SQLAlchemy(app)
# Model
def random_pk():
return random.randint(1e9, 1e10)
def random_word():
words = [line.strip() for line in open('words.txt') if len(line) > 10]
return random.choice(words).upper()
class Game(db.Model):
pk = db.Column(db.Integer, primary_key=True, default=random_pk)
word = db.Column(db.String(50), default=random_word)
tried = db.Column(db.String(50), default='')
player = db.Column(db.String(50))
def __init__(self, player):
self.player = player
@property
def errors(self):
return ''.join(set(self.tried) - set(self.word))
@property
def current(self):
return ''.join([c if c in self.tried else '_' for c in self.word])
@property
def points(self):
return 100 + 2*len(set(self.word)) + len(self.word) - 10*len(self.errors)
# Play
def try_letter(self, letter):
if not self.finished and letter not in self.tried:
self.tried += letter
db.session.commit()
# Game status
@property
def won(self):
return self.current == self.word
@property
def lost(self):
return len(self.errors) == 6
@property
def finished(self):
return self.won or self.lost
# Controller
@app.route('/')
def home():
games = sorted(
[game for game in Game.query.all() if game.won],
key=lambda game: -game.points)[:10]
return flask.render_template('home.html', games=games)
@app.route('/play')
def new_game():
player = flask.request.args.get('player')
game = Game(player)
db.session.add(game)
db.session.commit()
return flask.redirect(flask.url_for('play', game_id=game.pk))
@app.route('/play/<game_id>', methods=['GET', 'POST'])
def play(game_id):
game = Game.query.get_or_404(game_id)
if flask.request.method == 'POST':
letter = flask.request.form['letter'].upper()
if len(letter) == 1 and letter.isalpha():
game.try_letter(letter)
if flask.request.is_xhr:
return flask.jsonify(current=game.current,
errors=game.errors,
finished=game.finished)
else:
return flask.render_template('play.html', game=game)
# Main
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)