changed system dependant code, added unix availability
This commit is contained in:
parent
475639b711
commit
3e3238a389
|
@ -6,12 +6,33 @@
|
|||
* as published by Sam Hocevar. See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MSDOS) || defined(_WIN16)
|
||||
#define HAVE_CONIO_H 1
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
#define HAVE_WINDOWS_H 1
|
||||
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__) || \
|
||||
defined(__MACH__)
|
||||
#include <unistd.h>
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#include <termios.h>
|
||||
static struct termios old = { 0, 0, 0, 0, '\0', 0, 0, 0 };
|
||||
static struct termios new = { 0, 0, 0, 0, '\0', 0, 0, 0 };
|
||||
#define HAVE_ANSI_ESCAPE_CODE 1
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CONIO_H)
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WINDOWS_H)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define N 4
|
||||
typedef struct arr_t {
|
||||
int x; /* position on x-axis from left to right */
|
||||
|
@ -27,6 +48,12 @@ static int number = 0; /* highest number of current game */
|
|||
static int getindex(int *, int, int *) /*@*/;
|
||||
static int *arr2ptr(/*@returned@*/ int *, arr_t) /*@*/;
|
||||
static arr_t ptr2arr(int *, int *) /*@*/;
|
||||
/*@unused@*/ static int
|
||||
tty_break(void) /*@globals old, new@*/ /*@modifies new@*/;
|
||||
static int tty_getch(void) /*@*/;
|
||||
/*@unused@*/ static int tty_fix(void) /*@globals old*/ /*@modifies nothing@*/;
|
||||
static void tty_cls(void) /*@globals old, new@*/ /*@modifies new@*/;
|
||||
static void map_init(int *map) /*@modifies *map@*/;
|
||||
static void cpymap(int *dst, int *) /*@modifies *dst@*/;
|
||||
static void trans(int *map, int) /*@modifies *map@*/;
|
||||
static void prtwelcome(void) /*@globals fileSystem, hiscore, hinum@*/
|
||||
|
@ -83,7 +110,7 @@ getindex(int *arr, int arrsize, int *ptr) /*@*/
|
|||
* 'arr': arr to be converted
|
||||
*/
|
||||
static int * /* return pointer to given arr */
|
||||
arr2ptr(/*@returned@*/ int *start, arr_t arr) /*@modifies nothing@*/
|
||||
arr2ptr(/*@returned@*/ int *start, arr_t arr) /*@*/
|
||||
{
|
||||
return &start[arr.x + N * arr.y];
|
||||
}
|
||||
|
@ -94,7 +121,7 @@ arr2ptr(/*@returned@*/ int *start, arr_t arr) /*@modifies nothing@*/
|
|||
* 'ptr': pointer to be converted
|
||||
*/
|
||||
static arr_t /* return arr of given pointer */
|
||||
ptr2arr(int *start, int *ptr) /*@modifies nothing@*/
|
||||
ptr2arr(int *start, int *ptr) /*@*/
|
||||
{
|
||||
arr_t arr = { 0, 0 }; /* arr of given tile */
|
||||
int ptrindex =
|
||||
|
@ -105,6 +132,162 @@ ptr2arr(int *start, int *ptr) /*@modifies nothing@*/
|
|||
return arr;
|
||||
}
|
||||
|
||||
/*
|
||||
* changes terminal behavior to not wait for enter, not echo
|
||||
*/
|
||||
static int /* return 0 on success, -1 otherwise */
|
||||
tty_break(void) /*@globals new, old@*/ /*@modifies new@*/
|
||||
{
|
||||
#if defined(HAVE_CONIO_H)
|
||||
return 0;
|
||||
#elif defined(HAVE_WINDOWS_H)
|
||||
return 0;
|
||||
#elif defined(HAVE_TERMIOS_H)
|
||||
if (tcgetattr(0, &old) == -1) {
|
||||
return -1;
|
||||
}
|
||||
new = old;
|
||||
new.c_lflag &= ~ICANON;
|
||||
new.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(0, TCSANOW, &new) == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* get single character without waiting for enter or echoing
|
||||
* equivalent to getchar() if not supported by system
|
||||
*/
|
||||
static int /* return input character, EOF on failure */
|
||||
tty_getch(void) /*@globals old, new*/ /*@modifies new@*/
|
||||
{
|
||||
#if defined(HAVE_CONIO_H)
|
||||
return getch();
|
||||
#elif defined(HAVE_WINDOWS_H)
|
||||
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
INPUT_RECORD irInputRecord;
|
||||
DWORD dwEventsRead;
|
||||
CHAR cChar;
|
||||
|
||||
while (ReadConsoleInputA(hStdin, &irInputRecord, 1,
|
||||
&dwEventsRead)) /* Read key press */
|
||||
if (irInputRecord.EventType == KEY_EVENT &&
|
||||
irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_SHIFT &&
|
||||
irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_MENU &&
|
||||
irInputRecord.Event.KeyEvent.wVirtualKeyCode !=
|
||||
VK_CONTROL) {
|
||||
cChar = irInputRecord.Event.KeyEvent.uChar.AsciiChar;
|
||||
ReadConsoleInputA(
|
||||
hStdin, &irInputRecord, 1,
|
||||
&dwEventsRead); /* Read key release */
|
||||
return cChar;
|
||||
}
|
||||
return EOF;
|
||||
#elif defined(HAVE_TERMIOS_H)
|
||||
int ch;
|
||||
|
||||
if (tty_break() == -1) {
|
||||
return EOF;
|
||||
}
|
||||
ch = getchar();
|
||||
if (tty_fix() == -1) {
|
||||
return EOF;
|
||||
}
|
||||
return ch;
|
||||
#else
|
||||
return getchar();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* restore terminal behavior to original state
|
||||
*/
|
||||
static int /* return 0 on success, -1 otherwise */
|
||||
tty_fix(void) /*@globals old*/ /*@modifies nothing@*/
|
||||
{
|
||||
#if defined(HAVE_CONIO_H)
|
||||
return 0;
|
||||
#elif defined(HAVE_WINDOWS_H)
|
||||
return 0;
|
||||
#elif defined(HAVE_TERMIOS_H)
|
||||
return tcsetattr(0, TCSANOW, &old);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* clear terminal screen
|
||||
*/
|
||||
static void
|
||||
tty_cls(void) /*@globals fileSystem@*/ /*@modifies fileSystem@*/
|
||||
{
|
||||
#if defined(HAVE_CONIO_H)
|
||||
return clrscr();
|
||||
#elif defined(HAVE_WINDOWS_H)
|
||||
HANDLE hStdOut;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
DWORD count;
|
||||
DWORD cellCount;
|
||||
COORD homeCoords = { 0, 0 };
|
||||
|
||||
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hStdOut == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the number of cells in the current buffer */
|
||||
if (!GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
|
||||
return;
|
||||
}
|
||||
cellCount = csbi.dwSize.X * csbi.dwSize.Y;
|
||||
|
||||
/* Fill the entire buffer with spaces */
|
||||
if (!FillConsoleOutputCharacter(hStdOut, (TCHAR)' ', cellCount,
|
||||
homeCoords, &count)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill the entire buffer with the current colors and attributes */
|
||||
if (!FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, cellCount,
|
||||
homeCoords, &count)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move the cursor home */
|
||||
SetConsoleCursorPosition(hStdOut, homeCoords);
|
||||
#elif defined(HAVE_ANSI_ESCAPE_CODE)
|
||||
printf("\033[2J");
|
||||
printf("\033[%d;%dH", 1, 1);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* fill map with 0
|
||||
*/
|
||||
static void
|
||||
map_init(int *map) /*@modifies *map@*/
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
for (j = 0; j < N; j++) {
|
||||
arr_t tmparr = { 0, 0 }; /* temp arr */
|
||||
|
||||
tmparr.x = j;
|
||||
tmparr.y = i;
|
||||
*arr2ptr(map, tmparr) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* copy source map to destination map
|
||||
* 'dst': pointer to first element of destination map
|
||||
|
@ -142,7 +325,7 @@ trans(int *map, int times) /*@modifies *map@*/
|
|||
if (times == 0) {
|
||||
return;
|
||||
}
|
||||
memset(ptrtmp, 0, sizeof(tmp));
|
||||
map_init(ptrtmp);
|
||||
for (i = 0; i < N; i++) {
|
||||
for (j = 0; j < N; j++) {
|
||||
arr_t maparr = ptr2arr(map, curmap); /* current arr of
|
||||
|
@ -573,7 +756,7 @@ turn(int *map) /*@globals internalState, fileSystem, score@*/
|
|||
/*@modifies internalState, fileSystem, score, *map@*/
|
||||
{
|
||||
int haschanged = 0; /* 1 if change is made, 0 otherwise */
|
||||
char input = (char)getch(); /* input character */
|
||||
char input = (char)tty_getch(); /* input character */
|
||||
enum ctrl tmp = input_to_ctrl(input); /* ctrl enum */
|
||||
int times = 0; /* rotation time */
|
||||
|
||||
|
@ -590,7 +773,7 @@ turn(int *map) /*@globals internalState, fileSystem, score@*/
|
|||
if (haschanged == 0) {
|
||||
return 0;
|
||||
}
|
||||
(void)system("cls");
|
||||
tty_cls();
|
||||
(void)genrnd(map);
|
||||
prt(map);
|
||||
return 0;
|
||||
|
@ -608,7 +791,7 @@ game(int *map) /*@globals internalState, fileSystem, score@*/
|
|||
|
||||
(void)genrnd(map);
|
||||
(void)genrnd(map);
|
||||
(void)system("cls");
|
||||
tty_cls();
|
||||
prt(map);
|
||||
while (end == 0 && is_over(map) == 0) {
|
||||
end = turn(map);
|
||||
|
@ -644,17 +827,18 @@ main(void)
|
|||
int map[N][N] = { { 0 } }; /* map of tiles */
|
||||
int *ptrmap = &map[0][0]; /* pointer to first element of map */
|
||||
|
||||
memset(ptrmap, 0, sizeof(map));
|
||||
map_init(ptrmap);
|
||||
srand((unsigned int)time(NULL));
|
||||
do {
|
||||
memset(ptrmap, 0, sizeof(map));
|
||||
(void)system("cls");
|
||||
map_init(ptrmap);
|
||||
tty_cls();
|
||||
prtwelcome();
|
||||
if ((char)getch() != ' ') {
|
||||
if ((char)tty_getch() != ' ') {
|
||||
break;
|
||||
}
|
||||
game(ptrmap);
|
||||
gg(ptrmap);
|
||||
} while ((char)getch() == ' ');
|
||||
} while ((char)tty_getch() == ' ');
|
||||
tty_cls();
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue