Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

tkinter word guessing game/hangman

menator01

Gold Coder
Enjoy
Python:
#! /usr/bin/env python3
# Do the imports
import random as rnd
import tkinter as tk
from tkinter import messagebox
import os
import sys
import requests


class Stats:
    ''' Class for keeping stats '''
    wins = 0
    loss = 0
    games = 0
    tries = 0
    remaining = 0

    def __str__(self):
        return f'Stats: Wins: {Stats.wins} / Loss: {Stats.loss} / Games Played: {Stats.games} / Tries Left: {Stats.tries}'

class Model:
    '''
        Model for getting a word list from internet
        Creates a list from returned results
        Grabs a random word from the list
        Checks user entered letter against the word
    '''
    url = 'https://raw.githubusercontent.com/dwyl/english-words/master/words_alpha.txt'
    response = requests.get(url)
    words = response.text.split('\r\n')


    def __init__(self):
        self.wordlist = Model.words

    def random_word(self):
        word = self.wordlist.pop(rnd.randint(0, len(self.wordlist)-1))
        return word

    def find(self, letter, word, letters):
        match = [i for i, x in enumerate(word) if x == letter]
        if match:
            for i in match:
                letters[i] = letter
                Stats.remaining -= 1
        return ' '.join(letters)


class View:
    '''
        View is for showing the game window
    '''
    def __init__(self, parent):
        self.parent = parent
        self.parent.columnconfigure(0, weight=1)
        self.parent.rowconfigure(0, weight=0)
        self.parent.rowconfigure(1, weight=0)
        self.parent.rowconfigure(2, weight=0)
        self.parent.rowconfigure(3, weight=1)


        # Setup the header
        header_box = tk.Frame(self.parent)
        header_box.grid(column=0, row=0, sticky='new', padx=5, pady=5)
        header_box.grid_columnconfigure(0, weight=3)

        header = tk.Label(header_box, text='Tkinter Word Game')
        header['font'] = (None, 28, 'bold')
        header.grid(column=0, row=0, sticky='new')

        # Setup stats row
        stats_box = tk.Frame(self.parent)
        stats_box['highlightbackground'] = 'black'
        stats_box['highlightcolor'] = 'black'
        stats_box['highlightthickness'] = 1
        stats_box.grid(column=0, row=1, sticky='new', padx=5, pady=5)
        stats_box.grid_columnconfigure(0, weight=3)

        self.stats = tk.Label(stats_box, anchor='w')
        self.stats['font'] = (None, 10, 'bold')
        self.stats['text'] = Stats()
        self.stats.grid(column=0, row=0, sticky='new', padx=5, pady=5)

        word_box = tk.Frame(self.parent)
        word_box['highlightbackground'] = 'black'
        word_box['highlightcolor'] = 'black'
        word_box['highlightthickness'] = 1
        word_box.grid(column=0, row=2, sticky='new', padx=5, pady=5)
        word_box.grid_columnconfigure(0, weight=0)
        word_box.grid_columnconfigure(1, weight=3)

        label = tk.Label(word_box, text='Random Word: ', anchor='w')
        label['font'] = (None, 10, 'bold')
        label.grid(column=0, row=0, sticky='new', padx=2.5, pady=5)

        self.word = tk.Label(word_box, anchor='w')
        self.word['font'] = (None, 10, 'normal')
        self.word.grid(column=1, row=0, sticky='new', padx=(2.5,5), pady=5)

        # Letter/Button row
        btn_box = tk.Frame(self.parent)
        btn_box['highlightbackground'] = 'black'
        btn_box['highlightcolor'] = 'black'
        btn_box['highlightthickness'] = 1
        btn_box.grid(column=0, row=3, sticky='new', padx=5, pady=5)

        btn_box.grid_columnconfigure(0, weight=1, uniform='btn')
        btn_box.grid_columnconfigure(2, weight=1, uniform='btn')
        btn_box.grid_columnconfigure(3, weight=1, uniform='btn')
        btn_box.grid_columnconfigure(1, weight=3)

        self.letter_btn = tk.Button(btn_box, text='Submit Letter', bg='powderblue')
        self.letter_btn['cursor'] = 'hand2'
        self.letter_btn['activebackground'] = 'skyblue'
        self.letter_btn['activeforeground'] = 'blue'
        self.letter_btn.grid(column=0, row=0, sticky='new', pady=5, padx=(5,2.5))

        self.entry = tk.Entry(btn_box)
        self.entry['font'] = (None, 14, 'normal')
        self.entry.grid(column=1, row=0, sticky='new', pady=5, padx=2.5)
        self.entry.focus()

        self.btn_new = tk.Button(btn_box, text='New Word', bg='powderblue')
        self.btn_new['cursor'] = 'hand2'
        self.btn_new['activebackground'] = 'skyblue'
        self.btn_new['activeforeground'] = 'blue'
        self.btn_new.grid(column=2, row=0, sticky='new', pady=5, padx=2.5)

        self.exit_btn = tk.Button(btn_box, text='Quit', bg='tomato')
        self.exit_btn['activebackground'] = 'red'
        self.exit_btn['activeforeground'] = 'white'
        self.exit_btn['cursor'] = 'hand2'
        self.exit_btn.grid(column=3, row=0, sticky='new', pady=5, padx=(2.5, 5))


