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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "coin.h"
|
||||||
|
#include "animation.h"
|
||||||
|
#include "gui_animation.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <unistd.h>
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h> // For usleep()
|
|
||||||
|
|
||||||
#define DELAY 300000 // 300 ms delay for animation
|
int main(int argc, char **argv) {
|
||||||
|
int animate_flag = 0;
|
||||||
// Function prototypes
|
int gui_flag = 0;
|
||||||
void flip_coin();
|
|
||||||
void generate_random_number(int lower, int upper);
|
// Parse command-line arguments
|
||||||
void coin_animation(int result);
|
for (int i = 1; i < argc; i++) {
|
||||||
void random_number_animation(int num);
|
if (strcmp(argv[i], "-A") == 0 || strcmp(argv[i], "--animation") == 0) {
|
||||||
void handle_exit();
|
animate_flag = 1;
|
||||||
|
} else if (strcmp(argv[i], "-G") == 0 || strcmp(argv[i], "--gui") == 0) {
|
||||||
int main() {
|
gui_flag = 1;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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