Word games in c programming

This is a word puzzle game which you might find in many puzzle books. Just good to have it on the machine with different words of different categories, and also to be able to play with custom words.

  • Download project with executable — 582.8 KB

Image 1

Background

I coded the game a long time ago using Turbo C. But I lost the code. I thought it would be great to revive it once more with C#.NET. The language offers a lot of flexibilities in terms of memory, GC, graphics, which I had to explicitly take care of when using C. But with explicit care in C, it offered a lot of learning (that’s why it is called ‘God’s programming language’). On the other hand, since C# .NET takes care of these, I could focus on other enhancements like word directions, overlaps, cheat codes, scoring, encryption, etc. So there is a balance that we need to appreciate for both languages.

I am calling it complete for the following reasons:

  1. It has preset words with some categories.
  2. It keeps the words and scores in encrypted files so that nobody can tamper with the files. If there is a tamper, then it would revert back to presets and start scoring from the beginning.
  3. It has two cheat codes, however cheating penalizes the scoring by deducting 50 from the current score.
  4. It has a scoring mechanism.
  5. It has a scoring summary so the player can check the scoring mechanism.

Using the Code

The game offers the following features that will be discussed in subsequent sections:

  1. Loading categories and words: Words are loaded from presets hard-coded in the program. However if the player provides in custom words, then the game automatically stores all of them (along with the presets) in a file and reads from there.
  2. Choosing directions: The game is made omni-directional in v3.0 release. That means words might be placed in any of the 8 possible directions.
  3. Placement on grid: The game places all the words in the 18×18 matrix in random locations and in random directions. There are 8 possible directions are right, down, down-left, and down-right, left, up, up-left and up-right as seen in the snap above.
  4. Scoring: Scores are stored individually for individual categories. Score is calculated as length of the word multiplied by a factor. Multiplication factors are set to different values according to different difficulty levels as shown below. These are called ‘augmenters’ hereby. Augmenters are chosen according to difficulty level. E.g., left direction has a multiplier of 20, whereas right direction has a multiplier of 10 as finding out a left-directional word is more difficult than finding out a right-directional word.
    Along with this, after all the words are found, the remaining time is multiplied by the multiplication factor ( = 10 at this release) is added with the score.
  5. Display hidden words: If time runs out and the player could not find all the words, then the game displays the words in a different colour. The same method is used to flash the words when the cheat code ‘FLASH’ is applied.
  6. Summary display: At the end of the game, a summary is displayed along with the snap of the game board so as to provide the player the details of scoring.
  7. Cheat code: The game offers two cheat codes (mambazamba, flash) on the game board. The first one raises the time by 100 more seconds. The second one cheat code flashes the words for a second and then hides them again. Both of the cheat codes penalize the score by deducting 50 points from the current score.

1) Loading Categories and Words

Loading Presets

For holding categories and words, there is the class WordEntity:

class WordEntity
{
    public string Category { get; set; }
    public string Word { get; set; }
}

There are some preset categories and words as follows. The presets are all pipe-delimited where every 15th word is the category name and the following words are the words in that category.

private string PRESET_WORDS =
"COUNTRIES|BANGLADESH|GAMBIA|AUSTRALIA|ENGLAND|NEPAL|INDIA|PAKISTAN|
 TANZANIA|SRILANKA|CHINA|CANADA|JAPAN|BRAZIL|ARGENTINA|" +
"MUSIC|PINKFLOYD|METALLICA|IRONMAIDEN|NOVA|ARTCELL|FEEDBACK|ORTHOHIN|
 DEFLEPPARD|BEATLES|ADAMS|JACKSON|PARTON|HOUSTON|SHAKIRA|" +
...

Encryption is used to write these words in file so that nobody can tamper with the file. If any tampering is found, the game reloads from the hard-coded categories. For encryption, a class is borrowed from here. This is simple to use – just the string and an encryption password are passed to the method. For decryption, the encrypted string and the password are passed.

If the words file exists, then the categories and words are read from there, otherwise the presets (along with player’s custom words) are saved and read from there. This is done in the following code:

if (File.Exists(FILE_NAME_FOR_STORING_WORDS))   
    ReadFromFile();
else
{   
    string EncryptedWords = StringCipher.Encrypt(PRESET_WORDS, ENCRYPTION_PASSWORD);
    using (StreamWriter OutputFile = new StreamWriter(FILE_NAME_FOR_STORING_WORDS))
        OutputFile.Write(EncryptedWords);
    ReadFromFile();
}

The ReadFromFile() method simply reads from the file which stores the words. It first tries to decrypt the string read from file. If fails (determined by blank string returned), then it displays a message about the problem and then reload from the built-in presets. Else it reads through the strings and separates them into categories and words, and puts them in a word list. Every 15th word is the category, and subsequent words are the words under that category.

