## Making a Hangman

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
td1801
Prole
Posts: 7
Joined: Sat Jul 05, 2014 1:35 pm
Location: Haute Normandie, France

### Making a Hangman

Hi !
I'm new here, I'm not a programmer and I'm french. So I guess It will be hard for me to understand everything ! If you can't understand one of my sentence, I'll try my best to explain it to you.
Anyway yesterday I started to do a Hangman game with löve, and I was surprised (and proud ) to achieve to do a "working" program. But I can't think of a way to do one thing : the error counter. I tried to increment the error counter when a key is pressed and the character isn't one of the word but it increment the variable too much. I don't know where that come from or how I could resolve this..
Here is the .love :https://www.mediafire.com/?53s7crw5h97999e
And here's my code, that I tried my best to comment :

Code: Select all

 --HANGMAN 03-07-2014

function dictionnaire() --Choose a word and return it's length and a string.
local rowIndex =0
local wordList = {}
--The list of words used in the hangman
dictionnaire = [[abricot
absent
boule
boisson
bombardier
copain
captif
constitution
dent
fleurs
gourmand]]
--Selecting a random word
local line = math.random(1,11)
for row in dictionnaire:gmatch ("[^\n]+") do
rowIndex = rowIndex+1
wordList[rowIndex] = row
end

word = wordList[line]
length = string.len(word)
return word, length
end

function love.keypressed(key)
if key and key:match( '%a' ) then character = key end
end

function love.load () --Initialise the variables
character = "*"
victoryCount = 0
characterTable = {}
math.randomseed(os.time())
word, length = dictionnaire()
--CONVERT TABLE INTO _
for i=0,length do
i = i+1
characterTable[i-1] = "_"
end
life = 11
end

function love.update ()

-- Check if the key pressed is in the word
if character ~= "*" then
local i = 0
local o = 0
for letter in word:gmatch ("%a") do
i=i+1
if letter == character then
characterTable[i]= character
elseif letter ~= character and character ~= "*" then ---Here is the problem..
life = life -1
end
end
victoryCount = 0
for letter in word:gmatch ("%a") do --Check the number of correct letters
o = o + 1
if characterTable[o] == letter then
victoryCount = victoryCount+1
end

end

character = "*"
end
--Make the table into a string
characterString = table.concat(characterTable, " ")

function love.draw ()
love.graphics.print (word,10,1)
love.graphics.print (characterString,10,12)
love.graphics.print (victoryCount,10,24)
love.graphics.print (life,300,24)
if victoryCount == #word then
love.graphics.print ("Victory :D",10,34)
end
if life <= 0 then
love.graphics.print ("Defeat",10,44)
end
end
Thank you for reading this !
SneakySnake
Citizen
Posts: 94
Joined: Fri May 31, 2013 2:01 pm
Contact:

### Re: Making a Hangman

You are decreasing life for each character that does not match the guessed letter.
That's not how hangman works.

In hangman, if your guess hits a letter, it's revealed.
If it does not hit any letters, your life decreases.

Code: Select all

local hit

for letter in word:gmatch ("%a") do
i = i + 1
if letter == character then
characterTable[i] = character
-- Our guess has hit a letter
hit = true
end
end

-- If we haven't hit a letter, we missed, so we decrease life
if not hit then
life = life - 1
end


td1801
Prole
Posts: 7
Joined: Sat Jul 05, 2014 1:35 pm
Location: Haute Normandie, France

### Re: Making a Hangman

Thank you for your answer, of course your solution works ! But I have to say that I'm not really seeing any difference in the logic ?
In both case if the letter wasn't good, it decrease life ? Well nevermind, I'll think more deeply about that. Thank you again
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

### Re: Making a Hangman

td1801 wrote:In both case if the letter wasn't good, it decrease life ?

In your original: for every letter, if it isn't good, decrease a life.

In SneakySnake's version: if there exists at least one letter that isn't good, decrease a life.

I'm guessing you don't have a background in formal logic either, because that can be counter-intuitive at first, but it'll "click" eventually, if you keep at it.
Help us help you: attach a .love.
td1801
Prole
Posts: 7
Joined: Sat Jul 05, 2014 1:35 pm
Location: Haute Normandie, France

