For a project, I'm currently trying to create a game (a variation of the Hangman) in python using Flask to make it accessible on an html page. This game is destined to be used by deaf children to improve their written french.
It's my first time using Flask or any python web framework really (I started python a few months ago). My game uses a txt file as a database. This file contains words that are classified by difficulty (easy, medium, hard). I was able to create 3 pages : menu.html, choisir_diff.html and commencer_partie.html.
Here are the functions in my python file (main.py) :
from flask import Flask, render_template, request, redirect, url_for, session
import random
import math
app = Flask(__name__)
app.secret_key = 'your_secret_key'
def liste_mots(path_file):
dico = {"Facile" : [], "Moyen" : [], "Difficile" : []}
with open(path_file, "r") as fichier:
for mot in fichier:
mot = mot.strip()
if not mot:
continue
if mot in ["Facile", "Moyen", "Difficile"]:
difficulte = mot
else:
dico[difficulte].append(mot)
#print(dico)
return dico
@app.route('/')
def menu():
return render_template("menu.html")
@app.route('/choisir_diff/<difficulte>')
def choisir_diff(difficulte):
dico = liste_mots("mots.txt")
mots = dico[difficulte]
return render_template('choisir_diff.html', difficulte=difficulte, mots=mots)
The menu displays the three levels of difficulty, the choisir_diff one allows the user to choose a word among a list, and the commencer_partie one is supposed to "launch the game". The idea is that the computer will try to guess the chosen word by sending letters to the user who'll answer yes (if the letter is in the chosen word) or no (if it isn't). When the computer guesses 3/5 of the word's letters, or when it reaches 8 tries, it starts sending words to the user instead. If one of these words is the chosen one then the computer has won !
The choice of the letters and words sent by the computer are made in a while loop. I notably try to anticipate short words, ask the computer to first suggest very common letters and choose when to start sending words instead of letters. My loop may not be perfect but it seems to work when I isolate it in another file and print my values at each turn of the loop. Here is my while loop (I gave the variables English names !) :
word_dict = liste_mot("mots.txt")
selected_words = word_dict["Difficult"]
letters = list(selected_word)
word_length = len(letters)
letter_limit = math.floor(0.6 * len(letters))
print(letter_limit)
guessed_letters = ["_"] * word_length
common_letters = list("eastirnulodmcpévhgfb")
uncommon_letters = list("qjàxèêzykôûwâîüùëœçï")
alphabet = list("eastirnulodmcpévhgfbqjàxèêzykôûwâîüùëœçï")
current_turn = 0
while (true_guessed_letters := len(guessed_letters) - guessed_letters.count("_")) < letter_limit and current_turn < 9:
print(f"true_guessed_letters: {true_guessed_letters}")
print(f"guessed_letters: {guessed_letters}")
print(f"hangman traits: {current_turn}")
print("-" * 50)
if len(letters) > 6:
if true_guessed_letters < 5 and any(c in common_letters for c in letters):
computer_choice = random.choice(common_letters)
current_letter = computer_choice
session['current_letter'] = current_letter
if computer_choice in letters:
indices = [i for i, letter in enumerate(letters) if letter == computer_choice]
for index in indices:
guessed_letters[index] = computer_choice
common_letters.remove(computer_choice)
alphabet.remove(computer_choice)
print(guessed_letters)
else:
current_turn += 1
common_letters.remove(computer_choice)
alphabet.remove(computer_choice)
else:
computer_choice = random.choice(alphabet)
current_letter = computer_choice
session['current_letter'] = current_letter
print(f"alphabet letter choice: {computer_choice}")
if computer_choice in letters:
indices = [i for i, letter in enumerate(letters) if letter == computer_choice]
for index in indices:
guessed_letters[index] = computer_choice
alphabet.remove(computer_choice)
else:
current_turn += 1
alphabet.remove(computer_choice)
elif len(letters) < 5:
if true_guessed_letters < 3 and any(c in uncommon_letters for c in letters if c != "_") and uncommon_letters:
computer_choice = random.choice(uncommon_letters)
current_letter = computer_choice
session['current_letter'] = current_letter
if computer_choice in letters:
indices = [i for i, letter in enumerate(letters) if letter == computer_choice]
for index in indices:
guessed_letters[index] = computer_choice
uncommon_letters.remove(computer_choice)
alphabet.remove(computer_choice)
else:
current_turn += 1
uncommon_letters.remove(computer_choice)
alphabet.remove(computer_choice)
else:
computer_choice = random.choice(alphabet)
current_letter = computer_choice
session['current_letter'] = current_letter
if computer_choice in letters:
indices = [i for i, letter in enumerate(letters) if letter == computer_choice]
for index in indices:
guessed_letters[index] = computer_choice
alphabet.remove(computer_choice)
else:
current_turn += 1
alphabet.remove(computer_choice)`
# The computer starts trying to guess words if the number of turns reaches 8 or if 3/5 of the letters have been guessed.
# Possible words to be guessed are those containing all the guessed letters so far (ignoring their positions for simplicity).
# Possible words to be guessed are also those of the same length as the chosen one.
`
possible_words = [word for word in word_dict if all(letter in word if letter != '_' else True for letter in guessed_letters)]
possible_words = [word for word in possible_words if len(word) == len(letters)]
print(possible_words)
while current_turn < 11:
if possible_words:
computer_word_choice = random.choice(possible_words)
current_word = computer_word_choice
session['current_word'] = current_word
print(f"hangman traits: {current_turn}")
print(f"Computer word attempt: {computer_word_choice}")
if computer_word_choice != selected_word:
current_turn += 1
else:
break
Now, The idea would be that on my commencer_partie page, I have a button "let's go" that would display the first letter (so the value of current_letter in the first turn of the loop). The user could then click on a button "yes" or a button "no" and they would be redirected to another page with the next guessed letter (so the value of current_letter in the second turn of the loop). The same process would be repeated until we reach 10 current_turn (so when the hangman drawing will be completed, of course I haven't reached that step yet).
How can I do that ? I tried creating a new function display_letter that would get the values of the loop current turn to display it on screen. I did that using 'session' and the lines : session.get('current_letter', ' '), session.get('current_word', ' '), session.get('current_turn', ' '). However, these values appear empty when I try to print them (they take the default form ' ' or are just None when I take off that default value).
How could I achieve my desired result ? And if I do create a display_function, how will the exchange between it and my loop will be handled ? How will it appear in my display_function.html ?
Thank you very much and I apologize for the LOOOOOOOOOOOOOONG text ! Thanks !