From: Laurent Mazet Date: Fri, 28 Feb 2025 09:07:54 +0000 (+0100) Subject: initial commit X-Git-Url: https://secure.softndesign.org/git/?a=commitdiff_plain;h=242cae72b68930bb2a4ee3be166cbeb7e1fac51f;p=sudoku.git initial commit --- 242cae72b68930bb2a4ee3be166cbeb7e1fac51f diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68f55a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.d +*.exe +*.gcda +*.gcno +*.gcov +*.ld +*.o +*.log diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..b9eba44 --- /dev/null +++ b/debug.c @@ -0,0 +1,5 @@ +#include "debug.h" + +int verbose = 0; + +/* vim: set ts=4 sw=4 et: */ diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..32dc0ca --- /dev/null +++ b/debug.h @@ -0,0 +1,21 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +/* constants */ + +#define DEBUG 3 +#define INFO 2 +#define WARNING 1 +#define ERROR 0 + +/* macros */ + +#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0) + +/* gobal variables */ + +extern int verbose; + +#endif /* __DEBUG_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.c b/display.c new file mode 100644 index 0000000..39c94b5 --- /dev/null +++ b/display.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include + +#include "debug.h" +#include "function.h" + +#include "display.h" + +typedef enum { + white = 1, + red, + green, + blue, + cyan, + magenta, + yellow, + ired, + igreen, + iblue, + icyan, + imagenta, + iyellow, + bred, + bgreen, + bblue, + bcyan, + bmagenta, + byellow, + black, + wred, + wgreen, + wblue, + wcyan, + wmagenta, + wyellow, +} color_t; + +void set_color (color_t color) +{ + static int init = 1; + + if (init) { + init_pair (white, COLOR_WHITE, COLOR_BLACK); + init_pair (red, COLOR_RED, COLOR_BLACK); + init_pair (green, COLOR_GREEN, COLOR_BLACK); + init_pair (blue, COLOR_BLUE, COLOR_BLACK); + init_pair (magenta, COLOR_MAGENTA, COLOR_BLACK); + init_pair (yellow, COLOR_YELLOW, COLOR_BLACK); + init_pair (cyan, COLOR_CYAN, COLOR_BLACK); + init_pair (ired, COLOR_RED, COLOR_WHITE); + init_pair (igreen, COLOR_GREEN, COLOR_WHITE); + init_pair (iblue, COLOR_BLUE, COLOR_WHITE); + init_pair (imagenta, COLOR_MAGENTA, COLOR_WHITE); + init_pair (iyellow, COLOR_YELLOW, COLOR_WHITE); + init_pair (icyan, COLOR_CYAN, COLOR_WHITE); + init_pair (bred, COLOR_BLACK, COLOR_RED); + init_pair (bgreen, COLOR_BLACK, COLOR_GREEN); + init_pair (bblue, COLOR_BLACK, COLOR_BLUE); + init_pair (bmagenta, COLOR_BLACK, COLOR_MAGENTA); + init_pair (byellow, COLOR_BLACK, COLOR_YELLOW); + init_pair (bcyan, COLOR_BLACK, COLOR_CYAN); + init_pair (black, COLOR_BLACK, COLOR_WHITE); + init_pair (wred, COLOR_WHITE, COLOR_RED); + init_pair (wgreen, COLOR_WHITE, COLOR_GREEN); + init_pair (wblue, COLOR_WHITE, COLOR_BLUE); + init_pair (wcyan, COLOR_WHITE, COLOR_CYAN); + init_pair (wmagenta, COLOR_WHITE, COLOR_MAGENTA); + init_pair (wyellow, COLOR_WHITE, COLOR_YELLOW); + init = 0; + } + + attrset (COLOR_PAIR(color)); +} + +int _helpwindow (char *msg, int xoffset, int yoffset, int length) +{ + int i = 0; + int j = 0; + while ((msg) && (*msg != '\0')) { + if (*msg == '\n') { + if (i <= length) { + mvaddch (yoffset + j, xoffset + i, ' '); + i++; + continue; + } + i = 0; + j++; + } + if (*msg != '\n') { + mvaddch (yoffset + j, xoffset + i, *msg); + i++; + } + msg++; + } + return j; +} + +void _displaytitle (char *title, int xoffset, int yoffset, int length) +{ + int i; + for (i = 0; i < length; i++) { + mvaddch (yoffset, xoffset + i, ' '); + mvaddch (yoffset + 1, xoffset + i, ACS_HLINE); + } + for (i = 0; title[i] != '\0'; i++) { + mvaddch (yoffset, xoffset + i + (length - strlen (title)) / 2, title[i]); + } +} + +void _dobound (int xsize, int ysize, int xoffset, int yoffset) +{ + int i, j; + + for (i = 0; i < xsize; i++) { + mvaddch (yoffset - 1, xoffset + i, ACS_HLINE); + mvaddch (yoffset + ysize, xoffset + i, ACS_HLINE); + } + for (j = 0; j < ysize; j++) { + mvaddch (yoffset + j, xoffset - 1, ACS_VLINE); + mvaddch (yoffset + j, xoffset + xsize, ACS_VLINE); + } + mvaddch (yoffset - 1, xoffset - 1, ACS_ULCORNER); + mvaddch (yoffset + ysize, xoffset - 1, ACS_LLCORNER); + mvaddch (yoffset - 1, xoffset + xsize, ACS_URCORNER); + mvaddch (yoffset + ysize, xoffset + xsize, ACS_LRCORNER); +} + +int helpwindow (char *msg, int xoffset, int yoffset) +{ + char *title = "Help message"; + int length = strmaxlen (msg, '\n'); + if (length < (int)strlen (title)) { + length = strlen (title); + } + set_color (byellow); + _displaytitle (title, xoffset, yoffset, length); + int j = 2; + j += _helpwindow (msg, xoffset, yoffset + j, length); + _dobound (length, j, xoffset, yoffset); + set_color (white); + + while (getch () == ERR) { + usleep (200 * 1000); + } + + return j; +} + +void displayboard (board_t *board, int xoffset, int yoffset) +{ + int i, j; + + _dobound (board->nb + 2, board->nb + 2, xoffset - 1, yoffset - 1); + for (i = 0; i < board->nb; i++) { + for (j= 0; j < board->nb; j++) { + mvaddch (j + yoffset, i + xoffset, getvalue (board, i, j)); + } + } +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.h b/display.h new file mode 100644 index 0000000..031fa04 --- /dev/null +++ b/display.h @@ -0,0 +1,15 @@ +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include "type.h" + +int helpwindow (char *msg, int xoffset, int yoffset); + +void displayboard (board_t *board, int xoffset, int yoffset); + +#define KEY_DELETE 0x014a +#define KEY_ESC 0x1b + +#endif /* __DISPLAY_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.c b/function.c new file mode 100644 index 0000000..70b2ecf --- /dev/null +++ b/function.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include + +#include "debug.h" +#include "type.h" + +#include "function.h" + +int strmaxlen (char *str, char ch) +{ + int len = 0; + char *end = NULL; + while ((end = strchr (str, ch)) != NULL) { + int l = (int)(end - str); + if (l > len) { + len = l; + } + str = end + 1; + } + return len; +} + +board_t *initboard (int length) +{ + board_t *board = (board_t *) malloc (sizeof (board_t)); + CHECKALLOC (board); + board->length = length; + int nb = board->nb = length * length; + board->tab = (char *) calloc (1, nb * nb + 1); + CHECKALLOC (board->tab); + memset (board->tab, ' ', nb * nb); + return board; +} + +char _itoh (int x) +{ + char h = '0'; + if ((x > 0) && (x <= 10 + 'Z' - 'A')) { + h = x + ((x > 9) ? 'A' - 10 : '0'); + } + return h; +} + +board_t *initplay (board_t *board) +{ + int i, j, k; + + for (i = 0; i < board->nb; i++) { + for (j = 0; j < board->nb; j++) { + int draw = 1; + while (draw) { + + char tile = _itoh (1 + (rand () / board->nb) / (((RAND_MAX / board->nb) + board->nb) / board->nb)); + VERBOSE (DEBUG, printf ("tile drawn '%c'\n", tile)); + draw = 0; + + /* check line */ + VERBOSE (DEBUG, printf ("check line\n")); + for (k = 0; (k < j) && (!draw); k++) { + if (getvalue (board, i, k) == tile) { + draw = 1; + } + } + + /* check column */ + VERBOSE (DEBUG, printf ("check column\n")); + for (k = 0; (k < i) && (!draw); k++) { + if (getvalue (board, k, j) == tile) { + draw = 1; + } + } + + /* check box */ + VERBOSE (DEBUG, printf ("check box\n")); + for (k = 0; (k < board->nb) && (!draw); k++) { + int I = board->length * (i / board->length); + int J = board->length * (j / board->length); + if (getvalue (board, I + k / board->length, J + k % board->length) == tile) { + draw = 1; + } + } + + if (!draw) { + VERBOSE (INFO, printf ("(%d, %d) = %c\n", i, j, tile)); + *getcell (board, i, j) = tile; + } + } + } + } + + return board; +} + +void freeboard (board_t *board) +{ + if (board) { + free (board->tab); + } + free (board); +} + +int _makecomments (char *buffer, board_t *board) +{ + int i, j, l = 0; + for (j = 0; j < board->nb; j++) { + l += sprintf (buffer + l, "rem: \""); + for (i = 0; i < board->nb; i++) { + l += sprintf (buffer + l, "%c", getvalue (board, i, j)); + } + l += sprintf (buffer + l, "\"\n"); + } + return l; +} + +char *saveboard (board_t *board) +{ + int size = 2 * (8 + 3) + 8 + board->nb * board->nb + 1; + + char *buffer = (char *) calloc (size, 1); + CHECKALLOC (buffer); + + int l = sprintf (buffer, "length: %d\n", board->length); + l += sprintf (buffer + l, "nb: %d\n", board->nb); + + VERBOSE (INFO, _makecomments (buffer + l, board)); + + return buffer; +} + +int writedata (char *filename, char *data) +{ + int ret = 0; + + FILE *fd = fopen (filename, "w"); + if (fd) { + size_t n = fwrite (data, strlen (data), 1, fd); + fclose (fd); + ret = (n == strlen (data)); + } else { + VERBOSE (WARNING, printf ("can't write file (%s)\n", filename)); + } + + return ret; +} + +char *readdata (char *filename) +{ + char *buffer = NULL; + FILE *fd = fopen (filename, "r"); + if (fd) { + fseek (fd, 0, SEEK_END); + int size = ftell (fd); + buffer = (char *) calloc (size + 1, 1); + CHECKALLOC (buffer); + + fseek (fd, 0, SEEK_SET); + int nb = fread (buffer, 1, size, fd); + if (nb != size) { + VERBOSE (WARNING, printf ("can't fully read file (%s)\n", filename)); + } + fclose (fd); + } + + return buffer; +} + +char *atos (char *str) +{ + char *ret = NULL; + + if (*str == '"') { + char *ptr = ++str; + while ((*ptr != '"') && (*ptr != '\0')) { + ptr++; + } + if (*ptr == '"') { + *ptr = '\0'; + ret = str; + } + } + + return ret; +} + +board_t *loadboard (char *str) +{ + int length = 0; + int nb = 0; + char *tab = NULL; + + char *saveptr1, *saveptr2; + + char *line = strtok_r (str, "\n", &saveptr1); + while (line) { + + char *keyword = strtok_r (line, ":", &saveptr2); + + char *value = line + strlen (keyword) + 1; + while (*value == ' ') { + value++; + } + + if (strcmp (keyword, "length") == 0) { + length = atoi (value); + } else if (strcmp (keyword, "nb") == 0) { + nb = atoi (value); + } else if (strcmp (keyword, "rem") == 0) { + /* nothing to do with remark */ + } else { + VERBOSE (WARNING, printf ("unknown keyword: %s\n", keyword)); + } + + line = strtok_r (NULL, "\n", &saveptr1); + } + + board_t *board = NULL; + if ((tab) && (nb == length * length) && (strlen (tab) == (size_t)(nb * nb))) { + board = initboard (length); + memcpy (board->tab, tab, nb * nb); + } + + return board; +} + +char *getcell (board_t *board, int x, int y) +{ + return board->tab + x + board->nb * y; +} + +char getvalue (board_t *board, int x, int y) +{ + VERBOSE (DEBUG, printf ("(%d, %d) => '%c'\n", x, y, *getcell (board, x, y))); + return (x >= 0) && (x < board->nb) && (y >= 0) && (y < board->nb) ? *getcell (board, x, y) : 0; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.h b/function.h new file mode 100644 index 0000000..4d6b84d --- /dev/null +++ b/function.h @@ -0,0 +1,44 @@ +#ifndef __FUNCTION_H__ +#define __FUNCTION_H__ + +#include + +#include "type.h" + +#define CHECKALLOC(ptr) \ + do { \ + if ((ptr) == NULL) { \ + VERBOSE (ERROR, fprintf (stderr, "can't get enough memory for '%s'\n", #ptr)); \ + exit (1); \ + } \ + } while (0) + +#define max(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) + +#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) + +int strmaxlen (char *str, char ch); + +board_t *initboard (int length); + +board_t *initplay (board_t *board); + +void freeboard (board_t *board); + +char *saveboard (board_t *board); + +int writedata (char *filename, char *data); + +char *readdata (char *filename); + +char *atos (char *str); + +board_t *loadboard (char *str); + +char *getcell (board_t *board, int x, int y); + +char getvalue (board_t *board, int x, int y); + +#endif /* __FUNCTION_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/makefile b/makefile new file mode 100644 index 0000000..8abae4b --- /dev/null +++ b/makefile @@ -0,0 +1,193 @@ +# Default flags + +CC = gcc + +#INCLUDES = -I../debug -D__MEMORY_ALLOCATION__ +INCLUDES = +OFLAGS = -O4 -Os +#OFLAGS = -O4 -ffast-math -finline-functions +#OFLAGS = -O4 -finline-functions +#OFLAGS += -mtune=pentium3 -mmmx -msse -msse2 -m3dnow +#OFLAGS += -minline-all-stringops -fsingle-precision-constant +#OFLAGS += -malign-double +CFLAGS += -W -Wall -Wextra -g +#CFLAGS += -std=c99 -D_XOPEN_SOURCE=500 +CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS) +LDFLAGS += -g $(LDOPTS) $(OPTIONS) + +LDOPT = linker +MV = mv +ifneq (, $(findstring linux, $(MAKE_HOST))) +# Linux +else ifneq (, $(findstring mingw, $(MAKE_HOST))) +# Windows MinGw +CFLAGS += -DWIN32 +#LDLIBS += -lws2_32 +LDOPT = winlnk +else ifneq (, $(findstring cygwin, $(MAKE_HOST))) +CFLAGS += -DWIN32 +# Windows CygWin +LDOPT = winlnk +else ifneq (, $(findstring msdos, $(MAKE_HOST))) +# MSDOS +LDOPT = doslnk +MV = move +endif + +# Targets + +ALLEXE = +ALLEXE += sudoku + +SHELL = bash + +#MAKE = mingw32-make +MAKEFLAGS += -s +include $(wildcard .makefile) + +# Functions + +TITLE = echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t" +PASS = echo -e "\033[1;32m$(strip $(1))\033[0;0m" +WARN = echo -e "\033[1;33m$(strip $(1))\033[0;0m" +FAIL = echo -e "\033[1;31m$(strip $(1))\033[0;0m" + +MKDIR = mkdir -p $(1) && chmod a+rx,go-w $(1) + +INSTALL = test -d `dirname $(2)` || $(call MKDIR, `dirname $(2)`) && cp -pa $(1) $(2) && chmod a+rX,go-w $(2) + +VALID = $(call TITLE, $(1)) && $(2) && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; } + +GETCOMMENTS = awk '/\/\*\s*$(1):/,/\*\// { sub(/.*\/\*\s*$(1):/, ""); sub (/\s*\*\/.*/, ""); print } /\/\/\s*$(1):/ {sub (/.*\/\/\s*$(1):/, ""); print }' $(2) +#GETCOMMENTS = perl -- getcomments.pl -p='$(1):\s' -f='%' $(2) + +## Generic rules + +all: depends + $(MAKE) $(ALLEXE:%=%.exe) + +count: + wc $(wildcard *.c *.h) $(MAKEFILE_LIST) + +clean: + $(call TITLE, "Cleaning") + touch clean + rm -f clean $(wildcard *.d *.ld *.log *.o *.test *~ .exec_* gmon.out _) + $(call PASS, SUCCESS) + +depends: $(patsubst %.c, %.d, $(wildcard *.c)) $(patsubst %, %.ld, $(ALLEXE)) + +gcovs: + $(MAKE) $(addprefix gcov_,$(ALLEXE)) + +gprofs: + $(MAKE) $(addprefix gprof_,$(ALLEXE)) + +purge: clean + $(call TITLE, "Purging") + touch purge + rm -f purge $(ALLEXE:%=%.exe) + $(call PASS, SUCCESS) + +valgrinds: + $(MAKE) all + $(MAKE) $(addprefix valgrind_,$(ALLEXE)) + +wipe: purge + $(call TITLE, "Wiping") + touch wipe + rm -f wipe $(wildcard *.gcda *.gcno *.gcov *.glog) + $(call PASS, SUCCESS) + +tests: + -rm -f $(ALLEXE) + $(MAKE) all + $(MAKE) $(addprefix test_,$(ALLEXE)) + +## Main rules + +include $(wildcard *.d) +include $(wildcard *.ld) + +gcov_%: + $(MAKE) purge + $(MAKE) depends + OPTIONS="-coverage -O0" $(MAKE) ${@:gcov_%=%}.exe + $(MAKE) test_$(@:gcov_%=%) + gcov `sed -e 's/\.exe:/.c/;s/\.o/.c/g' $(@:gcov_%=%.ld)` + touch gcov + rm -f gcov $(wildcard *.gcda *.gcno) + $(MAKE) purge + grep '^ *#####' *.c.gcov || true + +gprof_%: + $(MAKE) purge + $(MAKE) depends + OPTIONS="-pg" $(MAKE) ${@:gprof_%=%}.exe + $(MAKE) ${@:gprof_%=%}.test + IFS=$$'\n'; id=1; \ + for test in `cat ${@:gprof_%=%}.test | sed 's,${@:gprof_%=%}.exe,./${@:gprof_%=%}.exe,g'`; do \ + log=${@:gprof_%=%}.prof-$$id.glog; \ + $(call TITLE, test: $$test); \ + echo $$test > $$log; \ + eval $$test >> $$log; \ + [ $$? -eq 0 ] \ + && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || echo -e "\033[1;31mFAILED\033[0;0m"; \ + [ -f gmon.out ] && { gprof ${@:gprof_%=%}.exe gmon.out >> $$log; rm gmon.out; }; \ + let id++; \ + done; + $(MAKE) purge + +%.test: %.c + $(call TITLE, "Building $@") + $(call GETCOMMENTS,test, $<) > $@ + $(call PASS, SUCCESS) + -rm -f _ + +test_%: %.test %.exe + IFS=$$'\n'; RC=0; \ + for test in `cat $< | sed 's,${<:.test=.exe},$(VALGRIND) ./${<:.test=.exe},g'`; do \ + echo "=== $$test ==="; \ + eval $$test; \ + [ $$? -eq 0 ] && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || { echo -e "\033[1;31mFAILED\033[0;0m"; RC=1; }; \ + test "$$RC" = 1 -a "$(STOP)" = 1 && break; \ + done; \ + test "$$RC" -ne 1 + +valgrind_%: %.exe + VALGRIND="valgrind -v --leak-check=full --log-fd=3"; \ + export VALGRIND; \ + $(MAKE) $(@:valgrind_%=test_%) 3>$@.log + +%.d: %.c + $(call TITLE, "Building $@") + $(CC) $(INCLUDES) -MM $< -o $@~ + echo ${<:.c=.o}: $(shell $(call GETCOMMENTS,depends, $<)) >> $@~ + $(MV) $@~ $@ + $(call PASS, SUCCESS) + +%.ld: %.c + $(call TITLE, "Building $@") + echo ${<:.c=.exe}: $(shell $(call GETCOMMENTS,$(LDOPT), $<) | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') > $@ + $(call PASS, SUCCESS) + +%.o: %.c + $(call TITLE, "Building $@") + $(CC) $(CFLAGS) $(INCLUDES) $(shell $(call GETCOMMENTS,cflags, $<)) -c $< -o $@ + $(call PASS, SUCCESS) + + +%.exe: %.o %.d + $(call TITLE, "Building $@") + $(CC) $(LDFLAGS) $< $(shell $(call GETCOMMENTS,$(LDOPT), ${<:.o=.c})) $(LDLIBS) -o $@ + $(call PASS, SUCCESS) + +## Phony + +.PHONY: all clean count depends gcovs purge tests + +## Precious + +.PRECIOUS: %.d %.o diff --git a/sudoku.c b/sudoku.c new file mode 100644 index 0000000..3068bb6 --- /dev/null +++ b/sudoku.c @@ -0,0 +1,142 @@ +/* depend: */ +/* cflags: */ +/* linker: debug.o display.o function.o -lcurses */ +/* doslnk: debug.o display.o function.o -lpdc~1 */ +/* winlnk: debug.o display.o function.o -lpdcurses */ + +#include +#include +#include +#include + +#include "debug.h" +#include "display.h" +#include "function.h" +#include "type.h" + +/* global constants */ + +/* static variables */ +char *progname = NULL; +char *version = "0.1"; + +int length = 3; +int xoffset = 1; +int yoffset = 1; + +char *help = + " Move up\n" + " Move left\n" + " Move down\n" + " Move right\n" + " Quit\n" + ; + +int usage (int ret) +{ + FILE *fd = ret ? stderr : stdout; + fprintf (fd, "usage: %s [-h] [-l length] [-v level]\n", progname); + fprintf (fd, " -h: help message\n"); + fprintf (fd, " -l: box length (%d)\n", length); + fprintf (fd, " -v: verbose level (%d)\n", verbose); + fprintf (fd, "%s version %s\n", progname, version); + + return ret; +} + +/* main function */ +int main (int argc, char *argv[]) +{ + + /* get basename */ + char *pt = progname = argv[0]; + while (*pt) { + if ((*pt == '/') || (*pt == '\\')) { + progname = pt + 1; + } + pt++; + } + + /* process argument */ + while (argc-- > 1) { + char *arg = *(++argv); + if (arg[0] != '-') { + VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, arg)); + return usage (1); + } + char c = arg[1]; + switch (c) { + case 'l': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: no length specified\n", progname)); + return usage (1); + } + length = atoi (arg); + break; + case 'v': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname)); + return usage (1); + } + verbose = atoi (arg); + break; + case 'h': + default: + return usage (c != 'h'); + } + } + + /* init board */ + board_t *board = initboard (length); + initplay (board); + + /* init curses */ + initscr (); + noecho (); + cbreak (); + nonl (); + keypad (stdscr, TRUE); + curs_set (0); + + /* event loop */ + int stop = 0; + while (!stop) { + + displayboard (board, xoffset, yoffset); + + int ch = getch (); + switch (ch) { + case KEY_UP: + case 'i': + break; + case KEY_LEFT: + case 'j': + break; + case KEY_DOWN: + case 'k': + break; + case KEY_RIGHT: + case 'l': + break; + case 'q': + stop = 1; + break; + } + } + + endwin (); + + freeboard (board); + + return 0; +} + +/* test: sudoku.exe -h | grep usage */ +/* test: sudoku.exe -l 2>&1 | grep length */ +/* test: sudoku.exe -v 2>&1 | grep missing */ +/* test: sudoku.exe _ 2>&1 | grep invalid */ + +/* test: { sleep 10; echo q; } | sudoku.exe */ + diff --git a/type.h b/type.h new file mode 100644 index 0000000..f7731ae --- /dev/null +++ b/type.h @@ -0,0 +1,12 @@ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +typedef struct { + int length; + int nb; + char *tab; +} board_t; + +#endif /* __TYPE_H__ */ + +/* vim: set ts=4 sw=4 et: */