Live site: https://charlie-project3-aebf005f6451.herokuapp.com/viewlib repo: https://github.com/Tropicalbunny/FLASK
i am having an issue where my hangman page is not displaying the revealed letters (or even not revealed) within the center of the screen, but it seems every time /gameboard reloads it removes the updated revealed letters.
i originally had the variable send to HTML through the gameboard route, but it was updating to the preivous session['correct_letters']. affectively "lagging" one behind each guess.
so i tried this approach to update through the JS. unfortunately causing this. i have added the repo and live site incase any of that helps.
Python Code thats relevant:
@app.route('/button', methods=["POST"])
def buttonpress():
data = request.json
value = data['value']
hangman(value, session)
session.modified = True
return jsonify({
'status': 'success',
'correct_letters': session['correct_letters'],
'guessed_letters': session['guessed_letters'],
'guesses_left': session['guesses_left'],
'game_over': session['game_over']
})
@app.route('/gameboard')
def gameboard():
return render_template('gameboard.html')
def hangman(guess, session):
guesses_left = session['guesses_left']
guessed_letters = session['guessed_letters']
correct_letters = session['correct_letters']
game_over = session['game_over']
database_word = session['database_word']
guessed_letters = guessed_letters + guess
correct_letters = ""
if guess not in database_word:
guesses_left -= 1
session['guesses_left'] = guesses_left
if guesses_left == 0:
session['game_over'] = 1
return game_over
for letter in database_word:
if letter in guessed_letters:
correct_letters += f"{letter} "
else:
correct_letters += "_ "
session['correct_letters'] = correct_letters
session['guessed_letters'] = guessed_letters
print("cookie", session['correct_letters'])
if all(letter in guessed_letters for letter in database_word):
session['game_over'] = 2
the JS Function:
function sendValue(buttonValue) {
fetch('/button', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ value: buttonValue }),
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
document.querySelector('#displayedLetters').textContent = data.correct_letters;
}else {
console.error('Error processing guess:', data);
}
})
}
snip of HTML with button so you can see whats calling:
<div id="word-guess"><p id="displayedLetters"></p></div>
<div id="letter-guesses">
<form>
<button onclick="sendValue(this.value)" class="guess-button" id="a" value ="a">A</button>
....
ive tried a few different things: redirecting the gameboard page(when i was using jinja to show the guessed letters) within the hangman function. tried time.sleep to slow the function until the session had been updated. now trying to update the js side to reveal the guessed letters. i have used Print and console.log to narrow the issue down to here. intrestingly the function hangman updates the session['correct_letters'] correctly. but it looks like /gameboard is running before the update can take place.
I can't test it on full code but when you press <button>
then browser sends full <form>
to server and later it get response and it reloads full page.
You have to send event
to your function
onclick="sendValue(event, this.value)"
and use preventDefault()
to stop sending full <form>
function sendValue(event, buttonValue) {
event.preventDefault();
// ... rest ...
}
You can even skip this.value
because you can get it from event.target.value
onclick="sendValue(event)"
function sendValue(event) {
event.preventDefault();
buttonValue = event.target.value;
// ... rest ...
}
EDIT:
You can also use
onclick="event.preventDefault(); sendValue(this.value)"
without changing code in sendValue()
EDIT:
If you use JavaScript
to send data then you can keep <button>
without <form>
and it should work without event.preventDefault()
BTW:
In template you can use for
-loop to create buttons
<form>
{% for char in "abcdefghijklmnopqrstuvwxyz" %}
<button onclick="event.preventDefault(); sendValue(this.value)"
class="guess-button"
id="{{ char }}"
value="{{ char }}">{{ char | upper }}</button>
{% endfor %}
</form>
EDIT:
Full working code with three versions for buttons
event.preventDefault()
in sendValue()
event.preventDefault()
in onclick=".."
<form>
(and with one word abracadabra
)
I uses render_template_string
so all code, JS and HTML is in one file
and everyone can simply copy and test it.
#!/usr/bin/env python3
from flask import Flask, render_template_string, request, session, jsonify
app = Flask(__name__)
app.secret_key = "Hello World!"
@app.route('/button', methods=["POST"])
def buttonpress():
data = request.json
print(data)
value = data['value']
hangman(value, session)
session.modified = True
return jsonify({
'status': 'success',
'correct_letters': session['correct_letters'],
'guessed_letters': session['guessed_letters'],
'guesses_left': session['guesses_left'],
'game_over': session['game_over']
})
@app.route('/')
def gameboard():
session['guesses_left'] = 7
session['guessed_letters'] = ""
session['correct_letters'] = ""
session['game_over'] = 0
session['database_word'] = "abracadabra"
placeholder = '_ ' * len(session['database_word'])
return render_template_string('''
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0">
<title>Example</title>
</head>
<body>
<form>
version 1:
{% for char in "abcdefghijklmnopqrstuvwxyz" %}
<button onclick="sendValueEvent(event)" class="guess-button" id="{{ char }}" value ="{{ char }}">{{ char | upper }}</button>
{% endfor %}
</form>
<br/>
<form>
version 2:
{% for char in "abcdefghijklmnopqrstuvwxyz" %}
<button onclick="event.preventDefault(); sendValue(this.value)" class="guess-button" id="{{ char }}" value ="{{ char }}">{{ char | upper }}</button>
{% endfor %}
</form>
<br/>
<!-- without <form> -->
version 3:
{% for char in "abcdefghijklmnopqrstuvwxyz" %}
<button onclick="sendValue(this.value)" class="guess-button" id="{{ char }}" value ="{{ char }}">{{ char | upper }}</button>
{% endfor %}
<br/>
<br/>
WORD: <span id="displayedLetters">{{ placeholder }}</span>
<script>
function sendValueEvent(event) {
event.preventDefault();
buttonValue = event.target.value;
sendValue(buttonValue);
}
function sendValue(buttonValue) {
fetch('/button', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ value: buttonValue }),
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
document.querySelector('#displayedLetters').textContent = data.correct_letters;
}else {
console.error('Error processing guess:', data);
}
})
}
</script>
</body>
</html>''', placeholder=placeholder)
def hangman(guess, session):
guesses_left = session['guesses_left']
guessed_letters = session['guessed_letters']
correct_letters = session['correct_letters']
game_over = session['game_over']
database_word = session['database_word']
guessed_letters = guessed_letters + guess
correct_letters = ""
if guess not in database_word:
guesses_left -= 1
session['guesses_left'] = guesses_left
if guesses_left == 0:
session['game_over'] = 1
return game_over
for letter in database_word:
if letter in guessed_letters:
correct_letters += f"{letter} "
else:
correct_letters += "_ "
session['correct_letters'] = correct_letters
session['guessed_letters'] = guessed_letters
print("cookie", session['correct_letters'])
if all(letter in guessed_letters for letter in database_word):
session['game_over'] = 2
if __name__ == '__main__':
app.debug = True
app.run()