class Controller:
    '''
        Controller class for communictions between the Model and View classes
    '''
    def __init__(self, view, model):
        self.view = view
        self.model = model
        self.word = self.model.random_word()
        self.letters = ['-']*len(self.word)
        self.view.word['text'] = self.letters
        Stats.tries = len(self.word) - round(len(self.word)/2)
        Stats.remaining = len(self.word)
        self.view.stats['text'] = Stats()

        # Buttons
        self.view.letter_btn['command'] = lambda: self.find(self.view.entry.get())
        self.view.btn_new['command'] = self.new
        self.view.exit_btn['command'] = self.view.parent.destroy

        # Button Binds
        self.view.parent.bind('<Return>', lambda letter: self.find(letter=self.view.entry.get()))
        self.view.parent.bind('<KP_Enter>', lambda letter: self.find(letter=self.view.entry.get()))


    def new(self):
        Stats.alist = []
        self.view.letter_btn['state'] = 'normal'
        self.view.entry['state'] = 'normal'
        self.word = self.model.random_word()
        self.letters = ['-']*len(self.word)
        self.view.word['text'] = self.letters
        Stats.tries = len(self.word) - round(len(self.word)/2)
        Stats.remaining = len(self.word)
        self.view.stats['text'] = Stats()
        self.view.entry.delete(0, tk.END)

    def find(self, letter):
        done = False
        if not letter or letter.isdigit():
            messagebox.showerror('Error', 'You must enter a letter')
            self.view.entry.delete(0, tk.END)
            Stats.tries += 1

        if len(letter) > 1:
            messagebox.showerror('Error!', 'Only one character can be entered at a time.')
            self.view.entry.delete(0, tk.END)
            Stats.tries += 1

        letter = letter.lower()
        found = self.model.find(letter, self.word, self.letters)

        if letter not in found:
            Stats.tries -= 1
            self.view.entry.delete(0, 'end')

            if Stats.tries == 0:
                self.view.letter_btn['state'] = 'disabled'
                self.view.entry['state'] = 'disabled'
                Stats.games += 1
                done = True
                self.game_over()
        else:
            self.view.entry.delete(0, 'end')
            if Stats.remaining == 0:
                self.view.letter_btn['state'] = 'disabled'
                self.view.entry['state'] = 'disabled'
                Stats.games += 1
                self.game_win()

        self.view.stats['text'] = Stats()
        if done:
            self.view.word['text'] = self.word
        else:
            self.view.word['text'] = found

    def game_over(self):
        messagebox.showinfo('Game Over!', 'You are out of guesses.')
        Stats.loss += 1
        

    def game_win(self):
        messagebox.showinfo('Congradulations!', 'You got the word!')
        Stats.wins += 1


if __name__ == '__main__':
    root = tk.Tk()
    root.title('Word Guessing Game')
    root.geometry('+300+300')
    controller = Controller(View(root), Model())
    root.mainloop()
 

New Threads

Latest posts

Buy us a coffee!

Back
Top Bottom