πŸ‡―πŸ‡΅ ζ—₯本θͺž | πŸ‡ΊπŸ‡Έ English

C Game Programming Projects

"I want to make this more fun" is the single best driver of your coding skill.
Build the basic version first, then put your own spin on it through the extension challenges.

How to work through these: Each game starts with a "basic implementation" and then offers "incremental extensions". Get the basic version working first, then tackle the extensions however you like — there's no single right answer.
🎯

GAME 1: Number Guessing Game

Beginner Random Loops Conditionals
Guess the secret number the computer picked, using "too high / too low" hints.
🎯 Guess a number between 1 and 100! Guess> 50 Too low Guess> 75 Too high Guess> 63 πŸŽ‰ Correct! You got it in 3 tries!
1
Pick the answer at random: call srand(time(NULL)) once, then rand() % 100 + 1 to get a number from 1 to 100.
2
Read input in a loop: use a while loop that keeps going until the guess is correct. Read each guess with scanf.
3
Compare and report: if guess > answer print "Too high"; if guess < answer print "Too low"; otherwise print "Correct".
4
Count attempts: keep an int counter for tries, then print it when the player wins.
Extension Challenges
  • Rate the player based on how many tries it took (≤5 = "Genius!", ≤10 = "Not bad", etc.).
  • Add difficulty selection (Easy: 1–50, Normal: 1–100, Hard: 1–1000).
  • Implement a "play again?" feature with a do-while loop.
  • Compute and show the maximum number of tries binary search would need.
  • Add a try limit and end the game if the player runs out of attempts.
Skeleton:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
    srand((unsigned)time(NULL));
    int answer = rand() % 100 + 1;
    int guess, count = 0;

    printf("Guess a number between 1 and 100!\n");
    do {
        printf("Guess> ");
        scanf("%d", &guess);
        count++;
        if (guess > answer) printf("Too high\n");
        else if (guess < answer) printf("Too low\n");
    } while (guess != answer);

    printf("Correct! Got it in %d tries!\n", count);
    return 0;
}
✊

GAME 2: Rock Paper Scissors

Beginner switch Random Arrays
Play rock-paper-scissors against the computer. Record results and display the win/loss record.
βœŠβœŒβœ‹ Rock-Paper-Scissors (0:Rock 1:Scissors 2:Paper -1:Quit) You> 0 You: Rock vs CPU: Scissors πŸŽ‰ You win! You> 2 You: Paper vs CPU: Paper 😐 Draw! You> -1 --- Record --- 3W 1L 1D (win rate 60.0%)
1
Store hand names in an array: char *hands[] = {"Rock","Scissors","Paper"};
2
Scoring logic: (player - cpu + 3) % 3 returns 0 = draw, 1 = lose, 2 = win.
3
Track the record: keep three counters — wins, losses, and draws.
4
Exit cleanly: break the loop when the user enters -1, then print the record.
Extension Challenges
  • Add best-of-three mode (first to 2 wins).
  • Track how often the player throws each hand and make the CPU a "learning AI" that counters their favorite.
  • Expand to "Rock-Paper-Scissors-Lizard-Spock" (5 choices).
  • Save each round to an array and print the full match history at the end.
Judging trick:
// 0=Rock, 1=Scissors, 2=Paper
int result = (player - cpu + 3) % 3;
if (result == 0) printf("Draw\n");
else if (result == 2) printf("You win!\n");
else printf("You lose...\n");
🎰

GAME 3: Slot Machine

