0

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 !

1 Answer 1

0

Due to the architecture of a web application and a loop, it is not possible to stop a while loop and extract values at a certain point in time.

The architecture of a web application consists of requests from the browser, which are answered by the server. However, you can use this process to keep a kind of loop going. To do this, you send requests to the same endpoint for as long as the loop should run. Each request corresponds to one iteration step. Session storage can be used to maintain variables across multiple requests. If you want to break the so-called loop, you can redirect the user to another page.

The following example illustrates the approach described.

from flask import (
    Flask, 
    redirect, 
    render_template_string, 
    request, 
    session, 
    url_for
)

app = Flask(__name__)
app.secret_key = 'your secret here'

@app.route('/')
def start():
    session['i'] = 0
    return redirect(url_for('step'))

@app.route('/step', methods=['GET', 'POST'])
def step():
    if 'i' not in session:
        return redirect(url_for('start'))

    i = int(session['i'])

    if request.method == 'POST':

        i += 1

        should_continue = request.form.get('continue', False, type=bool)
        if not should_continue or i >= 10:
            return redirect(url_for('end'))

        session['i'] = i 

        return redirect(request.url)

    return render_template_string('''
        <p>Current index is {{i}}<br/>Should the loop break?</p>
        <form method="post">
            <button type="submit" name="continue" value="">Break</button>
            <button type="submit" name="continue" value="true">Continue</button>
        </form>
        ''', **locals())

@app.route('/end')
def end():
    if 'i' not in session:
        return redirect(url_for('start'))

    i = session['i']
    return render_template_string('''
        <p>You left the loop at {{ i }}.</p>
        <a href="{{ url_for('start') }}">Try once more.</a>
        ''', **locals())
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.