string Str = File.ReadAllText(FILE_NAME_FOR_STORING_WORDS);
string[] DecryptedWords = StringCipher.Decrypt(Str, ENCRYPTION_PASSWORD).Split('|');
if (DecryptedWords[0].Equals(""))  
{
    MessageBox.Show("The words file was tampered. 
                     Any Categories/Words saved by the player will be lost.");
    File.Delete(FILE_NAME_FOR_STORING_WORDS);
    PopulateCategoriesAndWords();   
    return;
}

string Category = "";

for (int i = 0; i <= DecryptedWords.GetUpperBound(0); i++)
{
    if (i % (MAX_WORDS + 1) == 0)   
    {
        Category = DecryptedWords[i];
        Categories.Add(Category);
    }
    else
    {
        WordEntity Word = new WordEntity();
        Word.Category = Category;
        Word.Word = DecryptedWords[i];
        WordsList.Add(Word);
    }
}

Saving Player’s Customized Words

The game offers to play with customized words provided by the player. The facility is available on the same loading window. The words should be minimum 3 characters long, max 10 characters long, and there needs to be exactly 14 words — no more or no less. This is instructed in the label. Also a word cannot be sub-part of any other words. E.g.: There cannot be two words like ‘JAPAN‘ and ‘JAPANESE‘ as the former is contained in the latter.

Image 2

There are some validity checks on the words. There are two instant checks on max length and SPACE entry (no space allowed). This is done by adding the custom handler Control_KeyPress to the EditingControlShowing event of the words entry grid.

private void WordsDataGridView_EditingControlShowing
(object sender, DataGridViewEditingControlShowingEventArgs e)
{    
    e.Control.KeyPress -= new KeyPressEventHandler(Control_KeyPress);
    e.Control.KeyPress += new KeyPressEventHandler(Control_KeyPress);
}

Whenever the user enters something, the handler is called and checks the validity. This is done as follows:

TextBox tb = sender as TextBox;
if (tb.Text.Length >= MAX_LENGTH)   
{
    MessageBox.Show("Word length cannot be more than " + MAX_LENGTH + ".");
    e.Handled = true;
    return;
}
if (e.KeyChar.Equals(' '))          
                                    
                                    
{
    MessageBox.Show("No space, please.");
    e.Handled = true;
    return;
}
e.KeyChar = char.ToUpper(e.KeyChar);

Another validity check occurs after all the words are entered and the user chooses to save and play with the custom words. First, it checks if 14 words were entered or not. Then it iterates through all of the 14 words and checks if they have invalid characters. At the same time, it also checks duplicate words. After the check succeeds, the word is added in a list.

Then it iterates over the list and checks if any word has length of less than 3. If any such word is encountered, it pops a message.

Finally, another iteration is committed with the words in the list to check if a word is contained in another word (E.g., There cannot be two words like ‘JAPAN‘ and ‘JAPANESE‘ as the former is contained in the later). This is done in the CheckUserInputValidity() method as below:

if (WordsDataGridView.Rows.Count != MAX_WORDS)
{
    MessageBox.Show("You need to have " + MAX_WORDS + " words in the list. Please add more.");
    return false;
}

char[] NoLettersList = { ':', ';', '@', ''', '"', '{', '}', 
                        '[', ']', '|', '\', '<', '>', '?', ',', '.', '/',
                        '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 
                        '-', '=', '~', '!', '#', '$',
                        '%', '^', '&', '*', '(', ')', '_', '+'};   
foreach (DataGridViewRow Itm in WordsDataGridView.Rows)
{
    if (Itm.Cells[0].Value == null) continue;
    if (Itm.Cells[0].Value.ToString().IndexOfAny(NoLettersList) >= 0)
    {
        MessageBox.Show("Should only contain letters. 
                         The word that contains something else other than letters is: 
                         '" + Itm.Cells[0].Value.ToString() + "'");
        return false;
    }
    if (WordsByThePlayer.IndexOf(Itm.Cells[0].Value.ToString()) != -1)
    {
        MessageBox.Show("Can't have duplicate word in the list. 
                         The duplicate word is: '" + Itm.Cells[0].Value.ToString() + "'");
        return false;
    }
    WordsByThePlayer.Add(Itm.Cells[0].Value.ToString());
}

for (int i = 0; i < WordsByThePlayer.Count - 1; i++) 
                                                     
                                                     
                                                     
    if (WordsByThePlayer[i].Length <3)
        {
            MessageBox.Show("Words must be at least 3 characters long. 
                             A word '" + WordsByThePlayer[i]  + 
                             "' is encountered having less than the acceptable length.'");
            return false;
        }

for (int i = 0; i < WordsByThePlayer.Count - 1; i++)     
{
    string str = WordsByThePlayer[i];
    for (int j = i + 1; j < WordsByThePlayer.Count; j++) 
                                                         
        if (str.IndexOf(WordsByThePlayer[j]) != -1)
        {
            MessageBox.Show("Can't have a word as a sub-part of another word. 
                             Such words are: '" + WordsByThePlayer[i] + "' and 
                             '" + WordsByThePlayer[j] + "'");
            return false;
        }
}
return true;

The player’s list is saved along with the existing words and then the gameboard is opened up with those words in that category.

2) Choosing Directions

Image 3

The game is omni-directional; meaning it offers flexibility for words placement at any directions. It at least requires 2 directions. The chosen directions would impose a scoring augmenter, which is actually a multiplication factor. This factor is chosen according to difficulty. For example, the top-right, and top-left directions seem to be the hardest, hence they have the augmenters 30, compared to easier directions of right (which has augmenter 10). After choosing directions, the choice is passed to the game engine which deals with these directions.

private void PlayButton_Click(object sender, EventArgs e)
{
    try
    {
        List<GameEngine.Direction> ChosenDirections = new List<GameEngine.Direction>();
        if (!ListedDirectionsSuccessfully(ref ChosenDirections))
        {
            MessageBox.Show("Please choose at least two directions.");
            return;
        }

        GameBoard Board = new GameBoard(CurrentWords, CurrentCategory, ChosenDirections);
        Board.MdiParent = Parent.FindForm();
        Board.Show();
        Close();
    }
    catch (Exception Ex)
    {
        MessageBox.Show("An error occurred in 'PlayButton_Click' 
        method of 'ChooseDirections' form. Error msg: " + Ex.Message);
    }
}

private bool ListedDirectionsSuccessfully(ref List<GameEngine.Direction> Directions)
{
    foreach (Control Ctl in Controls)
        if (Ctl is CheckBox)
            if ((Ctl as CheckBox).Checked)
                Directions.Add((GameEngine.Direction)Enum.Parse
                (typeof(GameEngine.Direction), Ctl.Tag.ToString()));
    return Directions.Count >= 2;
}

This is to note that the GameEngine.Direction is borrowed from the game engine class which is the actual host of the Direction enum.

3) Placement on Grid

The main codes and logics are in the class GameEngine.

Placing Words on the Grid

The words are placed on the grid in the InitializeBoard() method. There is a character matrix (2D char array) WORDS_IN_BOARD where the words are placed first. Then this matrix is mapped to the grid. All the words are iterated one by one. For each word, a random location is obtained along with random direction (from 8 directions). At this point, the word matrix looks somewhat like the following:

Image 4

Placement is done in PlaceTheWords() method which obtains four parameters — direction of word, the X and Y-coordinates, and the word itself. This is a key method, so this needs a clear explanation for all the 8 directions.

Right Direction

A loop is run character by character for the entire word. First, it checks if the word is falling outside the grid. If that is true, then it returns to the calling procedure asking to generate a new random location and direction.

If it passes the boundary check above, then it checks if the current character is likely to overlap with an existing character on the grid. If that happens, then it checks if it is the same character or not. If not the same character, then it returns to the calling method requesting another random location and direction.

After these two checks, if the placement is a possibility, then it places the word in the matrix and also stores the location and direction in a list WordPositions through the method StoreWordPosition().

case Direction.Right:
    for (int i = 0, j = PlacementIndex_X; i < Word.Length; i++, j++) 
                                                                     
                                                                     
                                                                     
                                                                     
    {
        if (j >= GridSize) return false; 
                                         
        if (WORDS_IN_BOARD[j, PlacementIndex_Y] != '')
            if (WORDS_IN_BOARD[j, PlacementIndex_Y] != Word[i])   
                                                                  
                                                                  
                                                                  
                                                                  
            {
                PlaceAvailable = false;
                break;
            }
    }
    if (PlaceAvailable)
    {   
        
        for (int i = 0, j = PlacementIndex_X; i < Word.Length; i++, j++)
            WORDS_IN_BOARD[j, PlacementIndex_Y] = Word[i];
        StoreWordPosition(Word, PlacementIndex_X, PlacementIndex_Y, OrientationDecision);
        return true;
    }
    break;
Word Positions

The WordPosition class plays a vital role in holding the word map, pixel information, direction, and scoring augmenter. The class is as follows:

public class WordPosition
{
    public string Word { get; set; }
    public int PlacementIndex_X { get; set; }
    public int PlacementIndex_Y { get; set; }
    public GameEngine.Direction Direction { get; set; }
    public int ScoreAugmenter { get; set; }
}

And the method that keeps the positions of the words is as follows. It obtains four parameters – the word itself, the X and Y-coordinates of the word, and the direction. It instantiates the above class, stores information, and puts the augmenter factor according to directions.

private void StoreWordPosition(string Word, int PlacementIndex_X, 
                               int PlacementIndex_Y, Direction OrientationDecision)
{
    WordPosition Pos = new WordPosition();
    Pos.Word = Word;
    Pos.PlacementIndex_X = PlacementIndex_X;
    Pos.PlacementIndex_Y = PlacementIndex_Y;
    Pos.Direction = OrientationDecision;

    switch (OrientationDecision)
    {
        case Direction.Down: Pos.ScoreAugmenter = 10; break;
        case Direction.Up: Pos.ScoreAugmenter = 20; break;
        case Direction.Right: Pos.ScoreAugmenter = 10; break;
        case Direction.Left: Pos.ScoreAugmenter = 20; break;
        case Direction.DownLeft: Pos.ScoreAugmenter = 20; break;
        case Direction.DownRight: Pos.ScoreAugmenter = 20; break;
        case Direction.UpLeft: Pos.ScoreAugmenter = 30; break;
        case Direction.UpRight: Pos.ScoreAugmenter = 30; break;
        case Direction.None: Pos.ScoreAugmenter = 0; break;
    }
    WordPositions.Add(Pos);
}
Other Directions

The same logic applies for finding a good placement for the word for these other 7 directions. They differ in the increment/decrement of the matrix positions and boundary checks.

After all the words are placed in the matrix, the FillInTheGaps() method fills in the rest of the matrix with random letters. For every NULL cells (), it generates a random uppercase letter and puts it there.

for (int i = 0; i < GridSize; i++)
    for (int j = 0; j < GridSize; j++)
        if (WORDS_IN_BOARD[i, j] == '')
            WORDS_IN_BOARD[i, j] = (char)(65 + GetRandomNumber(Rnd, 26));

At this point, the form opens up and fires the Paint() event. On this event, first we draw the lines which ultimately display as 40×40 pixels rectangles. Then we map our character matrix to the board.

Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0));

ColourCells(ColouredRectangles, Color.LightBlue);
if (FailedRectangles.Count > 0) ColourCells(FailedRectangles, Color.ForestGreen);


for (int i = 0; i <= GridSize; i++)
    e.Graphics.DrawLine(pen, 40, (i + 1) * 40, GridSize * 40 + 40, (i + 1) * 40);


for (int i = 0; i <= GridSize; i++)
    e.Graphics.DrawLine(pen, (i + 1) * 40, 40, (i + 1) * 40, GridSize * 40 + 40);

MapArrayToGameBoard();

The MapArrayToGameBoard() method simply puts the character matrix on the board. The drawing code from MSDN is used here. This iterates through all the characters in the matrix places them in the middle of the 40×40 pixels rectangles with margin calibration of 10 pixels.

Graphics formGraphics = CreateGraphics();
Font drawFont = new Font("Arial", ResponsiveObj.GetMetrics(16));
SolidBrush drawBrush = new SolidBrush(Color.Black);
string CharacterToMap;

try
{
    for (int i = 0; i < GridSize; i++)
        for (int j = 0; j < GridSize; j++)
        {
            if (TheGameEngine.WORDS_IN_BOARD[i, j] != '')
            {
                CharacterToMap = "" + TheGameEngine.WORDS_IN_BOARD[i, j]; 
                                                                          
                                                                          
                                                                          
                                                                          
                formGraphics.DrawString(CharacterToMap, drawFont, drawBrush, 
                                       (i + 1) * SizeFactor + CalibrationFactor, 
                                       (j + 1) * SizeFactor + CalibrationFactor);
            }
        }
}

Word Finding and Validity Checks

Mouse click and release positions are stored in Points list. The CheckValidityAndUpdateScore() method is called on mouse button release event (GameBoard_MouseUp()). In the meantime, while the user drags the mouse while left button down, a line is drawn from the starting position to the mouse pointer. This is done in the GameBoard_MouseMove() event.

if (Points.Count > 1)
    Points.Pop();
if (Points.Count > 0)
    Points.Push(e.Location);





Point TopLeft = new Point(Top, Left);
Point DrawFrom = new Point(TopLeft.Y + Points.ToArray()[0].X + CalibrationFactor, 
                 TopLeft.X + Points.ToArray()[0].Y + MouseDrawYCalibrationFactor);
Point DrawTo = new Point(TopLeft.Y + Points.ToArray()[1].X + CalibrationFactor, 
               TopLeft.X + Points.ToArray()[1].Y + MouseDrawYCalibrationFactor);

ControlPaint.DrawReversibleLine(DrawFrom, DrawTo, Color.Black); 

The validity of a word is checked in CheckValidity() method. It formulates the word by grabbing all the letters drawn using the mouse by looking at the corresponding character matrix. Then it checks if this really matches a word in our word list. If matched, then it updates the cells by colouring them to light blue and graying the word in the word list.

Following is a snippet of code that grabs the line start and end positions. First, it checks if the line falls outside the boundary. Then it formulates the word and also stores the co-ordinates of the rectangles. Similarly, it checks for vertical, down-left and down-right words and tries to match accordingly. If this is really a match, then we store the temporary rectangles in our ColouredRectangles points list through AddCoordinates() method.

if (Points.Count == 1) return; 
int StartX = Points.ToArray()[1].X / SizeFactor;    
                                                    
int StartY = Points.ToArray()[1].Y / SizeFactor;

int EndX = Points.ToArray()[0].X / SizeFactor;      
                                                    
int EndY = Points.ToArray()[0].Y / SizeFactor;

if (StartX > GridSize || EndX > GridSize || StartY > GridSize || 
                                            EndY > GridSize || 
    StartX <= 0 || EndX <= 0 || StartY <= 0 || EndY <= 0)
    StatusForDisplay ="Nope!";

StringBuilder TheWordIntended = new StringBuilder();
List<Point> TempRectangles = new List<Point>();
TheWordIntended.Clear();
if (StartX < EndX && StartY == EndY) 
    for (int i = StartX; i <= EndX; i++)
    {
        TheWordIntended.Append(WORDS_IN_BOARD[i - 1, StartY - 1].ToString());
        TempRectangles.Add(new Point(i * SizeFactor, StartY * SizeFactor));
    }
else if (StartX > EndX && StartY == EndY) 
.................................
.................................
.................................

In the similar way, it checks for all other directions. Please notice this is an IFELSE IF block; once a direction is matched, the word in that direction only is added and other blocks are not entered.

After a word is formulated, it check if the word is in the words list. If it is there and not already found, then it adds the word in the WORDS_FOUND LIST and updates the score.

4) Scoring

For scoring, there is a score file. If it is missing, then it creates one with the current score and category. Here again, all the scores are combined in a big pipe-delimited string, then that string is encrypted and put in file. There are four attributes for a score:

class ScoreEntity
{
    public string Category { get; set; }
    public string Scorer { get; set; }
    public int Score { get; set; }
    public DateTime ScoreTime { get; set; }
..............
..............

It allows a maximum of MAX_SCORES (= 14 at this article) scores for a category. First, it loads all the scores in the scores list, then it obtains a sorted subset of scores for the current category (highest score on top). In that subset it checks if the current score greater than or equal to (>=) any available score. If it is, then it inserts the current score. After that, it checks if the subset count exceeds MAX_SCORES, if it does, then it eliminates the last one. So the last score is gone and the list always has MAX_SCORES scores. This is done in CheckAndSaveIfTopScore() method.

Here again, if somebody tampers the score file, then it simply starts a new scoring. No tampering allowed.

5) Displaying Hidden Words

If time runs out (or if cheat applied), then the game displays the words in green. First, it obtains the words that the player was not able to find. This is done here.

List<string> FailedWords = new List<string>();
foreach (string Word in WORD_ARRAY)
    if (WORDS_FOUND.IndexOf(Word) == -1)
        FailedWords.Add(Word);

Then it iterates through these failed word locations and formulates the corresponding failed rectangles. Finally, it calls the form’s paint method by invalidating.

foreach (string Word in FailedWords)
{
    WordPosition Pos = TheGameEngine.ObtainFailedWordPosition(Word);

    if (Pos.Direction == GameEngine.Direction.Right) 
        for (int i = Pos.PlacementIndex_X + 1, j = Pos.PlacementIndex_Y + 1, 
             k = 0; k < Pos.Word.Length; i++, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.Left) 
        for (int i = Pos.PlacementIndex_X + 1, j = Pos.PlacementIndex_Y + 1, 
             k = 0; k < Pos.Word.Length; i--, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.Down) 
        for (int i = Pos.PlacementIndex_X + 1, j = Pos.PlacementIndex_Y + 1, 
             k = 0; k < Pos.Word.Length; j++, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.Up) 
        for (int i = Pos.PlacementIndex_X + 1, j = Pos.PlacementIndex_Y + 1, 
             k = 0; k < Pos.Word.Length; j--, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.DownLeft) 
        for (int i = Pos.PlacementIndex_Y + 1, j = Pos.PlacementIndex_X + 1, 
             k = 0; k < Pos.Word.Length; i--, j++, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.UpLeft) 
        for (int i = Pos.PlacementIndex_Y + 1, j = Pos.PlacementIndex_X + 1, 
             k = 0; k < Pos.Word.Length; i--, j--, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.DownRight) 
        for (int i = Pos.PlacementIndex_X + 1, j = Pos.PlacementIndex_Y + 1, 
             k = 0; k < Pos.Word.Length; i++, j++, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
    else if (Pos.Direction == GameEngine.Direction.UpRight) 
        for (int i = Pos.PlacementIndex_X + 1, j = Pos.PlacementIndex_Y + 1, 
             k = 0; k < Pos.Word.Length; i++, j--, k++)
            FailedRectangles.Add(new Point(i * SizeFactor, j * SizeFactor));
}
Invalidate();

6) Summary Display

Image 5

The idea is to display a summary of scoring to the player at the end of the game (whether successful in finding out of the words, or failed to find all). This is done in the DisplayScoreDetails() method of the GameBoard form’s code file. This, on the other hand, captures a snap of the word grid area of the board (at the current situation – with colours for success and fails) and passes it as a memory stream to the ScoreDetails form.

private void DisplayScoreDetails()
{
    MemoryStream MS = new MemoryStream();
    CaptureGameScreen(ref MS);

    ScoreDetails ScoreDetailsObj = new ScoreDetails(TheGameEngine.WordPositions, 
    GameEngine.REMAINING_TIME_BONUS_FACTOR, TheGameEngine.WORDS_FOUND, Words, 
    Clock.TimeLeft, TheGameEngine.CurrentScore, ref MS);
    ScoreDetailsObj.MdiParent = Parent.FindForm();
    ScoreDetailsObj.Show();
}

private void CaptureGameScreen(ref MemoryStream MS)
{
    using (Bitmap bitmap = new Bitmap(GridSize * SizeFactor + 2, GridSize * SizeFactor + 2))
    {
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            if (Screen.PrimaryScreen.Bounds.Width >= 1600)
                g.CopyFromScreen(new Point(Bounds.Left + SizeFactor + 
                ResponsiveObj.GetMetrics(10), Convert.ToInt16(Bounds.Top + 
                (SizeFactor * 3.25))), Point.Empty, Bounds.Size);
            else if (Screen.PrimaryScreen.Bounds.Width > 1200)
                g.CopyFromScreen(new Point(Bounds.Left + SizeFactor + 
                ResponsiveObj.GetMetrics(10), Convert.ToInt16(Bounds.Top + 
                (SizeFactor * 3.85))), Point.Empty, Bounds.Size);
            else if (Screen.PrimaryScreen.Bounds.Width > 1100)
                g.CopyFromScreen(new Point(Bounds.Left + SizeFactor + 
                ResponsiveObj.GetMetrics(10), Convert.ToInt16(Bounds.Top + 
                (SizeFactor * 4.2))), Point.Empty, Bounds.Size);
            else
                g.CopyFromScreen(new Point(Bounds.Left + SizeFactor + 
                ResponsiveObj.GetMetrics(10), Convert.ToInt16(Bounds.Top + 
                (SizeFactor * 4.65))), Point.Empty, Bounds.Size);
        }
        bitmap.Save(MS, ImageFormat.Bmp);
    }
}

The purpose of the responsive object can be found in the references section of this article; this is not discussed here. Just to summarize, it provides a clever approach to scale the controls according to different resolutions – sort of ‘Shrink Ray’ as seen in the movie ‘Despicable Me’ :).

I have failed to find a generic approach to exact the grid area for different resolutions. As an alternative approach, different resolutions were tried to find a good capture of the words grid and then it was passed to the details form. The details form then regenerates the image and displays the score summary accordingly. This is to assist the player in understanding the calculations the game made for scoring. A point of interest here is, the tabs (t) didn’t work; perhaps it doesn’t work in label texts.

private void LoadScoreDetails()
{
    StringBuilder SBuilder = new StringBuilder();
    SBuilder.Append("Score for found words:n");
    SBuilder.Append("======================n");
    int Augmenter, Len;
    foreach(string Wrd in WORDS_FOUND)
    {
        Augmenter = WordPositions.Find(p => p.Word.Equals(Wrd)).ScoreAugmenter;
        Len = Wrd.Length;
        SBuilder.Append(Wrd + ", Score:tt" + Len.ToString() + " x " + 
        WordPositions.Find(p => p.Word.Equals(Wrd)).ScoreAugmenter.ToString() + 
        " = " + (Len * Augmenter).ToString() + "n");
    }

    SBuilder.Append("nFailed Words:n");
    SBuilder.Append("======================n");

    string[] FailedWords = WORD_ARRAY.Where(p => !WORDS_FOUND.Any
                           (p2 => p2.Equals(p))).ToArray();
    if (FailedWords.GetUpperBound(0) < 0)
        SBuilder.Append("Nonen");
    else
        foreach(string Word in FailedWords)
            SBuilder.Append(Word + "n");
    SBuilder.Append("nTimer bonus:tt");
    SBuilder.Append("======================n");
    if (RemainingTime == 0)
        SBuilder.Append("Nonen");
    else SBuilder.Append(RemainingTime.ToString() + " x " + 
         REMAINING_TIME_MULTIPLIER.ToString() + " = " + 
         (RemainingTime * REMAINING_TIME_MULTIPLIER).ToString() + "n");

    SBuilder.Append("======================n");
    SBuilder.Append("Total score:tt" + TotalScore.ToString());

    ScoreDetailslabel.Text = SBuilder.ToString();
}

Saving the snap is not provided at this point. Of course, the same approach of snapping the game board can be applied here as well.

7) Cheat Code

This is a minor thing to describe. This works on the keyup event where any keystroke is grabbed into two intermediary variables — CheatCodeForIncreasingTime and CheatCodeForFlashUndiscoveredWords. Actually, the keystrokes are amalgamated as entered by the player on the game window. Then it checks if the code matches any available cheat codes (‘mambazamba’, or ‘flash’). For example, if the player presses ‘m‘ and ‘a‘, then they are kept as ‘ma‘ in the CheatCodeForIncreasingTime variable (because, ‘ma‘ still matches the cheatcode pattern). Similarly, we add consecutive variables to it if it matches the pattern of the CHEAT_CODE. However, once it fails to match a pattern (e.g., ‘mambi‘), then it starts over.

Because the game has 2 cheat codes at the moment, so care needs to be taken for both of them explicitly. That is why the keystroke is kept in two separate variables and a match is checked separately. Whichever matches, it triggers the corresponding cheat action.

Finally, if there is a match with ‘mambazamba’ then the first cheat is activated (literally, it raises the remaining time by 100 more seconds), and applies the penalty (deducts 50 points from the current score).

On the other hand, if it matches with ‘flash’, then the second cheat is activated (this would flash all the undiscovered words on the board for 1 second and then hide them back), and applies the same penalty.

public enum CHEAT_TYPE { INCREASE_TIME, FLASH_WORDS, NONE};

CheatType = CHEAT_TYPE.NONE;
CheatCodeForIncreasingTime += CheatCode;

if (CHEAT_CODE_FOR_INCREASING_TIME.IndexOf(CheatCodeForIncreasingTime) == -1)  
          
    CheatCodeForIncreasingTime = (CheatCode);          
else if (CheatCodeForIncreasingTime.Equals(CHEAT_CODE_FOR_INCREASING_TIME) && 
         WordsFound != MAX_WORDS)
{
    CheatType = CHEAT_TYPE.INCREASE_TIME;
    return true;
}

CheatCodeForFlashUndiscoveredWords += CheatCode;
if (CHEAT_CODE_FOR_UNDISCOVERED_WORDS.IndexOf
    (CheatCodeForFlashUndiscoveredWords) == -1)        
                                                       
    CheatCodeForFlashUndiscoveredWords = (CheatCode);  
else if (CheatCodeForFlashUndiscoveredWords.Equals(CHEAT_CODE_FOR_UNDISCOVERED_WORDS) && 
                                                   WordsFound != MAX_WORDS)
{
    CheatType = CHEAT_TYPE.FLASH_WORDS;
    return true;
}
return false;

The interesting thing to note here is we have to use the KeyUp event of the WordsListView instead of the form. This is because after loading the game window, the list box has the focus, not the form.

Environment

Coded using Visual Studio 2015 IDE, with .NET Framework of 4.5. This is not a mobile version — a machine is required to play.

Points of Interest

To force a redraw of the window, we need to call the Invalidate() method of the window. There was also a need to calibrate the mouse co-ordinates by adjusting with the forms top and left positions. The interesting thing is, a form’s co-ordinates are defined as: X to be the distance from top of the screen, Y to be the distance from left of the screen. However, mouse co-ordinates are defined as the other way: X as the distance from left of the window, Y as the distance from top of the window. Hence, for calibration, we needed to adjust carefully.

private void GameBoard_MouseMove(object sender, MouseEventArgs e)
{
    try
    {
        if (e.Button == MouseButtons.Left)
        {
            if (Points.Count > 1)
                Points.Pop();
            if (Points.Count > 0)
                Points.Push(e.Location);

            
            

            
            Point TopLeft = new Point(Top, Left);
            Point DrawFrom = new Point(TopLeft.Y + Points.ToArray()[0].X + 10, 
                                       TopLeft.X + Points.ToArray()[0].Y + 80);
            Point DrawTo = new Point(TopLeft.Y + Points.ToArray()[1].X + 10, 
                                     TopLeft.X + Points.ToArray()[1].Y + 80);

            ControlPaint.DrawReversibleLine(DrawFrom, DrawTo, Color.Black); 
        }
    }

Another important and interesting thing was discovered through the message of jrobb229 about the ENTER key behaviour. The initial release offered instant checks on the datagrid where the player wants to enter words less than 3 characters long. It actually processed the logic check of length, but there was no way to stop the cursor from moving to the next cell. This happened on the way it was implemented.

I still couldn’t find a way to counter this behaviour. So I added the alternate approach of doing the length check in the later validation. I am not quite happy with the bypass; anyway just provided an alternative to the current bug, and hope to find the perfect workaround soon.

Glitches

I found a minor glitch if there are multiple monitors in a machine. If the game is loaded in one window, and it is moved to the other window, then mouse dragging keeps scar marks on the first window. But no panic, it erases after the game is closed.

Another glitch will be observed if the game board is moved to another window from the primary window and the snapping code tries to snap the given area of the primary screen. The reason is the same as the current release opts for screen capturing for the primary screen. A check is not provided as to where the game board has moved at the point of capturing.

Disclaimer

Aside from the initial release, the game is refactored to a more Object-Oriented approach. However, as it is a never-ending process, so there might be more ways to improvise.

I didn’t follow any naming convention. My personal preference is to have a name that might be able to tell the intention, while hovering over the name, we can easily understand the type; so why making a variable heavier with names like ‘strStatusLabel‘? There might be controversies, however that is not what this article is intended for.

Acknowledgements

Thanks to:

  • Member 10014441 for reporting the ‘CalibrationFactor’ bug
  • jrobb229 for reporting the top score bug, and the datagridview ENTER key anomaly bug. Also thanks for feature improvement suggestions
  • sx2008 for suggestions on size reduction of the project
  • everybody else for playing and commenting :)

Future Works

Remaining time should be adjusted according to difficulty levels. At this moment, a fixed 720 seconds does not really justify difficulty levels as easier directions and harder directions both have the same time limit. On another note, this might be considered okay as the player opts for a difficult game and hence time should remain constant.

The details screen can be captured and saved as an image for a future reference. The code for capturing a screen is already there.

A generic approach for snapping the game board in different resolutions might be sought for. At the moment, it is rather a crude approach with some IFELSE conditions.

The ENTER key press for the datagridview is actually not fired. This is an odd behaviour and difficult to deal with when we want to see what is happening (e.g., checking word length for less than 3 characters) at ENTER key press. ‘e.Handled’ is not applicable in this case. At this release, this problem was bypassed with an alternative approach. I am not very happy with the bypass, but just resorted to that to get it going at the moment. This is a genuine programming optimization and can be looked after.

Summary

This is a word puzzle game featuring preset words, custom words, scoring on individual word categories.

References

  • Drawing letter on a form
  • Drawing a straight line on a form — Link 1
  • Drawing a straight line on a form — Link 2
  • Colour a rectangle
  • Datagrid font sizing
  • Datagrid column width setup
  • Datagrid column header setup
  • Datagrid key press event handler
  • Bind datagrid columns with predefined columns
  • String ciphering
  • Fixing maximum number of allowed rows in a DataGridView

Finding items of a list which are absent in another list:

  • Capturing Screen — Link 1
  • Capturing Screen — Link 2
  • A Responsive Design Technique for Winforms
  • Arrows Clip-Art

History

  • 10th October, 2016: First release
  • 17th/18th October, 2016: Bug fixing, responsive design, re-formatted code in CodeProject
  • 20th October, 2016: Removed installer from downloadable, resized downloadable project and stored the executable in that downloadable zip file, added one more reference.
  • 15th November, 2016: Made it omni-directional (8 directions), provided two cheat codes, and refactored the whole project with a better OOP approach, better scoring. Scoring is now available if not all the words are found by the time limit, but is a top score anyway. Better scoring summary for scoring reference.

A software developer mainly in .NET technologies and SQL Server. Love to code and learn.

Write a program that plays a word game with the user.  The program should ask the

user to enter the following:

* His or her name

* His or her age

* The name of a city

* The name of a college

* A profession

* A type of animal

* A pet’s name

After the user has entered these items, the program should display the following

story, inserting the user’s input into the appropriate locations:

There once was a person named NAME who lived in CITY.  At the age of AGE, NAME

went to college at COLLEGE.  NAME graduated and went to work as a PROFESSION.

Then, NAME adopted a(n) ANIMAL named PETNAME.  They both lived happily ever after!

#include<iostream>
#include<string>
 
using namespace std;
 
int main()
{
string Name, City, College, Profession, Animal, PetName;
double Age;
 
cout << "Enter your name: ";
getline(cin, Name);
cout << "Enter your age: ";
cin >> Age;
cin.ignore();
cout << "Enter the name of a city: ";
getline(cin, City);
cout << "Enter the name of a college: ";
getline(cin, College);
cout << "Enter a profession: ";
getline(cin, Profession);
cout << "Enter a type of an animal: ";
getline(cin, Animal);
cout << "Enter a pet's name: ";
getline(cin, PetName);
 
cout << "nn______programology_________n"
 << "           Word Game"
 << "nprogramologynn";
 
cout << "There once was a person named " << Name << " who lived in " << City
 << ". At the age of n" << Age << ", " << Name << " went to " 
 << College << ".  " << Name << " graduated and went to work n"
 << "as a " << Profession << ".  Then, " << Name << " adopted a(n) "
 << Animal << " named " << PetName << ".  They, nboth lived happily "
 << "ever after! nn";
 
system("pause");
 
return 0;
}

The hangman game code in c is developed using C programming language. This hangman game in c programming is about guessing letters (A-Z) to form the words. A hangman game is a common word guessing game in which the player must guess one letter at a time to complete a missing word.

This hangman game source code in c language ends after a certain number of incorrect guesses, and the player loses. If the player correctly recognizes all of the letters in the missing title, the game is also over. In this project design is straightforward and clean, making it easy for users to learn, use, and navigate.

This console game application also includes a downloadable hangman game source code in c language for free, just find the downloadable source code below and click to start downloading.

Anyway if you want level up your knowledge in programming especially C/C++ Programming Language, try this new article I’ve made for you Best C Projects with Source Code for Beginners Free Download 2022.

To run this hangman game program in c language make sure that you have a Code Blocks or any platform of C installed in your computer.

ABOUT PROJECT PROJECT DETAILS
Project Name : hangman game
Project Platform : C/C++
Programming Language Used: C Programming Language
Developer Name : itsourcecode.com
IDE Tool (Recommended): Dev-C++/Codeblocks
Project Type : Desktop Application
Database: Stores data in .DAT file
Hangman Game In C With Source Code Information

Hangman Game In C Source Code Steps On How To Run The Project

Time needed: 5 minutes.

These are the steps on how to run Hangman Game project In C With Source Code

  • Step 1: Download

    First, download the source code given below.
    Hangman Game In C Step 1

  • Step 2: Extract file.

    Second, after you finished download the source code, extract the zip file.
    Hangman Game In C Step 2

  • Step 3: Open CodeBlocks

    Third, open “CodeBlocks IDE”.

  • Step 4: Open Project.

    Fourth, open file tab and Open File after that open folder HangmanGameC then click the “hangman.c“.

  • Step 5: Run Project

    Fifth, run the project.

  • Step 6: The actual code.

    You are free to copy the given source code below or download the downloadable source code given.

The Code Given Below is the Actual Code of System

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>

#define WORDS 10
#define WORDLEN 40
#define CHANCE 6

bool srand_called = false;

int i_rnd(int i) {
    if (!srand_called) {
        srand(time(NULL) << 10);
        srand_called = true;
    }
    return rand() % i;
}

char* decrypt(char* code) {
	int hash = ((strlen(code) - 3) / 3) + 2;
	char* decrypt = malloc(hash);
	char* toFree = decrypt;
	char* word = code;
	for (int ch = *code; ch != ''; ch = *(++code))
	{
		if((code - word + 2) % 3  == 1){
			*(decrypt++) = ch - (word - code + 1) - hash;
		}
	}
	*decrypt = '';
	return toFree;
}

void printBody(int mistakes, char* body) {
	printf("tMistakes :%dn", mistakes);
	switch(mistakes) {

		case 6: body[6] = '\'; break;
		case 5: body[5] = '/'; break;
		case 4: body[4] = '\'; break;
		case 3: body[3] = '|'; break;
		case 2: body[2] = '/'; break;
		case 1: body[1] = ')', body[0] = '('; break;
		default: break;

	}

	printf("t _________n"
	       "t|         |n"
	       "t|        %c %cn"
	       "t|        %c%c%cn"
	       "t|        %c %cn"
	       "t|             n"
	       "t|             ", body[0], body[1], body[2],
	       body[3], body[4], body[5], body[6]);
}

void printWord(char* guess, int len) {
	printf("t");
	for (int i = 0; i < len; ++i)
	{
		printf("%c ", guess[i]);
	}
	printf("nn");
}

int main() {

	printf("nt Be aware you can be hanged!!.");

	printf("nnt Rules : ");
	printf("nt - Maximum 6 mistakes are allowed.");
	printf("nt - All alphabet are in lower case.");
	printf("nt - All words are name of very popular Websites. eg. Google");
	printf("nt - If you enjoy continue, otherwise close it.");

	printf("nt Syntax : Alphabet");
	printf("nt Example : a nn");

	char values[WORDS][WORDLEN] = {"N~mqOlJ^tZletXodeYgs","gCnDIfFQe^CdP^^B{hZpeLA^hv","7urtrtwQv{dt`>^}FaR]i]XUug^GI",
									"aSwfXsxOsWAlXScVQmjAWJG","cruD=idduvUdr=gmcauCmg]","BQt`zncypFVjvIaTl]u=_?Aa}F",
									"iLvkKdT`yu~mWj[^gcO|","jSiLyzJ=vPmnv^`N]^>ViAC^z_","xo|RqqhO|nNstjmzfiuoiFfhwtdh~",
									"OHkttvxdp|[nnW]Drgaomdq"};
	char *body = malloc(CHANCE+1);

	int id = i_rnd(WORDS);
	char *word = decrypt(values[id]);
	int len = strlen(word);
	char *guessed = malloc(len);
	char falseWord[CHANCE];

	memset(body, ' ', CHANCE+1);
	memset(guessed, '_', len);
	char guess;
	bool found;
	char* win;

	int mistakes = 0;
	setvbuf(stdin, NULL, _IONBF, 0);

	do {

		found = false;
		printf("nn");
		printBody(mistakes, body);
		printf("nn");
		printf("tFalse Letters : ");
		if(mistakes == 0) printf("Nonen");
		for (int i = 0; i < mistakes; ++i)
		{
			printf("%c", falseWord[i]);
		}
		printf("nn");
		printWord(guessed, len);
		printf("tGive me a alphabet in lower case : ");
		do {scanf("%c",&guess);} while ( getchar() != 'n' );
		for (int i = 0; i < len; ++i)
		{
			if(word[i] == guess) {
				found = true;
				guessed[i] = guess;
			}
		}
		if(!found) {
			falseWord[mistakes] = guess;
			mistakes += 1;
		}
		win = strchr(guessed, '_');
	}while(mistakes < CHANCE && win != NULL);

	if(win == NULL) {
		printf("n");
		printWord(guessed, len);
		printf("ntCongrats! You have won : %snn", word);
	} else {
		printf("n");
		printBody(mistakes, body);
		printf("nntBetter try next time. Word was %snn", word);
	}

	free(body);
	free(word);
	free(guessed);
	return EXIT_SUCCESS;
}

Downloadable Source Code

Conclusion

This hangman in c language is only a project made for school requirement purposes only. You can download this source code and modify it to suit your client requirements, since this is a student project it means you cannot really expect 100% functionality from this.

Related Articles

  • Hangman Game In Python With Source Code
  • Code For Games in Python: Free Python Games Source Code

Inquiries

If you have any questions or suggestions about hangman in c description, please feel free to leave a comment below.

Random words, an array, and conditional statements.

Create a word guessing game that asks a player to guess a random word. As we build the C# console application, we’ll discuss some fundamental programming concepts.

We’ll build upon the code we started in Numeric Guessing Game: C# Console Application. (If you haven’t read it yet, you might want to start there!)

Game Instance

In the numeric guessing game we didn’t create an instance of the Game class. Our first step will be to change our code so we have a Game object. With examples of each you can compare the two approaches.

Remove:

  • Delete the static keyword from our Game class members.
  • Clear the Game Play method call from Main.

Add:

  • Make an instance of the Game class.
  • Inside of Main, call the instance’s method Play.

The two versions are below. If you run them they will appear the same to the player; the only changes are internal.

Original:

 class Program
    {
        static void Main()
        {
            Game.Play();
        }
    }

Revised:

 class Program
    {
        static void Main()
        {
            Game theGame = new Game();
            theGame.Play();
        }
    }

Full Code: Updated Numeric Guessing Game Code

using System;

namespace GuessingGame
{
    class Game
    {
        int Guess = 0;
        int Target = 5;
        string Input = "";
        Random RandomNumber = new Random();

        public void Play()
        {
            Target = RandomNumber.Next(10) + 1;
            Console.Write("Guess what number I am thinking of... ");
            Input = Console.ReadLine();
            if (int.TryParse(Input, out Guess))
            {
                if (Guess == Target)
                {
                    Console.WriteLine("Congratulations! You guessed " + Guess + " and the number I was thinking of was " + Target + ".");
                }
                else
                {
                    Console.WriteLine("Too bad. You guessed " + Guess + " and the number I was thinking of was " + Target + ". Try again!");
                }
            }
            else
            {
                Console.WriteLine("Please enter a number.");
                Console.WriteLine("Press enter to continue...");
                Console.ReadLine();
                Play();
            }

            Console.ReadKey();
        }
    }
    class Program
    {
        static void Main()
        {
            Game theGame = new Game();
            theGame.Play();
        }
    }
}

Using the new version of our numeric game as a base, we will convert it into a game where the player tries to guess a random word instead of number.

Array

Our list of possible words will be stored in an array. We’ll use the same random number code we used previously. Now, though, our random number will be used to select an element. The player will see the options and can enter their guess as to which word will match.

Add an array to the Game class and initialize it with a few words. In the example the words are: cat, hat, and rat.

class Game
{
    static int Guess = 0;
    static int Target = 5;
    string[] Words = { "cat", "hat", "rat" };
    static Random RandomNumber = new Random(); [...]

Show Options

Write out the word options and ask the player to guess one of them. As with the numeric game, you can make this a simple instruction («Choose a word:») or make it more fanciful («My crystal ball is showing something … through the mists I am getting a message… do you know what I see?»).

To print out each word in the array, you can use a foreach statement:

foreach (string word in Words)
{
    Console.Write(word + " ");
}

Word Guessing Game: Example using a foreach statement to write out elements in an array

Example using a foreach statement to write out elements in an array

You could also add commas between each word as it is written out. For this type of approach, you would want to know when you’ve reached the last element in the array. A for loop makes that easy:

Console.Write(" Guess which word I am thinking of... is it ");
for (int i = 0;i< Words.Length;i++)
{
	if (i==(Words.Length-1))
	    Console.Write("or " + Words[i] + "? ");
	else
	    Console.Write(Words[i] + ", ");
}

Word Guessing Game: Example using a for loop

Example using a for loop

Comparison

To select a word from the array, we’ll use the same random number as in our numeric game. The range can be dynamically determined from the length of the Words array.

Target = RandomNumber.Next(Words.Length);

The code to check whether the input is a number won’t be needed now that we are matching words instead of integers. We can also change our conditional statement. It will now compare what the player has typed to the random element from the Words array.

if (Input == Words[Target])
{
    Console.WriteLine("Congratulations! You guessed it!");
}
else
{
    Console.WriteLine("Not a match. Try again!");
}

If the player didn’t guess the word, we can call the Play() method to restart the game.

Word Guessing Game Final Code

using System;

namespace GuessingGame
{
    class Game
    {
        int Guess = 0;
        int Target = 5;
        string Input = "";
        string[] Words = { "cat", "hat", "rat" };
        Random RandomNumber = new Random();

        public void Play()
        {
            Target = RandomNumber.Next(Words.Length);


            Console.Write(" Guess which word I am thinking of... is it ");
            for (int i = 0; i < Words.Length; i++)
            {
                if (i == (Words.Length - 1))
                    Console.Write("or " + Words[i] + "? ");
                else
                    Console.Write(Words[i] + ", ");
            }

            Input = Console.ReadLine();

            if (Input == Words[Target])
            {
                Console.WriteLine("Congratulations! You guessed it!");
            }
            else
            {
                Console.WriteLine("Not a match. Try again!");
                Console.WriteLine("Press enter to continue...");
                Console.ReadLine();
                Play();
            }


            Console.ReadKey();
        }
    }
    class Program
    {
        static void Main()
        {
            Game theGame = new Game();
            theGame.Play();
        }
    }
}

Next Step

Think about your game’s interface. Can you make it more engaging?

Word Guessing Game: Example title screen

Example title screen

I am having some issues writing a program. The program is essentially the word guessing game hangman. I have the store a word, and the user gets however many chances to guess the word. I’m having trouble getting the game to loop correctly and end when the number of guesses has been used up. Also, I made a second array with, the same size as the array with my word, but this array is filled with dashes. If a letter is correctly guessed, I need the correct letter to show up around the dashes. If somebody can help, I would really appreciate it.

#include <stdio.h>   // Input and output operations
#include <stdlib.h>  // General purpose functions

int main(void)
{
   FILE*fp;          // File pointer variable
   fp = fopen("Quiz 6", "w");

   int numTries, tries, i;  // Declaration of variables
   char guess;
   char myWord [6] = {'a','p','p','l','e',''};  // Initialization of variables
   char dashedArray [6] = {'-','-','-','-','-','-'};

   numTries = 0;
   i=0;
   tries = 0;

   printf("nLet's play a game! The objective of the game is to guess my secret word. You will have
          five chances to guess.n");
   printf("nLet's get started!n");
   printf("nPlease enter a letter: ");
   scanf("%c", &guess);

   for (i = 0; i < 4; i++)
   {
      numTries = numTries +1;
      if (guess == myWord [0])
      {
         printf("n %c----", myWord [0]);
         printf("nGood Guess!n");
         printf("nPlease guess another letter: ");
         scanf(" %c", &guess);
      }

      if ( guess == myWord [1] && myWord [1] )
      {
         printf("n-%c%c--", myWord [1], myWord [1]);
         printf("nGood Guess!n");
         printf("nPlease guess another letter: ");
         scanf(" %c", &guess);
      }

      if ( guess == myWord [3] )
      {
         printf("n---%c-", myWord [3]);
         printf("nGood Guess!n");
         printf("nPlease guess another letter: ");
         scanf(" %c", &guess);
      }

      if ( guess == myWord [4] )
      {
         printf("n----%c", myWord [4]);
         printf("nGood Guess!n");
         printf("nPlease guess another letter: ");
         scanf(" %c", &guess);
      }

      if ( if word is completed and guessed correctly )
      {
         printf("nCongrats! You guessed the secret word!n");
      }

      else if ( guess != myWord )
      {
         printf("nSorry. That is not a correct letter. Please guess again:n");
         scanf(" %c", &guess);
      }
   }
}

  • Forum
  • Beginners
  • Word Guessing Game C Programming

Word Guessing Game C Programming

I’m trying to create a code with these prospects:

Program that simulates a simple word-guessing game, similar to Hangman (without the pictures) or television’s Wheel of Fortune (without the money and prizes). The idea is that the program will “think” of a secret phrase, and the user will try to discover the phrase by guessing one letter at a time.
The program will use a single secret phrase that it uses each time the program runs. It can be any phrase, as long as it contains at least 15 characters, including at least one space (i.e., multiple letters).
• After each guess, the program should show the current status of the user’s guesses, using dashes to indicates unguessed letters. For example, if the secret phrase is ‘magical mystery tour’ and the user has already guessed the letters b, y, and t, then the program should display:
——- -y-t—y t—
Any spaces in the phrase should automatically be included (i.e., the user doesn’t have to guess them).
• Keep track of the number of guesses the user makes. (If a user re-guesses a letter previously guessed, the new guess is still counted.)
• If, after the 20th guess, the user still hasn’t completely discovered the phrase, the program should display a consolation message and end the game. The consolation message should include the secret phrase.
• If the user discovers the secret phrase by the 20th guess, display a congratulatory message, along with the number of guesses the user took.

This is what I got so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
int main ()
{
	int count = 0;
	char letter;
   char word[18]= "these lovely bones";
   char guess[20];
 
   for(int i=0; i < 20;++i )
   {
   printf ("Enter a letter to guess the wordn");
	scanf("%c", &letter);
	   int flag = 0;
	   if(count == 20)
	   {
		   printf("you guessed the wordn");

	   }
	   for(int j=0; j < 20;++j)
	   {
	   if(letter == word[j])
	   {
		   printf("Letter foundn");
		   count++;
		   flag=1;

	   }
	   }
	   if (flag==0) 
	   {
		   printf("Letter not foundn");
	   }
   }

  return 0;
}

It’s basically nothing but I find this code so hard. Help on any of the bullet points would be greatly appreciated.

Last edited on

char phrase[18 + 1] = "these lovely bones"; //[18+1] don't forget the NULL terminator

I tried to keep your code that would work below and give you some ideas of what you could do in the comments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
int main ()
{
    int count
    char letter;
    char phrase[18 + 1] = "these lovely bones"; //[18+1] don't forget the NULL terminator
    char cur_guess[18 + 1] = "---- ------ -----"; //[18+1] don't forget the NULL terminator
    bool guessed = FALSE; //initially they haven't guessed the word
     
    for(int i=0; i < 20; ++i) //Goes from 0 - 19, gives the user 20 chances to guess.
    {
         //if the user hasn't already guessed the corrected phrase 
        {
            //get the guess from the user
            //use a function to check if the letter is in the phrase, update the current guess and print it out

            //if the letter is in the phrase then...
                //...use a function to see if the current guess matches the phrase, if so update count and guessed
        }
    }
    
    //check to see if they GUESSED the word correctly
        //print out congratulatory message and count
    //if they have NOT GUESSED the word correctly
        //print out consolation message and the phrase

    return 0;
}

Last edited on

Topic archived. No new replies allowed.

Понравилась статья? Поделить с друзьями:
  • Word generator for words
  • Word games from around the world
  • Word generator for word search
  • Word games for your computer
  • Word generator for letters