Beginner Random Arrays Conditionals
Spin three reels to match symbols. Track the player's coin balance as it rises and falls.
🎰 Slot Machine (Coins: 100) Press Enter to spin (10 coins/spin)> | πŸ’ | πŸ‹ | πŸ’ | β†’ No match Coins left: 90 Press Enter> | 7️ | 7️ | 7️ | β†’ πŸŽ‰ JACKPOT! +500 coins! Coins left: 580
1
Store symbols in an array: for example, char *symbols[] = {"πŸ’","πŸ‹","πŸ””","⭐","7"};
2
Randomize the three reels: call rand() % num_symbols three times.
3
Check for wins: three matching = jackpot, two matching = small win, otherwise no match.
4
Manage the coin balance: subtract 10 per spin and add winnings on a match. Game over when coins reach 0.
Extension Challenges
  • Different payouts per symbol (e.g. three 7's pays the most).
  • Bias the reel probabilities (make 7 rare).
  • Let the player choose how much to bet each spin.
  • Save history to a file and reload on startup
β­•

GAME 4: Tic-Tac-Toe

Intermediate 2D Arrays Functions Loops
Alternate placing O and X on a 3x3 board. First to make a line wins. Manage the board with a 2D array.
1 | 2 | 3 ---+---+--- 4 | 5 | 6 ---+---+--- 7 | 8 | 9 O's turn cell#> 5 | | ---+---+--- | O | ---+---+--- | | X's turn cell#> 1 X | | ---+---+--- | O | ---+---+--- | |
1
Represent the board with a 2D array: char board[3][3]. Empty = ' ', O = 'O', X = 'X'.
2
Write a board-printing function: void print_board(char board[3][3]) that draws separator lines between rows.
3
Write a win-check function: examine all 8 lines (3 rows, 3 columns, 2 diagonals).
4
Validate input: reject already-taken cells and any value outside 1–9, then prompt again.
Extension Challenges
  • Add a CPU opponent that plays a random empty cell.
  • Make the CPU smarter (prefer corners, block the opponent's near-wins).
  • Scale to a 4x4 or 5x5 board (four-in-a-row to win).
  • Save stats to a file and display cumulative totals.
  • Implement a perfect minimax AI (advanced).
Win-check trick:
int check_win(char b[3][3], char c) {
    for (int i = 0; i < 3; i++) {
        if (b[i][0]==c && b[i][1]==c && b[i][2]==c) return 1; // row
        if (b[0][i]==c && b[1][i]==c && b[2][i]==c) return 1; // col
    }
    if (b[0][0]==c && b[1][1]==c && b[2][2]==c) return 1; // diag
    if (b[0][2]==c && b[1][1]==c && b[2][0]==c) return 1; // diag
    return 0;
}
πŸƒ

GAME 5: Maze Escape

Intermediate 2D Arrays Structs Functions
Represent a maze with a 2D array. Move the player with WASD to reach the goal.
################ #P.....#.......# #.####.#.#####.# #......#.#...#.# ######.#.#.#.#.# #......#...#...# #.##########.### #..............G ################ Move (w/a/s/d)> d
1
Maze data: char maze[H][W], where '#' = wall, '.' = path, 'P' = player, 'G' = goal.
2
Store the player position in a struct: struct Pos { int x, y; };
3
Movement logic: update the position if the target cell isn't a wall; otherwise print "Can't move".
4
Goal check: end the maze when the player's position reaches 'G'.
Extension Challenges
  • Track the number of moves as a score.
  • Add a locked door that requires picking up a key first.
  • Add randomly moving enemies — touching one ends the game.
  • Load the maze from an external file.
  • Try a maze-generation algorithm (e.g. recursive backtracker).
  • Limit "vision" to the 3 cells around the player.
πŸƒ

GAME 6: Blackjack

Intermediate Structs Arrays Functions Random
Classic blackjack. Get as close to 21 as possible without going over. Represent cards with a struct.
πŸƒ Blackjack Your hand: [β™ A] [β™₯K] β†’ Total: 21 Dealer: [♦7] [??] Hit(h) / Stand(s)> s Dealer hand: [♦7] [♣9] β†’ Total: 16 Dealer hits: [β™ 5] β†’ Total: 21 😐 Push!
1
Represent a card as a struct: struct Card { int suit; int rank; };
2
Build and shuffle a 52-card deck: use the Fisher–Yates shuffle.
3
Hand-total function: count each Ace as 1 or 11, whichever keeps the total under 22.
4
Dealer AI: keep hitting until the total is 17 or higher (the standard rule).
Extension Challenges
  • Add chips and a betting system.
  • Implement double-down, split, and surrender.
  • Support multi-deck shoes (6 decks, etc.).
  • Add a card-counting practice mode.
πŸ“

GAME 7: Hangman (Word Guessing)

Intermediate Strings Arrays Loops
Guess the hidden word one letter at a time. A fixed number of wrong guesses ends the game. Great practice for string manipulation.
Guess the word! (misses left: 6) _ _ _ _ _ _ _ _ _ Letter> e _ _ _ _ _ _ _ _ e β­• Letter> a No match ❌ (left: 5) Letter> r _ r _ _ r _ _ _ e β­•
1
Prepare a word list as an array: char *words[] = {"programming","computer",...};
2
Track revealed letters in an array: int revealed[MAX].
3
Check the guess against every position: use a for loop and reveal every matching letter.
4
End conditions: all letters revealed → win; too many misses → lose.
Extension Challenges
  • Draw the hangman progressively in ASCII art.
  • Change word length based on the selected difficulty.
  • Display the letters the player has already guessed.
  • Load the word list from an external file.
  • Add multiple categories or languages of words.
βš”οΈ

GAME 8: Text RPG Battle

Advanced Structs Pointers Functions Random
Turn-based combat between hero and monster. Store stats in a struct and choose attack/defend/magic commands.
βš”οΈ A Slime appears! Hero HP:100/100 MP:30/30 Slime HP:50/50 1:Attack 2:Defend 3:Magic > 1 Hero attacks! Slime takes 15 damage! Slime HP: 35/50 Slime attacks! Hero takes 8 damage! Hero HP: 92/100
1
Character struct: struct Character { char name[20]; int hp, max_hp, mp, atk, def; };
2
Damage function: int calc_damage(int atk, int def) — add some random variance.
3
Command selection: branch on the player's choice of attack, defend, or magic.
4
Battle loop: keep looping until one side's HP falls to 0 or below.
Extension Challenges
  • Store multiple enemies in an array for back-to-back battles.
  • Add experience points and leveling up.
  • Item inventory (an array of items, potions, etc.).
  • Smarter enemy AI (e.g. heals when HP gets low).
  • Add boss-fight special effects.
  • Save and load progress with file I/O.
πŸ’£

GAME 9: Minesweeper

Advanced 2D Arrays Recursion Functions
Avoid mines while revealing every safe cell. The core challenge is counting neighboring mines and cascading opens (recursion).
1 2 3 4 5 1 . . . . . 2 . . . . . 3 . . . . . 4 . . . . . 5 . . . . . Open (row col)> 3 3 1 2 3 4 5 1 1 . . . 2 1 2 . . 3 1 . . 4 1 2 . 5 1 .
1
Use two 2D arrays: int mines[H][W] for mine locations and int visible[H][W] for what's been revealed.
2
Place mines randomly: scatter the target number of mines across unique cells.
3
Neighbor count: for each cell, check the 8 surrounding cells and count mines.
4
Cascade open (recursion): when opening a cell with 0 mine neighbors, recursively open its neighbors.
Extension Challenges
  • Add a flagging feature for marking suspected mines.
  • Make sure the first click never hits a mine.
  • Let the player pick the board size and number of mines.
  • Measure and display the clear time.
  • Save high scores to a file.
🧱

GAME 10: Falling Block Puzzle (Tetris-like)

Advanced 2D Arrays Structs Timer
Blocks fall from the top and clear when a row fills. The ultimate text-mode Tetris-like challenge.
| | | | | | | ## | | ## | | | | | | # | | ### | | #### ## | +----------+ Score: 100 Level: 1
1
Represent the playfield with a 2D array that stores locked blocks.
2
Define tetrominoes with a struct and arrays: 7 shapes as 4x4 grids.
3
Collision detection: make sure a rotated or moved piece doesn't overlap walls or locked blocks.
4
Line clears: remove full rows and drop everything above them down.
Extension Challenges
  • Preview the next piece.
  • Increase falling speed as the level rises.
  • Hold feature (stash one piece for later).
  • Save high scores to a file.
Hint: For real-time terminal input you'll need non-blocking reads — termios.h on Linux/Mac or conio.h on Windows. The easiest starting point is a turn-based version that waits for each keystroke.

Roadmap

Difficulty ramps up as you go. Start with GAME 1–3, and once you feel comfortable, move on to 4–7.
Beginner
Number Guess
Beginner
RPS
Beginner
Slot Machine
Intermediate
Tic-Tac-Toe
Intermediate
Maze
Intermediate
Blackjack
Intermediate
Hangman
Advanced
RPG Battle
Advanced
Minesweeper
Advanced
Tetris-like
Share this article
Share on X Share on Facebook