### Re: Making a Hangman

Ok, thank you very much. I just understood, It was simple in fact x)
td1801
Prole
Posts: 7
Joined: Sat Jul 05, 2014 1:35 pm
Location: Haute Normandie, France

### Re: Making a Hangman

So I'm making a double post, because I have another problem. I searched the forum but I didn't find goods keywords I guess ("function" "string" "update" and "error" are not very precise one x)) ! Because of that I wasn't sure that it needed another post ? And since it's not only an addition to my precedent post, I think it's not against the guidelines ? If it is, i'm sorry

Anyway my problem is that when I call a function I get an error message :
"attempt to call global "dictionnaire" : a string value
But a string is exactly what I want

My function :

Code: Select all

function dictionnaire() --Choose a word and return it's length and a string.
local rowIndex =0
local wordList = {}
dictionnaire = [[
aaa
bbb
word
stuff
]]

local line = math.random(1,3)
for row in dictionnaire:gmatch ("[^\n]+") do
rowIndex = rowIndex+1
wordList[rowIndex] = row
end

word = wordList[line]
length = string.len(word)
return word, length
end

and where I call it

Code: Select all

function love.update()
--[[...]]--
if 	prgmEnd == true and character == "return" then
character = "*"
victoryCount = 0
errorCount = 0
characterTable = {}
errorTable = {}
math.randomseed(os.time())
word, length = dictionnaire() -- "attempt to call global "dictionnaire" : a string value "
timer1 = 0
timer2 = 0
timer3 = 0
timer4 = 0
timer5 = 0

for i=0,length do
i = i+1
characterTable[i-1] = "_"
end
character = "*"
prgmEnd = false
end
end
I made some test and I think the problem is that I call my function in the update Callback ? But why ?
Thank you !
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

### Re: Making a Hangman

You gave the function and the string the same name, and that doesn't work. If you replace the line

Code: Select all

dictionnaire = [[
by

Code: Select all

local dictionnaire = [[
it should work. (The string dictionnaire is now local to that function, and so doesn't overwrite the global dictionnaire.)
Help us help you: attach a .love.
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

### Re: Making a Hangman

The problem is that, inside the function dictionnaire, you overwrite the variable "dictionnaire". Here:

Code: Select all

function dictionnaire() --Choose a word and return it's length and a string.
-- [...]
dictionnaire = [[
aaa
bbb
word
stuff
]]
-- [...]
end
That means, the first time you call the function, everything is fine, but inside, you change "dictionnaire" and when you call it a second time, it is a string.
You can solve the problem by renaming one of the two things, the function or the string.

One practical advice: I highly suggest renaming the function so that the name tells you, what it is doing. How about "pickRandomWord()"?

And another small thing you can improve: Rather than saving all of the words in one long string, separated by new-line-characters, you can better store it in a table. The function can then be shortened a bit:

Code: Select all

function pickRandomWord()
local dictionnaire = {'aaa','bbb','word','stuff'}
local index = love.math.random(1,#dictionnaire)
local word = dictionnaire[index]
local length = #word
return word,length
end

Or even shorter (and less readable)

Code: Select all

function pickRandomWord()
local dictionnaire = {'aaa','bbb','word','stuff'}
local word = dictionnaire[love.math.random(1,#dictionnaire)]
return word, #word
end

Robin was faster.
td1801
Prole
Posts: 7
Joined: Sat Jul 05, 2014 1:35 pm
Location: Haute Normandie, France

### Re: Making a Hangman

Thank both of you so much
Now it's working perfectly ! (And I'm so proud of this little crappy things that I'm finding myself strange !)
micha wrote:One practical advice: I highly suggest renaming the function so that the name tells you, what it is doing. How about "pickRandomWord()"?
Thank you for the advice ! That's definetely less confusing !
micha wrote:And another small thing you can improve: Rather than saving all of the words in one long string, separated by new-line-characters, you can better store it in a table.
Yep, But I chose the string because it was easier to add word (And it have learned me some useful things !)

### Who is online

Users browsing this forum: darkfrei, mk8 and 9 guests