Advertisement
Inksaver

Hangman Lua 5.1

Sep 28th, 2014
500
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.63 KB | None | 0 0
  1. -- Hangman console version Lua 5.1
  2. -- http://pastebin.com/GbctjwVe
  3. -- get dictionary.txt from github or elsewhere call it "dictionary.txt" in same folder as script
  4. -- https://github.com/dmcguinness/Hangman/blob/master/dictionary.txt
  5.  
  6. version = "1.0"
  7.  
  8. function createDictionaryObject()
  9.     clsDictionary = {} -- the table representing the class, which will double as the metatable for any instances
  10.     clsDictionary.__index = clsDictionary -- failed table lookups on the instances should fallback to the class table, to get methods
  11.  
  12.     local self = setmetatable({}, clsDictionary)
  13.     local fso = ""
  14.     local line = ""
  15.     local lenLine = 0
  16.     local newIndex = 0
  17.  
  18.     self.report = "" -- no error so nothing to report
  19.  
  20.     fso = (io.open("dictionary.txt", "r")) -- check if dictionary file in place
  21.     if fso ~= nil then
  22.         self.wordLength = {} -- define table
  23.         for i = 1,25 do -- create 25 tables within the wordLength{} table
  24.             self.wordLength[i] = {}
  25.         end
  26.  
  27.         for line in fso:lines() do   -- read each line in dictionary and put into correct list
  28.             lenLine = #line
  29.             if lenLine > 0 then -- ignore empty lines
  30.                 newIndex = #self.wordLength[lenLine] + 1
  31.                 if string.find(line, "-") == nil then -- ignore hyphenated words
  32.                     self.wordLength[lenLine][newIndex] = line
  33.                 end
  34.             end
  35.         end
  36.         fso:close() -- close text file
  37.  
  38.     else -- file missing
  39.         self.report = "File 'dictionary.txt' not found"
  40.     end
  41.  
  42.     function clsDictionary.getError(self) -- property get: error text
  43.         return self.report
  44.     end
  45.  
  46.     function clsDictionary.getWord(self, length) -- method: get a word from the dictionary
  47.         local returnValue = ""
  48.        
  49.         if length > 0 and length < 26 then -- word must be between 1 and 25 characters
  50.             listLength = #self.wordLength[length]
  51.             if listLength > 0 then
  52.                 returnValue = string.upper(self.wordLength[length][math.random(1, listLength)])
  53.             end
  54.         else
  55.             self.report = "Error: word length requested = 0 or > 25"
  56.         end
  57.        
  58.         return returnValue
  59.     end
  60.  
  61.     return self
  62. end
  63.  
  64. function createHangmanObject()
  65.     clsHangman = {} -- the table representing the class, which will double as the metatable for any instances
  66.     clsHangman.__index = clsHangman -- failed table lookups on the instances should fallback to the class table, to get methods
  67.  
  68.     --[[
  69.         0_________________
  70.         1|    _________  |
  71.         2|    | /     |  |
  72.         3|    |/      O  |
  73.         4|    |      /|\ |
  74.         5|    |       |  |
  75.         6|    |      / \ |
  76.         7| ___|___       |
  77.         8|_______________|
  78.     ]]--
  79.     local self = setmetatable({}, clsHangman)
  80.     self.stage = 1
  81.     self.lettersAvailable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  82.     self.lettersChosen = ""
  83.     self.completed = false
  84.     self.progress = ""
  85.     self.fail = false
  86.     self.word = ""
  87.  
  88.     self.row = {{},{},{},{},{},{},{},{},{}} -- setup array elements for graphics
  89.     --stage 0 - new game
  90.     self.row[1][1] = "_________________"
  91.     self.row[2][1] = "|               |"
  92.     self.row[3][1] = "|               |"
  93.     self.row[4][1] = "|               |"
  94.     self.row[5][1] = "|               |"
  95.     self.row[6][1] = "|               |"
  96.     self.row[7][1] = "|               |"
  97.     self.row[8][1] = "|               |"
  98.     self.row[9][1] = "|_______________|"
  99.     -- stage 1 - 1 mistake
  100.     self.row[1][2] = "_________________"
  101.     self.row[2][2] = "|               |"
  102.     self.row[3][2] = "|               |"
  103.     self.row[4][2] = "|               |"
  104.     self.row[5][2] = "|               |"
  105.     self.row[6][2] = "|               |"
  106.     self.row[7][2] = "|               |"
  107.     self.row[8][2] = "| _______       |"
  108.     self.row[9][2] = "|_______________|"
  109.     -- stage 2 - 2 mistakes
  110.     self.row[1][3] = "_________________"
  111.     self.row[2][3] = "|               |"
  112.     self.row[3][3] = "|    |          |"
  113.     self.row[4][3] = "|    |          |"
  114.     self.row[5][3] = "|    |          |"
  115.     self.row[6][3] = "|    |          |"
  116.     self.row[7][3] = "|    |          |"
  117.     self.row[8][3] = "| ___|___       |"
  118.     self.row[9][3] = "|_______________|"
  119.  
  120.     self.row[1][4] = "_________________"
  121.     self.row[2][4] = "|    _________  |"
  122.     self.row[3][4] = "|    | /        |"
  123.     self.row[4][4] = "|    |/         |"
  124.     self.row[5][4] = "|    |          |"
  125.     self.row[6][4] = "|    |          |"
  126.     self.row[7][4] = "|    |          |"
  127.     self.row[8][4] = "| ___|___       |"
  128.     self.row[9][4] = "|_______________|"
  129.  
  130.     self.row[1][5] = "_________________"
  131.     self.row[2][5] = "|    _________  |"
  132.     self.row[3][5] = "|    | /     |  |"
  133.     self.row[4][5] = "|    |/         |"
  134.     self.row[5][5] = "|    |          |"
  135.     self.row[6][5] = "|    |          |"
  136.     self.row[7][5] = "|    |          |"
  137.     self.row[8][5] = "| ___|___       |"
  138.     self.row[9][5] = "|_______________|"
  139.  
  140.     self.row[1][6] = "_________________"
  141.     self.row[2][6] = "|    _________  |"
  142.     self.row[3][6] = "|    | /     |  |"
  143.     self.row[4][6] = "|    |/      O  |"
  144.     self.row[5][6] = "|    |          |"
  145.     self.row[6][6] = "|    |          |"
  146.     self.row[7][6] = "|    |          |"
  147.     self.row[8][6] = "| ___|___       |"
  148.     self.row[9][6] = "|_______________|"
  149.  
  150.     self.row[1][7] = "_________________"
  151.     self.row[2][7] = "|    _________  |"
  152.     self.row[3][7] = "|    | /     |  |"
  153.     self.row[4][7] = "|    |/      O  |"
  154.     self.row[5][7] = "|    |      /   |"
  155.     self.row[6][7] = "|    |          |"
  156.     self.row[7][7] = "|    |          |"
  157.     self.row[8][7] = "| ___|___       |"
  158.     self.row[9][7] = "|_______________|"
  159.  
  160.     self.row[1][8] = "_________________"
  161.     self.row[2][8] = "|    _________  |"
  162.     self.row[3][8] = "|    | /     |  |"
  163.     self.row[4][8] = "|    |/      O  |"
  164.     self.row[5][8] = "|    |      /|  |"
  165.     self.row[6][8] = "|    |          |"
  166.     self.row[7][8] = "|    |          |"
  167.     self.row[8][8] = "| ___|___       |"
  168.     self.row[9][8] = "|_______________|"
  169.  
  170.     self.row[1][9] = "_________________"
  171.     self.row[2][9] = "|    _________  |"
  172.     self.row[3][9] = "|    | /     |  |"
  173.     self.row[4][9] = "|    |/      O  |"
  174.     self.row[5][9] = "|    |      /|"..string.char(92) .." |" -- backspace causes printing errors so use ascii code
  175.     self.row[6][9] = "|    |          |"
  176.     self.row[7][9] = "|    |          |"
  177.     self.row[8][9] = "| ___|___       |"
  178.     self.row[9][9] = "|_______________|"
  179.  
  180.     self.row[1][10] = "_________________"
  181.     self.row[2][10] = "|    _________  |"
  182.     self.row[3][10] = "|    | /     |  |"
  183.     self.row[4][10] = "|    |/      O  |"
  184.     self.row[5][10] = "|    |      /|"..string.char(92) .." |"
  185.     self.row[6][10] = "|    |       |  |"
  186.     self.row[7][10] = "|    |          |"
  187.     self.row[8][10] = "| ___|___       |"
  188.     self.row[9][10] = "|_______________|"
  189.  
  190.     self.row[1][11] = "_________________"
  191.     self.row[2][11] = "|    _________  |"
  192.     self.row[3][11] = "|    | /     |  |"
  193.     self.row[4][11] = "|    |/      O  |"
  194.     self.row[5][11] = "|    |      /|"..string.char(92) .." |"
  195.     self.row[6][11] = "|    |       |  |"
  196.     self.row[7][11] = "|    |      /   |"
  197.     self.row[8][11] = "| ___|___       |"
  198.     self.row[9][11] = "|_______________|"
  199.     -- stage 11 - 11 mistakes - end of game
  200.     self.row[1][12] = "_________________"
  201.     self.row[2][12] = "|    _________  |"
  202.     self.row[3][12] = "|    | /     |  |"
  203.     self.row[4][12] = "|    |/      O  |"
  204.     self.row[5][12] = "|    |      /|"..string.char(92) .." |"
  205.     self.row[6][12] = "|    |       |  |"
  206.     self.row[7][12] = "|    |      / "..string.char(92) .." |"
  207.     self.row[8][12] = "| ___|___       |"
  208.     self.row[9][12] = "|_______________|"
  209.  
  210.  
  211.     function clsHangman.printStage(self) -- method: print graphics for current stage
  212.         for i = 1, 9 do
  213.             print(self.row[i][self.stage])
  214.         end
  215.         wordOut = ""
  216.         for i = 1, #self.progress do
  217.             wordOut = wordOut.." "..string.sub(self.progress, i, i)
  218.         end
  219.         print(wordOut)
  220.     end
  221.  
  222.     function clsHangman.setWord(self, newWord) -- property set: use word from clsDictionary object
  223.         local wordLength = #newWord
  224.  
  225.         self.word = newWord
  226.         self.progress = ""
  227.         for i = 1, wordLength do -- create a string of underscores as placeholders for letters
  228.             self.progress = self.progress..'_'
  229.         end
  230.     end
  231.  
  232.     function clsHangman.getWord(self) -- property get: current word used in game
  233.         return self.word
  234.     end
  235.  
  236.     function clsHangman.getLettersAvailable(self) -- property get: list of letters mot yet tried
  237.         return self.lettersAvailable
  238.     end
  239.  
  240.     function clsHangman.getLettersChosen(self) -- property get: list of letters already tried
  241.         return self.lettersChosen
  242.     end
  243.  
  244.     function clsHangman.getCompleted(self) -- property get: game complete, either pass or fail
  245.         return self.completed
  246.     end
  247.  
  248.     function clsHangman.checkGuess(self, guess) -- method: check letter entered by user
  249.         local front =""
  250.         local middle = ""
  251.         local endWord = ""
  252.         local sortTable = {}
  253.  
  254.         if string.find(self.lettersChosen, guess) == nil then -- letter not used before
  255.             if string.find(self.word, guess) ~= nil then -- letter is in game word!
  256.                 --add letter to self.progress (replace underscore characters with letters)
  257.                 position = string.find(self.word, guess) -- nil = not found, 1 = beginning
  258.                 while position ~= nil do -- found in game word
  259.                     if position == 1 then -- first letter of word, so substitute letter for first underscore
  260.                         front = guess
  261.                         middle = ""
  262.                         endWord = string.sub(self.progress, 2)
  263.                     else -- not first letter, calculate new string with letter in place of underscore
  264.                         front = string.sub(self.progress, 1, position - 1)
  265.                         middle = guess
  266.                         if position == #self.word then -- last letter.
  267.                             endWord = ""
  268.                         else
  269.                             endWord = string.sub(self.progress, position + 1)
  270.                         end
  271.                     end
  272.                     self.progress = front..middle..endWord
  273.                     position = string.find(self.word, guess, position + 1)
  274.                 end
  275.                 if string.find(self.progress, '_') == nil then -- game completed as all underscores are gone
  276.                     self.completed = true
  277.                 end
  278.             else
  279.                 --draw next stage of hangman
  280.                 if self.stage == 11 then -- game over, word not found
  281.                     self.fail = true
  282.                     self.completed = true
  283.                 end
  284.                 self.stage = self.stage + 1 -- make sure next / final graphic is drawn
  285.             end
  286.             self.lettersChosen = self.lettersChosen..guess
  287.             -- add last letter to string, convert to table, sort table and return to string
  288.             for i = 1, #self.lettersChosen do
  289.                 sortTable[i] = string.sub(self.lettersChosen, i, i)
  290.             end
  291.             table.sort(sortTable)
  292.             self.lettersChosen = ""
  293.             for k,v in ipairs(sortTable) do --rebuild string from table
  294.                 self.lettersChosen = self.lettersChosen..v
  295.             end
  296.  
  297.             position = string.find(self.lettersAvailable, guess) -- remove last letter from list of available letters
  298.             self.lettersAvailable = string.sub(self.lettersAvailable, 1, position - 1)..string.sub(self.lettersAvailable, position + 1)
  299.         end
  300.     end
  301.  
  302.     function clsHangman.getFail(self) -- property get: game over with fail :(
  303.         return self.fail
  304.     end
  305.  
  306.     return self
  307. end
  308.  
  309. function printMenu(wordlist, game)
  310.     local word  = ""
  311.  
  312.     os.execute('cls') -- clear screen
  313.     print("Welcome to Hangman version "..version)
  314.     word = wordlist:getWord(math.random(5, 15)) -- get a 5 to 15 word from the dictionary
  315.     game:setWord(word) -- pass it to the game
  316.     print("Guess the "..tostring(#game:getWord()).." letter word I have chosen")
  317. end
  318.  
  319. function play(game)
  320.     local doContinue = true
  321.  
  322.     repeat
  323.         game:printStage()
  324.         doContinue = true
  325.         print("Letters Used:"..game:getLettersChosen())
  326.         print("Letters Available: "..game:getLettersAvailable())
  327.         print()
  328.         repeat
  329.             io.write("Choose a letter: ")
  330.             guess = io.read('*l')
  331.             if #guess > 0 then
  332.                 if (string.byte(guess) > 64 and string.byte(guess) < 91) or (string.byte(guess) > 96 and string.byte(guess) < 123) then
  333.                     guess = string.upper(guess)
  334.                     doContinue = false
  335.                 end
  336.             end
  337.         until not doContinue
  338.         game:checkGuess(guess)
  339.     until game:getCompleted()
  340. end
  341.  
  342. function main()
  343.     local doContinue = true
  344.  
  345.     wordlist = createDictionaryObject() -- create instance of clsDictionary, which will read text file and sort into lists by word length
  346.     if wordlist:getError() == "" then -- no errors opening dictionary
  347.         while doContinue do
  348.             -- Lua random generator is buggy. This helps
  349.             math.randomseed(os.time())
  350.             math.random()
  351.             math.random()
  352.             game = createHangmanObject() -- create instance of clsHangman as a game object
  353.             printMenu(wordlist, game) -- print introduction and get word from dictionary object
  354.             play(game) -- play the game
  355.             game:printStage() -- print final stage
  356.             if game:getFail() then
  357.                 print ("Sorry you did not guess the word")
  358.                 print("it was: "..game:getWord())
  359.             else
  360.                 print("Well Done!")
  361.             end
  362.             io.write("Do you want to play again? Y/N >")
  363.             answer = io.read(1)
  364.             if string.upper(answer) ~= "Y" then -- any key to quit, Y to continue
  365.                 os.execute('cls')
  366.                 doContinue = false
  367.             end
  368.         end
  369.     else -- error opening dictionary. ? deleted/moved/renamed
  370.         print(wordlist:getError())
  371.     end
  372. end
  373. -- program runs from here
  374. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement