Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5f056237a |
23
Makefile
Normal file
23
Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -O2
|
||||
LIBS = -lX11 -lm
|
||||
|
||||
SRC = src/main.c src/coin.c src/animation.c src/gui_animation.c
|
||||
OBJDIR = obj
|
||||
OBJ = $(OBJDIR)/main.o $(OBJDIR)/coin.o $(OBJDIR)/animation.o $(OBJDIR)/gui_animation.o
|
||||
TARGET = coinfipper
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
$(OBJDIR)/%.o: src/%.c | $(OBJDIR)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(TARGET)
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# coinflipper Project
|
||||
|
||||
This is a C project generated with the setup tool.
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -I../include
|
||||
OBJDIR = ../obj
|
||||
SRCDIR = ../src
|
||||
BINDIR = ../bin
|
||||
TARGET = $(BINDIR)/coin_flip_random_number
|
||||
|
||||
OBJS = $(OBJDIR)/main.o
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
@mkdir -p $(BINDIR)
|
||||
$(CC) $(OBJS) -lncurses -o $(TARGET)
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||
@mkdir -p $(OBJDIR)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(BINDIR)
|
||||
BIN
coinfipper
Executable file
BIN
coinfipper
Executable file
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
#ifndef FUNCTIONS_H
|
||||
#define FUNCTIONS_H
|
||||
|
||||
void flip_coin();
|
||||
void generate_random_number(int lower, int upper);
|
||||
|
||||
#endif // FUNCTIONS_H
|
||||
BIN
obj/animation.o
Normal file
BIN
obj/animation.o
Normal file
Binary file not shown.
BIN
obj/coin.o
Normal file
BIN
obj/coin.o
Normal file
Binary file not shown.
BIN
obj/gui_animation.o
Normal file
BIN
obj/gui_animation.o
Normal file
Binary file not shown.
BIN
obj/main.o
BIN
obj/main.o
Binary file not shown.
219
src/animation.c
Normal file
219
src/animation.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "animation.h"
|
||||
#include "coin.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Internal function declarations
|
||||
static void run_terminal_animation(const char* final_result);
|
||||
static void run_framebuffer_animation(const char* final_result);
|
||||
static int is_framebuffer_available();
|
||||
static void draw_ascii_coin(int width, int height, const char* face);
|
||||
static void draw_fb_detailed_coin(char* fbp, struct fb_var_screeninfo vinfo,
|
||||
struct fb_fix_screeninfo finfo, int centerX,
|
||||
int centerY, int radius, const char* face);
|
||||
|
||||
void run_animation(const char* final_result) {
|
||||
if (is_framebuffer_available()) {
|
||||
run_framebuffer_animation(final_result);
|
||||
} else {
|
||||
run_terminal_animation(final_result);
|
||||
}
|
||||
}
|
||||
|
||||
// Try opening /dev/fb0 to see if a framebuffer is available.
|
||||
static int is_framebuffer_available() {
|
||||
int fb = open("/dev/fb0", O_RDWR);
|
||||
if (fb < 0) {
|
||||
return 0; // Not available.
|
||||
}
|
||||
close(fb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Draw an ASCII coin with “engraved” border and pattern.
|
||||
// If face is nonempty, the coin’s center will show the final coin flip result.
|
||||
static void draw_ascii_coin(int width, int height, const char* face) {
|
||||
for (int y = -height; y <= height; y++) {
|
||||
for (int x = -width; x <= width; x++) {
|
||||
float dx = (float)x / width;
|
||||
float dy = (float)y / height;
|
||||
if (dx*dx + dy*dy <= 1.0f) {
|
||||
// Near the edge, print a border engraving.
|
||||
float dist = dx*dx + dy*dy;
|
||||
if (dist > 0.85f)
|
||||
printf("#");
|
||||
else {
|
||||
// Alternate pattern to simulate fine engraving detail.
|
||||
if (((x + y) % 2) == 0)
|
||||
printf(".");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
// If space allows, center the coin flip result as if engraved.
|
||||
if (strlen(face) > 0) {
|
||||
int totalWidth = width * 2 + 1;
|
||||
int textLen = strlen(face);
|
||||
int padding = (totalWidth - textLen) / 2;
|
||||
for (int i = 0; i < padding; i++) printf(" ");
|
||||
printf("[%s]\n", face);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Terminal animation: simulates a coin flip by scaling the coin’s horizontal radius.
|
||||
static void run_terminal_animation(const char* final_result) {
|
||||
int total_frames = 60;
|
||||
int base_width = 12;
|
||||
int base_height = 6;
|
||||
|
||||
for (int frame = 0; frame < total_frames; frame++) {
|
||||
float factor = fabs(sin(frame * M_PI / total_frames));
|
||||
int current_width = (int)(base_width * factor);
|
||||
if (current_width < 1) current_width = 1;
|
||||
// Clear the terminal screen.
|
||||
printf("\033[H\033[J");
|
||||
draw_ascii_coin(current_width, base_height, "");
|
||||
usleep(30000);
|
||||
}
|
||||
// Final engraved coin.
|
||||
printf("\033[H\033[J");
|
||||
draw_ascii_coin(base_width, base_height, final_result);
|
||||
printf("\nFinal Result: %s\n", final_result);
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
// Helper to set a pixel in the framebuffer (supports 32bpp and 16bpp).
|
||||
static void set_pixel(char* fbp, struct fb_var_screeninfo vinfo, long x, long y, unsigned int color) {
|
||||
if (x < 0 || y < 0 || x >= vinfo.xres || y >= vinfo.yres) return;
|
||||
long location = (x + y * vinfo.xres) * (vinfo.bits_per_pixel / 8);
|
||||
if (vinfo.bits_per_pixel == 32) {
|
||||
*((unsigned int*)(fbp + location)) = color;
|
||||
} else if (vinfo.bits_per_pixel == 16) {
|
||||
unsigned short col = (unsigned short)color;
|
||||
*((unsigned short*)(fbp + location)) = col;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a detailed coin on the framebuffer with simulated engravings.
|
||||
// The coin is drawn as a circle with a dark border, inner engraving line, and a subtle pattern.
|
||||
// If face is nonempty, extra marks (simulating a portrait or reverse) are drawn.
|
||||
static void draw_fb_detailed_coin(char* fbp, struct fb_var_screeninfo vinfo,
|
||||
struct fb_fix_screeninfo finfo, int centerX,
|
||||
int centerY, int radius, const char* face) {
|
||||
// Define colors (in 0xRRGGBB format – conversion may be needed on some systems).
|
||||
unsigned int gold = 0xFFD700; // Base gold fill.
|
||||
unsigned int darkGold = 0xB8860B; // Border and detail.
|
||||
unsigned int engravingColor = 0x8B7500; // For fine engraving lines.
|
||||
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
float dx = (float)x / radius;
|
||||
float dy = (float)y / radius;
|
||||
if (dx*dx + dy*dy <= 1.0f) {
|
||||
int px = centerX + x;
|
||||
int py = centerY + y;
|
||||
float dist = sqrt(dx*dx + dy*dy);
|
||||
if (dist > 0.9f) {
|
||||
set_pixel(fbp, vinfo, px, py, darkGold);
|
||||
} else if (fabs(dist - 0.5f) < 0.05f) {
|
||||
set_pixel(fbp, vinfo, px, py, engravingColor);
|
||||
} else {
|
||||
set_pixel(fbp, vinfo, px, py, gold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Overlay additional detail based on coin face.
|
||||
if (strlen(face) > 0) {
|
||||
if (strcmp(face, "Heads") == 0) {
|
||||
// Simulate a simplified portrait engraving.
|
||||
for (int y = -radius/4; y <= radius/4; y++) {
|
||||
for (int x = -radius/4; x <= radius/4; x++) {
|
||||
if ((x + y) % 3 == 0) {
|
||||
set_pixel(fbp, vinfo, centerX + x, centerY + y, darkGold);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Simulate reverse-side engraving.
|
||||
for (int y = -radius/4; y <= radius/4; y++) {
|
||||
for (int x = -radius/4; x <= radius/4; x++) {
|
||||
if ((x - y) % 3 == 0) {
|
||||
set_pixel(fbp, vinfo, centerX + x, centerY + y, darkGold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Framebuffer animation: flips the coin with a scaling effect and then renders the final engraved coin.
|
||||
static void run_framebuffer_animation(const char* final_result) {
|
||||
int fb_fd = open("/dev/fb0", O_RDWR);
|
||||
if (fb_fd < 0) {
|
||||
perror("Error opening /dev/fb0");
|
||||
return;
|
||||
}
|
||||
|
||||
struct fb_var_screeninfo vinfo;
|
||||
struct fb_fix_screeninfo finfo;
|
||||
|
||||
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo)) {
|
||||
perror("Error reading fixed information");
|
||||
close(fb_fd);
|
||||
return;
|
||||
}
|
||||
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo)) {
|
||||
perror("Error reading variable information");
|
||||
close(fb_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
long screensize = vinfo.yres_virtual * finfo.line_length;
|
||||
char *fbp = (char *) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
|
||||
if (fbp == MAP_FAILED) {
|
||||
perror("Error: failed to map framebuffer device to memory");
|
||||
close(fb_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
int centerX = vinfo.xres / 2;
|
||||
int centerY = vinfo.yres / 2;
|
||||
int radius = (vinfo.yres < vinfo.xres ? vinfo.yres : vinfo.xres) / 8;
|
||||
int total_frames = 60;
|
||||
|
||||
for (int f = 0; f < total_frames; f++) {
|
||||
float factor = fabs(sin(f * M_PI / total_frames));
|
||||
int currentRadius = (int)(radius * factor);
|
||||
if (currentRadius < 1) currentRadius = 1;
|
||||
// Clear the framebuffer (black).
|
||||
memset(fbp, 0, screensize);
|
||||
draw_fb_detailed_coin(fbp, vinfo, finfo, centerX, centerY, currentRadius, "");
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
// Final coin engraving showing the actual flip result.
|
||||
memset(fbp, 0, screensize);
|
||||
draw_fb_detailed_coin(fbp, vinfo, finfo, centerX, centerY, radius, final_result);
|
||||
usleep(2000000);
|
||||
|
||||
munmap(fbp, screensize);
|
||||
close(fb_fd);
|
||||
}
|
||||
|
||||
9
src/animation.h
Normal file
9
src/animation.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef ANIMATION_H
|
||||
#define ANIMATION_H
|
||||
|
||||
// Runs the coin flipping animation for the terminal or framebuffer.
|
||||
// The final_result ("Heads" or "Tails") is used to choose the engraved design.
|
||||
void run_animation(const char* final_result);
|
||||
|
||||
#endif
|
||||
|
||||
BIN
src/animation.o
Normal file
BIN
src/animation.o
Normal file
Binary file not shown.
13
src/coin.c
Normal file
13
src/coin.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "coin.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
const char* flip_coin() {
|
||||
// Seed random number generator (for a simple example; in a larger program, you might do this once in main)
|
||||
srand(time(NULL));
|
||||
if (rand() % 2 == 0)
|
||||
return "Heads";
|
||||
else
|
||||
return "Tails";
|
||||
}
|
||||
|
||||
8
src/coin.h
Normal file
8
src/coin.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef COIN_H
|
||||
#define COIN_H
|
||||
|
||||
// Returns "Heads" or "Tails"
|
||||
const char* flip_coin();
|
||||
|
||||
#endif
|
||||
|
||||
BIN
src/coin.o
Normal file
BIN
src/coin.o
Normal file
Binary file not shown.
116
src/gui_animation.c
Normal file
116
src/gui_animation.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "gui_animation.h"
|
||||
#include "coin.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159
|
||||
#endif
|
||||
|
||||
// Draw a detailed coin in the X11 window using drawing primitives.
|
||||
static void draw_gui_detailed_coin(Display *d, Window win, GC gc, int win_width, int win_height, int radius, const char* face) {
|
||||
// Define colors.
|
||||
unsigned long gold = 0xFFD700;
|
||||
unsigned long darkGold = 0xB8860B;
|
||||
unsigned long engravingColor = 0x8B7500;
|
||||
|
||||
int coin_diameter = radius * 2;
|
||||
int x = (win_width - coin_diameter) / 2;
|
||||
int y = (win_height - coin_diameter) / 2;
|
||||
|
||||
// Fill coin circle with gold.
|
||||
XSetForeground(d, gc, gold);
|
||||
XFillArc(d, win, gc, x, y, coin_diameter, coin_diameter, 0, 360*64);
|
||||
|
||||
// Draw outer border.
|
||||
XSetForeground(d, gc, darkGold);
|
||||
XDrawArc(d, win, gc, x, y, coin_diameter, coin_diameter, 0, 360*64);
|
||||
|
||||
// Draw an inner engraving circle.
|
||||
int inner_diameter = coin_diameter * 0.7;
|
||||
int inner_x = (win_width - inner_diameter) / 2;
|
||||
int inner_y = (win_height - inner_diameter) / 2;
|
||||
XSetForeground(d, gc, engravingColor);
|
||||
XDrawArc(d, win, gc, inner_x, inner_y, inner_diameter, inner_diameter, 0, 360*64);
|
||||
|
||||
// Overlay text to simulate the coin’s face engraving.
|
||||
char text[50];
|
||||
if (strcmp(face, "Heads") == 0)
|
||||
snprintf(text, sizeof(text), "LIBERTY");
|
||||
else
|
||||
snprintf(text, sizeof(text), "E PLURIBUS UNUM");
|
||||
|
||||
/* Instead of using DefaultFont (which is undefined), we load the "fixed" font */
|
||||
XFontStruct *font = XLoadQueryFont(d, "fixed");
|
||||
if (!font) {
|
||||
fprintf(stderr, "Failed to load font 'fixed'\n");
|
||||
return;
|
||||
}
|
||||
XSetFont(d, gc, font->fid);
|
||||
int text_width = XTextWidth(font, text, strlen(text));
|
||||
int text_x = (win_width - text_width) / 2;
|
||||
int text_y = win_height / 2;
|
||||
XSetForeground(d, gc, darkGold);
|
||||
XDrawString(d, win, gc, text_x, text_y, text, strlen(text));
|
||||
|
||||
XFreeFont(d, font);
|
||||
}
|
||||
|
||||
// GUI animation: uses X11 to animate a coin flip with a scaling (flipping) effect
|
||||
// and then renders the final detailed coin with engravings.
|
||||
void run_gui_animation(const char* final_result) {
|
||||
char *display_name = getenv("DISPLAY");
|
||||
if (!display_name) {
|
||||
fprintf(stderr, "No DISPLAY environment variable set. Cannot run GUI animation.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Display *d = XOpenDisplay(NULL);
|
||||
if (d == NULL) {
|
||||
fprintf(stderr, "Unable to open X display.\n");
|
||||
return;
|
||||
}
|
||||
int screen = DefaultScreen(d);
|
||||
int win_width = 500, win_height = 500;
|
||||
Window win = XCreateSimpleWindow(d, RootWindow(d, screen), 100, 100, win_width, win_height, 1,
|
||||
BlackPixel(d, screen), WhitePixel(d, screen));
|
||||
XSelectInput(d, win, ExposureMask | KeyPressMask);
|
||||
XMapWindow(d, win);
|
||||
|
||||
// Wait for an expose event.
|
||||
XEvent e;
|
||||
while (1) {
|
||||
XNextEvent(d, &e);
|
||||
if (e.type == Expose)
|
||||
break;
|
||||
}
|
||||
|
||||
GC gc = XCreateGC(d, win, 0, 0);
|
||||
|
||||
int total_frames = 60;
|
||||
int coin_radius = 100;
|
||||
|
||||
for (int frame = 0; frame < total_frames; frame++) {
|
||||
XClearWindow(d, win);
|
||||
float factor = fabs(sin(frame * M_PI / total_frames));
|
||||
int current_radius = (int)(coin_radius * factor);
|
||||
if (current_radius < 1) current_radius = 1;
|
||||
draw_gui_detailed_coin(d, win, gc, win_width, win_height, current_radius, "");
|
||||
XFlush(d);
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
// Final engraved coin.
|
||||
XClearWindow(d, win);
|
||||
draw_gui_detailed_coin(d, win, gc, win_width, win_height, coin_radius, final_result);
|
||||
XFlush(d);
|
||||
|
||||
sleep(3);
|
||||
XCloseDisplay(d);
|
||||
}
|
||||
|
||||
9
src/gui_animation.h
Normal file
9
src/gui_animation.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef GUI_ANIMATION_H
|
||||
#define GUI_ANIMATION_H
|
||||
|
||||
// Runs the GUI-based coin flip animation in an X11 window.
|
||||
// The final_result ("Heads" or "Tails") determines the engraved design.
|
||||
void run_gui_animation(const char* final_result);
|
||||
|
||||
#endif
|
||||
|
||||
BIN
src/gui_animation.o
Normal file
BIN
src/gui_animation.o
Normal file
Binary file not shown.
209
src/main.c
209
src/main.c
@@ -1,190 +1,35 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "coin.h"
|
||||
#include "animation.h"
|
||||
#include "gui_animation.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <ncurses.h>
|
||||
#include <unistd.h> // For usleep()
|
||||
#include <unistd.h>
|
||||
|
||||
#define DELAY 300000 // 300 ms delay for animation
|
||||
|
||||
// Function prototypes
|
||||
void flip_coin();
|
||||
void generate_random_number(int lower, int upper);
|
||||
void coin_animation(int result);
|
||||
void random_number_animation(int num);
|
||||
void handle_exit();
|
||||
|
||||
int main() {
|
||||
int choice, lower, upper;
|
||||
|
||||
srand(time(NULL)); // Seed the random number generator
|
||||
|
||||
// Initialize ncurses
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
curs_set(0);
|
||||
keypad(stdscr, TRUE); // Enable arrow keys and special keys
|
||||
|
||||
int term_height, term_width;
|
||||
getmaxyx(stdscr, term_height, term_width); // Get terminal size
|
||||
|
||||
while (1) {
|
||||
clear();
|
||||
mvprintw(term_height / 2 - 3, (term_width - 35) / 2, "Choose an option (Press 'q' or 'Esc' to quit):");
|
||||
mvprintw(term_height / 2 - 1, (term_width - 20) / 2, "1. Flip a coin");
|
||||
mvprintw(term_height / 2, (term_width - 20) / 2, "2. Generate a random number");
|
||||
mvprintw(term_height / 2 + 1, (term_width - 20) / 2, "3. Exit");
|
||||
mvprintw(term_height / 2 + 3, (term_width - 20) / 2, "Enter your choice: ");
|
||||
refresh();
|
||||
|
||||
char input = getch();
|
||||
choice = input - '0';
|
||||
|
||||
if (input == 'q' || input == 27) { // 'q' or 'Esc'
|
||||
handle_exit();
|
||||
}
|
||||
|
||||
switch (choice) {
|
||||
case 1:
|
||||
clear();
|
||||
flip_coin();
|
||||
break;
|
||||
case 2:
|
||||
clear();
|
||||
mvprintw(4, 4, "Enter the lower bound: ");
|
||||
echo();
|
||||
scanw("%d", &lower);
|
||||
mvprintw(5, 4, "Enter the upper bound: ");
|
||||
scanw("%d", &upper);
|
||||
noecho();
|
||||
clear();
|
||||
generate_random_number(lower, upper);
|
||||
break;
|
||||
case 3:
|
||||
handle_exit();
|
||||
break;
|
||||
default:
|
||||
mvprintw(10, 4, "Invalid choice, please try again.");
|
||||
refresh();
|
||||
usleep(1000000); // Pause for 1 second before clearing
|
||||
int main(int argc, char **argv) {
|
||||
int animate_flag = 0;
|
||||
int gui_flag = 0;
|
||||
|
||||
// Parse command-line arguments
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-A") == 0 || strcmp(argv[i], "--animation") == 0) {
|
||||
animate_flag = 1;
|
||||
} else if (strcmp(argv[i], "-G") == 0 || strcmp(argv[i], "--gui") == 0) {
|
||||
gui_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
endwin(); // End ncurses mode
|
||||
|
||||
// Determine coin flip result once.
|
||||
const char *result = flip_coin();
|
||||
|
||||
if (gui_flag) {
|
||||
run_gui_animation(result);
|
||||
} else if (animate_flag) {
|
||||
run_animation(result);
|
||||
} else {
|
||||
printf("%s\n", result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flip_coin() {
|
||||
int result = rand() % 2;
|
||||
coin_animation(result);
|
||||
if (result == 0)
|
||||
mvprintw(LINES - 2, (COLS - 7) / 2, "Heads!"); // Align below the animation
|
||||
else
|
||||
mvprintw(LINES - 2, (COLS - 7) / 2, "Tails!");
|
||||
refresh();
|
||||
usleep(2000000); // Display result for 2 seconds
|
||||
}
|
||||
|
||||
void generate_random_number(int lower, int upper) {
|
||||
if (lower > upper) {
|
||||
mvprintw(8, 4, "Invalid range! Lower bound must be less than or equal to upper bound.");
|
||||
refresh();
|
||||
usleep(2000000); // Pause for 2 seconds
|
||||
return;
|
||||
}
|
||||
int num = (rand() % (upper - lower + 1)) + lower;
|
||||
random_number_animation(num);
|
||||
mvprintw(10, 4, "Random number: %d", num);
|
||||
refresh();
|
||||
usleep(2000000); // Display result for 2 seconds
|
||||
}
|
||||
|
||||
void coin_animation(int result) {
|
||||
const char *flat_coin =
|
||||
" _______ \n"
|
||||
" | | \n"
|
||||
" |_______| \n";
|
||||
|
||||
const char *first_circle_coin =
|
||||
" ______ \n"
|
||||
" / \\ \n"
|
||||
" | | \n"
|
||||
" \\______/ \n";
|
||||
|
||||
const char *second_circle_coin =
|
||||
" ____ \n"
|
||||
" // \\ \n"
|
||||
" | | \n"
|
||||
" \\____// \n";
|
||||
|
||||
const char *side_coin_vertical =
|
||||
" |=| \n"
|
||||
" |=| \n"
|
||||
" |=| \n"
|
||||
" |=| \n";
|
||||
|
||||
const char *side_coin_horizontal =
|
||||
" _______ \n"
|
||||
" ||||||| \n"
|
||||
" ¯¯¯¯¯¯¯ \n";
|
||||
|
||||
int height = 5; // Height the coin will "move" up
|
||||
|
||||
// Center coin horizontally
|
||||
int x_center = (COLS - 11) / 2;
|
||||
|
||||
// Animating the coin going up and down with better alignment
|
||||
for (int i = 0; i < height; i++) {
|
||||
clear();
|
||||
if (i == 2) {
|
||||
mvprintw(4 + i, x_center, "%s", first_circle_coin); // Coin facing the user at the peak
|
||||
} else if (i == 1 || i == 3) {
|
||||
mvprintw(4 + i, x_center, "%s", side_coin_vertical); // Vertical side coin
|
||||
} else {
|
||||
mvprintw(4 + i, x_center, "%s", flat_coin); // Flat coin at start and end
|
||||
}
|
||||
refresh();
|
||||
usleep(DELAY);
|
||||
}
|
||||
|
||||
// Display the final result as heads or tails, with proper alignment
|
||||
clear();
|
||||
mvprintw(4 + height, x_center, "%s", second_circle_coin); // Show circle coin
|
||||
if (result == 0) {
|
||||
mvprintw(6 + height, x_center + 4, "O"); // Center the "O" inside the coin
|
||||
} else {
|
||||
mvprintw(6 + height, x_center + 4, "X"); // Center the "X" inside the coin
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void random_number_animation(int num) {
|
||||
char *box_top = "+--------+\n";
|
||||
char *box_bottom = "+--------+\n";
|
||||
char number_display[20];
|
||||
|
||||
// Handle different number lengths
|
||||
if (num < 10) {
|
||||
sprintf(number_display, "| %d |\n", num);
|
||||
} else if (num < 100) {
|
||||
sprintf(number_display, "| %d |\n", num);
|
||||
} else {
|
||||
sprintf(number_display, "| %d |\n", num);
|
||||
}
|
||||
|
||||
int x_center = (COLS - 10) / 2;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
clear();
|
||||
mvprintw(4, x_center, "%s", box_top);
|
||||
mvprintw(5, x_center, "%s", number_display);
|
||||
mvprintw(6, x_center, "%s", box_bottom);
|
||||
refresh();
|
||||
usleep(DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_exit() {
|
||||
endwin(); // End ncurses mode
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
// Function prototypes
|
||||
void flip_coin();
|
||||
void generate_random_number(int lower, int upper);
|
||||
|
||||
int main() {
|
||||
int choice, lower, upper;
|
||||
|
||||
srand(time(NULL)); // Seed the random number generator
|
||||
|
||||
while (1) {
|
||||
printf("\nChoose an option:\n");
|
||||
printf("1. Flip a coin\n");
|
||||
printf("2. Generate a random number\n");
|
||||
printf("3. Exit\n");
|
||||
printf("Enter your choice: ");
|
||||
scanf("%d", &choice);
|
||||
|
||||
switch (choice) {
|
||||
case 1:
|
||||
flip_coin();
|
||||
break;
|
||||
case 2:
|
||||
printf("Enter the lower bound: ");
|
||||
scanf("%d", &lower);
|
||||
printf("Enter the upper bound: ");
|
||||
scanf("%d", &upper);
|
||||
generate_random_number(lower, upper);
|
||||
break;
|
||||
case 3:
|
||||
exit(0);
|
||||
default:
|
||||
printf("Invalid choice, please try again.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flip_coin() {
|
||||
int result = rand() % 2;
|
||||
if (result == 0)
|
||||
printf("Heads!\n");
|
||||
else
|
||||
printf("Tails!\n");
|
||||
}
|
||||
|
||||
void generate_random_number(int lower, int upper) {
|
||||
if (lower > upper) {
|
||||
printf("Invalid range! Lower bound must be less than or equal to upper bound.\n");
|
||||
return;
|
||||
}
|
||||
int num = (rand() % (upper - lower + 1)) + lower;
|
||||
printf("Random number: %d\n", num);
|
||||
}
|
||||
BIN
src/main.o
Normal file
BIN
src/main.o
Normal file
Binary file not shown.
31
tags
31
tags
@@ -1,31 +0,0 @@
|
||||
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
|
||||
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
|
||||
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
||||
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
|
||||
!_TAG_PROC_CWD /home/klein/codeWS/C/coinflipper/ //
|
||||
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
||||
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
||||
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
||||
!_TAG_PROGRAM_VERSION 5.9.0 //
|
||||
$(OBJDIR)/%.o build/Makefile /^$(OBJDIR)\/%.o: $(SRCDIR)\/%.c$/;" t
|
||||
$(TARGET) build/Makefile /^$(TARGET): $(OBJS)$/;" t
|
||||
BINDIR build/Makefile /^BINDIR = ..\/bin$/;" m
|
||||
CC build/Makefile /^CC = gcc$/;" m
|
||||
CFLAGS build/Makefile /^CFLAGS = -I..\/include$/;" m
|
||||
DELAY src/main.c /^#define DELAY /;" d file:
|
||||
FUNCTIONS_H include/functions.h /^#define FUNCTIONS_H$/;" d
|
||||
OBJDIR build/Makefile /^OBJDIR = ..\/obj$/;" m
|
||||
OBJS build/Makefile /^OBJS = $(OBJDIR)\/main.o$/;" m
|
||||
SRCDIR build/Makefile /^SRCDIR = ..\/src$/;" m
|
||||
TARGET build/Makefile /^TARGET = $(BINDIR)\/coin_flip_random_number$/;" m
|
||||
all build/Makefile /^all: $(TARGET)$/;" t
|
||||
clean build/Makefile /^clean:$/;" t
|
||||
coin_animation src/main.c /^void coin_animation(int result) {$/;" f typeref:typename:void
|
||||
coinflipper Project README.md /^# coinflipper Project$/;" c
|
||||
flip_coin src/main.c /^void flip_coin() {$/;" f typeref:typename:void
|
||||
generate_random_number src/main.c /^void generate_random_number(int lower, int upper) {$/;" f typeref:typename:void
|
||||
handle_exit src/main.c /^void handle_exit() {$/;" f typeref:typename:void
|
||||
main src/main.c /^int main() {$/;" f typeref:typename:int
|
||||
random_number_animation src/main.c /^void random_number_animation(int num) {$/;" f typeref:typename:void
|
||||
Reference in New Issue
Block a user