Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Drawing.Imaging;
- using System;
- using System.Drawing;
- using System.Linq;
- using System.Web.Mvc;
- namespace Blah
- {
- public class HangmanController : Controller
- {
- public ActionResult Index()
- {
- var game = Session["hangman"] as HangmanGame ?? HangmanGame.New();
- game = ExecuteGameCommand(game);
- Session["hangman"] = game;
- var imageRenderer = new HangmanImageRenderer(game);
- return new ImageResult(imageRenderer.Render());
- }
- private HangmanGame ExecuteGameCommand(HangmanGame game)
- {
- var referrerQuery = Request.UrlReferrer != null ? Request.UrlReferrer.Query : string.Empty;
- if (referrerQuery.Contains("_new_hangman_"))
- return HangmanGame.New();
- if (game.IsOver())
- return game;
- var chosenLetter = HangmanGame.ValidLetters
- .FirstOrDefault(letter => referrerQuery.Contains(String.Format("_hangman_{0}_", letter)));
- if (chosenLetter != default(char))
- game.RegisterGuess(chosenLetter);
- return game;
- }
- }
- public class HangmanImageRenderer
- {
- private const int ImageWidth = 500;
- private const int ImageHeight = 150;
- private const int LetterDistance = 10;
- private static readonly Pen Pen = new Pen(Brushes.Black, 3);
- private static readonly Font Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
- private static readonly Font MonospaceFont = new Font(FontFamily.GenericMonospace, 10, FontStyle.Regular);
- private static readonly Font TitleFont = new Font(FontFamily.GenericSansSerif, 15, FontStyle.Bold);
- private readonly HangmanGame _game;
- public HangmanImageRenderer(HangmanGame game)
- {
- _game = game;
- }
- public Image Render()
- {
- var image = new Bitmap(ImageWidth, ImageHeight);
- using (var g = Graphics.FromImage(image))
- {
- DrawWhiteCanvas(g);
- DrawBorder(g);
- WriteTitle(g);
- DrawHang(g);
- DrawMan(g);
- DrawUsedLetters(g);
- DrawPuzzleText(g, _game.Guessed);
- if (_game.IsWon())
- DrawGameWonMessage(g);
- if (_game.IsLost())
- {
- DrawGameLostMessage(g);
- DrawPuzzleText(g, _game.Solution);
- }
- }
- return image;
- }
- private static void DrawWhiteCanvas(Graphics g)
- {
- g.FillRectangle(Brushes.White, 0, 0, ImageWidth, ImageHeight);
- }
- private static void DrawBorder(Graphics g)
- {
- g.DrawRectangle(Pen, 0, 0, ImageWidth, ImageHeight);
- }
- private static void WriteTitle(Graphics g)
- {
- g.DrawString("StackExchange Hangman", TitleFont, Brushes.DodgerBlue, 10, 10);
- }
- private static void DrawHang(Graphics g)
- {
- g.DrawLine(Pen, 400, 10, 400, 15);
- g.DrawLine(Pen, 400, 10, 475, 10);
- g.DrawLine(Pen, 475, 10, 475, 110);
- }
- private void DrawMan(Graphics g)
- {
- if (_game.WrongAttempts > 0)
- {
- g.DrawArc(Pen, 390, 15, 20, 20, 0, 360);
- g.DrawLine(Pen, 397, 20, 397, 25);
- g.DrawLine(Pen, 403, 20, 403, 25);
- }
- if (_game.WrongAttempts > 1)
- g.DrawLine(Pen, 400, 35, 400, 75);
- if (_game.WrongAttempts > 2)
- g.DrawLine(Pen, 400, 40, 380, 60);
- if (_game.WrongAttempts > 3)
- g.DrawLine(Pen, 400, 40, 420, 60);
- if (_game.WrongAttempts > 4)
- g.DrawLine(Pen, 400, 75, 380, 105);
- if (_game.WrongAttempts > 5)
- g.DrawLine(Pen, 400, 75, 420, 105);
- }
- private void DrawUsedLetters(Graphics g)
- {
- if (String.IsNullOrEmpty(_game.UsedLetters))
- return;
- g.DrawString(
- "Used Letters: " + String.Join(",", _game.UsedLetters.Select(c => c).OrderBy(c => c)),
- Font,
- Brushes.DarkGray,
- 10, 100);
- }
- private static void DrawPuzzleText(Graphics g, string text)
- {
- for (var i = 0; i < text.Length; i++)
- {
- g.DrawString(
- text.Substring(i, 1),
- MonospaceFont, Brushes.Black, (i + 1) * LetterDistance, 125);
- }
- }
- private static void DrawGameWonMessage(Graphics g)
- {
- g.DrawString("Contratulations! You won!", TitleFont, Brushes.DarkGreen, 10, 55);
- }
- private static void DrawGameLostMessage(Graphics g)
- {
- g.DrawString("You lost!", TitleFont, Brushes.DarkRed, 10, 55);
- }
- }
- [Serializable]
- public class HangmanGame
- {
- public const string ValidLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- public string Solution { get; set; }
- public string Guessed { get; set; }
- public string UsedLetters { get; set; }
- public int WrongAttempts { get; set; }
- public static HangmanGame New()
- {
- var randomWord = Dictionary[new Random().Next(Dictionary.Length)].ToUpperInvariant();
- return new HangmanGame
- {
- Solution = randomWord,
- Guessed = MaskLetters(randomWord),
- UsedLetters = String.Empty,
- WrongAttempts = 0
- };
- }
- private static string MaskLetters(string source)
- {
- return new String(source.Select(c => char.IsLetter(c) ? '_' : c).ToArray());
- }
- public void RegisterGuess(char chosenLetter)
- {
- if (!ValidLetters.Contains(chosenLetter) ||
- UsedLetters.Contains(chosenLetter))
- return;
- UsedLetters += chosenLetter;
- if (!Solution.Contains(chosenLetter))
- WrongAttempts++;
- else
- Guessed = new string(
- Solution.Zip(Guessed, (s, g) => s == chosenLetter ? chosenLetter : g).ToArray());
- }
- public bool IsOver()
- {
- return IsWon() || IsLost();
- }
- public bool IsWon()
- {
- return !Guessed.Contains('_');
- }
- public bool IsLost()
- {
- return WrongAttempts > 5;
- }
- private static readonly string[] Dictionary = new[]
- {
- "Stack Overflow", "Server Fault", "Super User", "Meta Stack Overflow"
- , "Web Applications", "Gaming", "Webmasters",
- "Cooking", "Game Development", "Photography", "Statistical Analysis",
- "Mathematics", "Home Improvement", "GIS",
- "TeX - LaTeX", "Ask Ubuntu", "Personal Finance and Money",
- "English Language and Usage", "Stack Apps",
- "User Experience", "Unix and Linux", "WordPress",
- "Theoretical Computer Science", "Apple", "Role-playing Games",
- "Bicycles", "Programmers", "Electrical Engineering",
- "Android Enthusiasts", "OnStartups", "Board and Card Games",
- "Physics", "Homebrewing", "IT Security", "Writers",
- "Audio-Video Production", "Graphic Design",
- "Database Administrators", "Science Fiction and Fantasy",
- "Code Review", "Code Golf", "Quantitative Finance",
- "Project Management", "Skeptics", "Fitness and Nutrition",
- "Drupal Answers",
- "Motor Vehicle Maintenance and Repair", "Parenting", "SharePoint",
- "Musical Practice and Performance",
- "Software Quality Assurance and Testing", "Mi Yodeya",
- "German Language and Usage", "Japanese Language and Usage",
- "Philosophy", "Gardening and Landscaping", "Travel",
- "Personal Productivity", "Cryptography", "Signal Processing",
- "French Language and Usage", "Christianity", "Bitcoin", "Linguistics"
- , "Biblical Hermeneutics", "History",
- "LEGO® Answers", "Spanish Language and Usage",
- "Computational Science", "Movies and TV",
- "Chinese Language and Usage", "Biology", "Poker", "Mathematica",
- "Cognitive Sciences", "The Great Outdoors",
- "SmugMug", "Martial Arts", "Sports", "Academia", "Computer Science",
- "The Workplace", "Windows Phone",
- "Chemistry", "Chess"
- };
- }
- public class ImageResult : ActionResult
- {
- public ImageResult(Image image)
- {
- if (image == null)
- throw new ArgumentNullException("image");
- _image = image;
- }
- private readonly Image _image;
- public override void ExecuteResult(ControllerContext context)
- {
- if (context == null)
- throw new ArgumentNullException("context");
- var response = context.HttpContext.Response;
- response.ContentType = "image/gif";
- _image.Save(response.OutputStream, ImageFormat.Gif);
- response.End();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement