- Fun Sentence Generator!
- 03 May 2025 07:11:51 pm
- Last edited by CarJeepTruckson on 05 May 2025 08:01:07 pm; edited 1 time in total
I'm happy to share this program that I made in c, using the CE C/C++ Toolchain. It's called the Sentence Generator
The program generates random, plausible, sentences(yes I'm aware that they don't really make sense) from defined structures and word lists. You'll get everything from boring statements to funny combinations.
Features:
Here is a screenshot:
Here is the code in c:
Code:
Download Here:https://drive.google.com/file/d/1ZMDvgwvTPKxbco7htAkbQhUeqlx2yfIy/view?usp=sharing
The program generates random, plausible, sentences(yes I'm aware that they don't really make sense) from defined structures and word lists. You'll get everything from boring statements to funny combinations.
Features:
- Random Generation: Always unique by using the real-time clock.
Variety of Words: It includes many different types of words.
Structured templates: It uses predefined structures to guide the sentences.
Basic Agreement: Tries to make it keep agreement between subjects.
Graphical Display: Uses the graphx module to display the sentences.
Word Wrapping: Longer sentences wrap onto the next line.
Simple Controls: Very easy to use.
Here is a screenshot:
Here is the code in c:
Code:
#include <graphx.h>
#include <keypadc.h>
#include <stdlib.h>
#include <string.h>
#include <tice.h> // Used for rtc_Time() for srand seed
#include <stdint.h>
#include <ctype.h> // Used for toupper()
#define MAX_WORDS 15
#define MAX_SENTENCE_LENGTH 256
// --- Colors ---
#define COLOR_BLACK 0
#define COLOR_WHITE 255
// --- Data ---
const char *articles_singular[] = {"the", "a", "my", "your", "his", "her", "our", "their", "this", "that", "each", "every", "another", "one"};
const char *articles_plural[] = {"the", "my", "your", "his", "her", "our", "their", "these", "those", "all", "some", "many", "few"};
const char *adjectives[] = {"happy", "silly", "fast", "blue", "big", "small", "red", "brave", "quiet", "loud", "clever", "gentle", "wild", "calm", "strange", "old", "young", "new", "good", "bad", "beautiful", "ugly", "bright", "dark", "strong", "weak", "soft", "hard", "long", "short", "tall", "short", "heavy", "light", "funny", "serious", "delicious", "awful", "lovely", "horrible", "quick", "slow", "smart", "foolish", "rich", "poor", "famous", "shy", "energetic", "lazy", "kind", "cruel", "polite", "rude", "honest", "dishonest", "loyal", "disloyal", "patient", "impatient", "generous", "selfish", "optimistic", "pessimistic", "cheerful", "gloomy", "peaceful", "noisy", "careful", "careless", "creative", "boring", "popular", "unpopular", "healthy", "sick", "wise", "naive", "grateful", "ungrateful"};
const char *nouns_singular[] = {"cat", "dog", "bird", "car", "tree", "house", "book", "computer", "flower", "sun", "moon", "star", "river", "mountain", "cloud", "ocean", "friend", "teacher", "student", "ball", "game", "song", "apple", "banana", "orange", "grape", "table", "chair", "desk", "phone", "clock", "shoe", "hat", "coat", "shirt", "pants", "skirt", "dress", "cup", "plate", "knife", "fork", "spoon", "glass", "bottle", "door", "window", "wall", "floor", "ceiling", "bed", "pillow", "blanket", "lamp", "key", "lock", "pen", "pencil", "paper", "picture", "radio", "television", "camera", "watch", "money", "ticket", "ticket", "plane", "train", "bus", "boat", "bike", "map", "globe", "city", "country", "world", "planet", "galaxy", "universe", "beach", "forest", "park", "school", "hospital", "restaurant", "store", "museum", "library", "office", "factory", "bridge", "road", "path", "sky", "earth", "wind", "rain", "snow", "ice", "fire", "water", "stone", "wood", "metal", "music", "movie", "art", "dance", "sport", "team", "idea", "dream", "plan", "reason", "problem", "solution", "question", "answer", "story", "poem", "letter", "message", "secret", "promise", "gift", "toy", "tool", "machine", "plant", "animal", "person", "child", "man", "woman", "king", "queen", "prince", "princess", "hero", "villain"};
const char *nouns_plural[] = {"cats", "dogs", "birds", "cars", "trees", "houses", "books", "computers", "flowers", "suns", "moons", "stars", "rivers", "mountains", "clouds", "oceans", "friends", "teachers", "students", "balls", "games", "songs", "apples", "bananas", "oranges", "grapes", "tables", "chairs", "desks", "phones", "clocks", "shoes", "hats", "coats", "shirts", "pants", "skirts", "dresses", "cups", "plates", "knives", "forks", "spoons", "glasses", "bottles", "doors", "windows", "walls", "floors", "ceilings", "beds", "pillows", "blankets", "lamps", "keys", "locks", "pens", "pencils", "papers", "pictures", "radios", "televisions", "cameras", "watches", "money", "tickets", "tickets", "planes", "trains", "buses", "boats", "bikes", "maps", "globes", "cities", "countries", "worlds", "planets", "galaxies", "universes", "beaches", "forests", "parks", "schools", "hospitals", "restaurants", "stores", "museums", "libraries", "offices", "factories", "bridges", "roads", "paths", "skies", "earths", "winds", "rains", "snows", "ices", "fires", "waters", "stones", "woods", "metals", "music", "movies", "art", "dances", "sports", "teams", "ideas", "dreams", "plans", "reasons", "problems", "solutions", "questions", "answers", "stories", "poems", "letters", "messages", "secrets", "promises", "gifts", "toys", "tools", "machines", "plants", "animals", "people", "children", "men", "women", "kings", "queens", "princes", "princesses", "heroes", "villains"};
const char *verbs_singular[] = {"runs", "jumps", "sings", "drives", "grows", "sleeps", "eats", "reads", "writes", "plays", "flies", "swims", "thinks", "dreams", "works", "learns", "laughs", "cries", "talks", "walks", "looks", "sees", "hears", "touches", "feels", "tastes", "smells", "speaks", "listens", "waits", "hopes", "believes", "knows", "understands", "remembers", "forgets", "loves", "hates", "helps", "hurts", "gives", "takes", "finds", "loses", "makes", "breaks", "builds", "destroys", "opens", "closes", "starts", "stops", "turns", "changes", "chooses", "decides", "asks", "answers", "calls", "shows", "hides", "uses", "sells", "buys", "wins", "loses", "create", "destroy", "protect", "attack", "support", "oppose", "allow", "forbid", "encourage", "discourage", "agree", "disagree", "invite", "refuse", "prefer", "accept", "reject", "visit", "live", "die"};
const char *verbs_plural[] = {"run", "jump", "sing", "drive", "grow", "sleep", "eat", "read", "write", "play", "fly", "swim", "think", "dream", "work", "learn", "laugh", "cry", "talk", "walk", "look", "see", "hear", "touch", "feel", "taste", "smell", "speak", "listen", "wait", "hope", "believe", "know", "understand", "remember", "forget", "love", "hate", "help", "hurt", "give", "take", "find", "lose", "make", "break", "build", "destroy", "open", "close", "start", "stop", "turn", "change", "choose", "decide", "ask", "answer", "call", "show", "hide", "use", "sell", "buy", "win", "lose", "create", "destroy", "protect", "attack", "support", "oppose", "allow", "forbid", "encourage", "discourage", "agree", "disagree", "invite", "refuse", "prefer", "accept", "reject", "visit", "live", "die"};
const char *adverbs[] = {"quickly", "slowly", "loudly", "happily", "carefully", "sadly", "quietly", "easily", "well", "badly", "eagerly", "silently", "softly", "bravely", "mysteriously", "often", "rarely", "always", "never", "sometimes", "usually", "generally", "normally", "occasionally", "seldom", "frequently", "constantly", "continually", "regularly", "irregularly", "punctually", "late", "early", "soon", "now", "then", "later", "before", "after", "again", "once", "twice", "thrice", "mostly", "partially", "fully", "completely", "almost", "nearly", "totally", "slightly", "somewhat", "especially", "particularly", "surprisingly", "suddenly", "gradually", "eventually", "finally", "certainly", "probably", "possibly", "maybe", "perhaps", "definitely", "absolutely", "clearly", "obviously", "simply", "just", "merely", "only", "simply", "indeed", "actually", "really", "virtually", "practically", "technically", "literally", "figuratively", "approximately"};
const char *prepositions[] = {"on", "in", "under", "over", "by", "near", "with", "through", "around", "at", "above", "below", "beside", "behind", "between", "among", "across", "along", "towards", "from", "into", "onto", "out", "within", "without", "against", "beyond", "upon", "beneath", "during", "before", "after", "until", "since", "for"};
const char *conjunctions[] = {"and", "but", "or", "so", "because", "if", "although", "though", "while", "unless", "since", "as", "when", "where", "whenever", "wherever", "before", "after", "until", "once"};
const char *pronouns_singular[] = {"he", "she", "it"};
const char *pronouns_plural[] = {"they"};
// --- Sentence structures ---
const char *sentence_structures[] = {
"[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Adverb].",
"[Pronoun:subject] [Verb:subject] [Adverb] [Preposition] [Article:noun] [Noun].",
"[Article:noun] [Noun:subject] [Verb:subject] [Conjunction] [Article:noun] [Noun:noun] [Verb:noun].",
"[Pronoun:subject] [Verb:subject] [Article:noun] [Adjective] [Noun].",
"[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Preposition] [Article:noun] [Noun:noun].",
"[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Adverb] [Conjunction] [Article:noun] [Adjective] [Noun:noun] [Verb:noun].",
"[Pronoun:subject] [Verb:subject] [Adverb] [Preposition] [Article:noun] [Adjective] [Noun].",
"[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Preposition] [Article:noun] [Noun:noun] [Conjunction] [Article:noun] [Noun:noun] [Verb:noun]."
};
const int num_sentence_structures = sizeof(sentence_structures) / sizeof(sentence_structures[0]);
// --- Functions ---
char * generate_sentence() {
static char sentence[MAX_SENTENCE_LENGTH];
memset(sentence, 0, MAX_SENTENCE_LENGTH);
const char *structure = sentence_structures[rand() % num_sentence_structures];
int used_words[8][64] = {0}; // Tracks if a word has been used for a specific category
int subjects[1] = {0}; // 0=undetermined, 1=singular, 2=plural
int i;
for (i = 0; structure[i] != '\0'; ++i)
{
if (structure[i] == '[')
{
int start = i + 1;
int end = 0;
for (int j = start; structure[j] != '\0'; ++j)
{
if (structure[j] == ']')
{
end = j;
break;
}
}
if (end == 0) break; // Malformed structure, stop processing
char key_type[20] = {0};
char modifier[20] = {0};
int k = 0; // Index of ':'
for(int j = start; j < end; j++)
{
if (structure[j] == ':')
{
k = j;
break;
}
key_type[j - start] = structure[j];
}
if (k) // If ':' was found
{
for (int j = k + 1; j < end; j++)
modifier[j - k - 1] = structure[j];
}
else // No modifier, copy key_type as modifier for simpler logic later
{
strncpy(modifier, key_type, sizeof(modifier) - 1);
}
const char **word_list = NULL;
int num_words = 0;
int word_category_index = -1; // Index for used_words array
// Determine word list and category index
if (strcmp(key_type, "Article") == 0) {
word_category_index = 0;
if (strcmp(modifier, "noun") == 0) {
if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
word_list = (subjects[0] == 1) ? articles_singular : articles_plural;
num_words = (subjects[0] == 1) ? sizeof(articles_singular) / sizeof(articles_singular[0]) : sizeof(articles_plural) / sizeof(articles_plural[0]);
} else {
word_list = articles_singular; // Default or unknown modifier
num_words = sizeof(articles_singular) / sizeof(articles_singular[0]);
}
} else if (strcmp(key_type, "Adjective") == 0) {
word_category_index = 1;
word_list = adjectives;
num_words = sizeof(adjectives) / sizeof(adjectives[0]);
} else if (strcmp(key_type, "Noun") == 0) {
word_category_index = 2;
if (strcmp(modifier, "subject") == 0) {
if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
word_list = (subjects[0] == 1) ? nouns_singular : nouns_plural;
num_words = (subjects[0] == 1) ? sizeof(nouns_singular) / sizeof(nouns_singular[0]) : sizeof(nouns_plural) / sizeof(nouns_plural[0]);
} else if (strcmp(modifier, "noun") == 0) {
// Noun modifier implies it should match subject plurality if determined
if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
word_list = (subjects[0] == 1) ? nouns_singular : nouns_plural;
num_words = (subjects[0] == 1) ? sizeof(nouns_singular) / sizeof(nouns_singular[0]) : sizeof(nouns_plural) / sizeof(nouns_plural[0]);
} else {
word_list = nouns_singular; // Default
num_words = sizeof(nouns_singular) / sizeof(nouns_singular[0]);
}
} else if (strcmp(key_type, "Verb") == 0) {
word_category_index = 3;
if (strcmp(modifier, "subject") == 0 || strcmp(modifier, "noun") == 0) { // Verb matches subject/noun
if(subjects[0] == 0) subjects[0] = rand() % 2 + 1;
word_list = (subjects[0] == 1) ? verbs_singular : verbs_plural;
num_words = (subjects[0] == 1) ? sizeof(verbs_singular) / sizeof(verbs_singular[0]) : sizeof(verbs_plural) / sizeof(verbs_plural[0]);
} else {
word_list = verbs_singular; // Default
num_words = sizeof(verbs_singular) / sizeof(verbs_singular[0]);
}
} else if (strcmp(key_type, "Adverb") == 0) {
word_category_index = 4;
word_list = adverbs;
num_words = sizeof(adverbs) / sizeof(adverbs[0]);
} else if (strcmp(key_type, "Preposition") == 0) {
word_category_index = 5;
word_list = prepositions;
num_words = sizeof(prepositions) / sizeof(prepositions[0]);
} else if (strcmp(key_type, "Conjunction") == 0) {
word_category_index = 6;
word_list = conjunctions;
num_words = sizeof(conjunctions) / sizeof(conjunctions[0]);
} else if (strcmp(key_type, "Pronoun") == 0) {
word_category_index = 7;
if (strcmp(modifier, "subject") == 0) {
if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
word_list = (subjects[0] == 1) ? pronouns_singular : pronouns_plural;
num_words = (subjects[0] == 1) ? sizeof(pronouns_singular) / sizeof(pronouns_singular[0]) : sizeof(pronouns_plural) / sizeof(pronouns_plural[0]);
} else {
word_list = pronouns_singular; // Default
num_words = sizeof(pronouns_singular) / sizeof(pronouns_singular[0]);
}
}
// If a valid word list was found
if (word_list != NULL && num_words > 0 && word_category_index != -1) {
int chosen_word_index = rand() % num_words;
int attempts = 0; // Prevent infinite loop if all words used (unlikely)
// Find an unused word for this category
while(attempts < num_words) {
bool found = false;
for (int z = 0; z < 64; z++) {
if (used_words[word_category_index][z] == 0) break; // End of used list
if (used_words[word_category_index][z] == chosen_word_index + 1) {
found = true;
break;
}
}
if (!found) break; // Word is not used, exit while loop
// Word was used, try next one
chosen_word_index = (chosen_word_index + 1) % num_words;
attempts++;
}
// Mark the word as used for this category
if (attempts < num_words) {
for(int z = 0; z < 64; z++) {
if (used_words[word_category_index][z] == 0) {
used_words[word_category_index][z] = chosen_word_index + 1;
break;
}
}
}
// else { // Fallback if all words somehow used
// chosen_word_index = rand() % num_words;
// }
const char* chosen_word = word_list[chosen_word_index];
int len = strlen(chosen_word);
int current_sentence_len = strlen(sentence);
// Check if there's enough space for the word and potentially a space + null terminator
if (MAX_SENTENCE_LENGTH - current_sentence_len - 1 >= len + 1) { // +1 for potential space or just null term
// Add a space BEFORE the word if:
// 1. Not the first word being added (current_sentence_len > 0).
// 2. The character *before* the opening bracket '[' in the template was a space.
if (current_sentence_len > 0 && i > 0 && structure[i - 1] == ' ') {
// Check space remaining *just* for the space
if (current_sentence_len < MAX_SENTENCE_LENGTH - 2) {
strcat(sentence, " ");
current_sentence_len++; // Update length after adding space
} else {
break; // Not enough space even for the preceding space
}
}
// Add the word itself, checking space again in case only the space fit
if (MAX_SENTENCE_LENGTH - current_sentence_len - 1 >= len) {
strcat(sentence, chosen_word);
} else {
break; // Not enough space for the word
}
} else {
// Not enough space, maybe truncate or stop
break; // Stop generating sentence if out of space initially
}
}
i = end; // Move loop index past the processed placeholder
}
else if (structure[i] != ' ') { // Don't add spaces from template directly
int current_len = strlen(sentence);
// Remove trailing space before punctuation if present
if (current_len > 0 && sentence[current_len - 1] == ' ' && (structure[i] == '.' || structure[i] == ',' || structure[i] == '!' || structure[i] == '?')) {
sentence[current_len - 1] = '\0'; // Remove trailing space
current_len--;
}
// Add the punctuation if space allows
if (current_len < MAX_SENTENCE_LENGTH - 1) {
sentence[current_len] = structure[i];
sentence[current_len + 1] = '\0';
} else {
break; // Stop if no space for punctuation
}
}
// Skip spaces in the template string, they are handled above based on context
}
// Capitalize the first letter
if(strlen(sentence) > 0){
sentence[0] = toupper(sentence[0]);
}
return sentence;
}
int main(void) {
/* Initialize graphics */
gfx_Begin();
gfx_SetDrawBuffer();
// --- Set colors ---
gfx_SetTextFGColor(COLOR_BLACK); // Black text
gfx_SetTextBGColor(COLOR_WHITE); // White background for text transparency
gfx_SetColor(COLOR_WHITE); // White color for fill
gfx_SetTextConfig(gfx_text_noclip);
gfx_FillScreen(COLOR_WHITE); // Clear screen to white background
/* Initialize random seed based on real-time clock */
srand(rtc_Time());
char sentence[MAX_SENTENCE_LENGTH];
strcpy(sentence, generate_sentence());
kb_key_t key;
int text_x, text_y;
const uint8_t sentence_scale_x = 2;
const uint8_t sentence_scale_y = 2;
const int line_height = 8 * sentence_scale_y; // Base font height (8) * Y scale
const int heading_y = 10;
const int footer_y = GFX_LCD_HEIGHT - 20;
const int sentence_start_y = heading_y + 20; // Start sentence below heading
const int sentence_x_offset = 10; // <<<--- ADDED: Define the horizontal offset (e.g., 10 pixels)
// Strings for header/footer
const char *heading_text = "Sentence Generator";
const char *footer_text = "Press ENTER to generate or CLEAR to leave";
/* Main loop */
while (true) {
// Clear the buffer with white background before drawing
gfx_FillScreen(COLOR_WHITE);
// --- Draw Header and Footer (with default 1x1 scale) ---
gfx_SetTextScale(1, 1);
// Center and draw heading
text_x = (GFX_LCD_WIDTH - gfx_GetStringWidth(heading_text)) / 2;
gfx_PrintStringXY(heading_text, text_x, heading_y);
// Center and draw footer
text_x = (GFX_LCD_WIDTH - gfx_GetStringWidth(footer_text)) / 2;
gfx_PrintStringXY(footer_text, text_x, footer_y);
// --- Draw Generated Sentence (with 2x2 scale) ---
gfx_SetTextScale(sentence_scale_x, sentence_scale_y);
// Reset text position for drawing the sentence
text_x = sentence_x_offset; // Start at the offset
text_y = sentence_start_y; // Use calculated start Y
gfx_SetTextXY(text_x, text_y);
// Word wrapping logic
int word_start_index = 0;
for (int i = 0; sentence[i] != '\0'; ++i) {
// Find the end of the current word (space or null terminator)
if (sentence[i] == ' ' || sentence[i+1] == '\0') {
int word_end_index = (sentence[i+1] == '\0') ? i + 1 : i; // Include last char if end of sentence
char word[MAX_SENTENCE_LENGTH] = {0}; // Should be large enough for any single word
strncpy(word, sentence + word_start_index, word_end_index - word_start_index);
// Include the space after the word for width calculation, unless it's the very end
char word_with_space[MAX_SENTENCE_LENGTH + 1] = {0};
strcpy(word_with_space, word);
if (sentence[i] == ' ') {
strcat(word_with_space, " ");
}
// Get width using the current scale (2x2)
int word_width = gfx_GetStringWidth(word_with_space);
// Check if the word fits on the current line
if (text_x + word_width >= GFX_LCD_WIDTH) {
// Doesn't fit, move to the next line
text_x = sentence_x_offset;
text_y += line_height; // Use scaled line height
gfx_SetTextXY(text_x, text_y);
// Check if we're drawing off the screen (below the footer)
if (text_y >= footer_y - line_height) {
break; // Stop drawing if off screen / overlaps footer
}
}
// Print the word (without the trailing space used for width calc)
gfx_PrintString(word);
// Print the space if it exists
if (sentence[i] == ' ') {
gfx_PrintChar(' ');
}
// Update text position and word start index for the next word
text_x = gfx_GetTextX();
word_start_index = i + 1;
}
}
// Swap the buffer to the screen
gfx_BlitBuffer();
// Handle key presses
kb_Scan();
key = kb_Data[6]; // Check group 6 for Enter and Clear
if (key & kb_Enter) {
// Generate a new sentence
strcpy(sentence, generate_sentence());
// Small delay to prevent multiple generations from one press
delay(150);
}
if (key & kb_Clear) {
break; // Exit loop
}
}
/* End graphics */
gfx_End();
return 0;
}Download Here:https://drive.google.com/file/d/1ZMDvgwvTPKxbco7htAkbQhUeqlx2yfIy/view?usp=sharing







