changed system dependant code, added unix availability

This commit is contained in:
afrangry 2023-05-20 15:50:20 +08:00
parent 475639b711
commit 3e3238a389
1 changed files with 196 additions and 12 deletions

208
2048.c Normal file → Executable file
View File

@ -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;
}