⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 puzzle.c

📁 linux下的一个拼图程序的源代码 使用curses库函数
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <ncurses.h>

#define STARTX 9
#define STARTY 3
#define WIDTH  6
#define HEIGHT 4

#define BLANK 0

typedef struct _tile {
	int x;
	int y;
}tile;

void init_board(int **board, int n, tile *blank);
void board(WINDOW *win, int starty, int startx, int lines, int cols, 
	   int tile_width, int tile_height);
void shuffle_board(int **board, int n);
void move_blank(int direction, int **s_board, int n, tile *blank);
int check_win(int **s_board, int n, tile *blank);


enum { LEFT, RIGHT, UP, DOWN };
int count = 0;

int main(int argc, char *argv[])
{	int **s_board;
	int n, i, ch;
	tile blank;

	if(argc != 2)
	{	printf("Please input the lines you want.\n");
		exit(1);
	}
	n = atoi(argv[1]);
	
	s_board = (int **)calloc(n, sizeof(int *));
	for(i = 0;i < n; ++i)
		s_board[i] = (int *)calloc(n, sizeof(int));
	init_board(s_board, n, &blank);
	initscr();
	start_color();
	use_default_colors();
	init_color(COLOR_WHITE,1000,1000,1000);
	init_pair(1,COLOR_BLUE,COLOR_WHITE);
	init_pair(2,COLOR_MAGENTA,COLOR_WHITE);
	keypad(stdscr, TRUE);
	curs_set(0);
	cbreak();
	shuffle_board(s_board, n);
	while(1)
	{	ch = getch();
		switch(ch)
		{	case KEY_LEFT:
				move_blank(RIGHT, s_board, n, &blank);
				break;
			case KEY_RIGHT:
				move_blank(LEFT, s_board, n, &blank);
				break;
			case KEY_UP:
				move_blank(DOWN, s_board, n, &blank);
				break;
			case KEY_DOWN:
				move_blank(UP, s_board, n, &blank);
				break;
			case 'q':
			case 'Q':
				endwin();
				return 0;
		}
		shuffle_board(s_board, n);
		if(check_win(s_board, n, &blank) == TRUE)
		{	
			erase();
			mvprintw(12, 30, "Congratulations !\n");
			mvprintw(13, 30, "You finished this in just %d steps.\n",count);
			refresh();
			alarm(5);
			pause();
			break;
		}
	}
	endwin();
	return 0;	
}

void move_blank(int direction, int **s_board, int n, tile *blank)
{	int temp;

	switch(direction)
	{	case LEFT:
		{	if(blank->x != 0)
			{	--blank->x;
				temp = s_board[blank->x][blank->y];
				s_board[blank->x + 1][blank->y] = temp;
				s_board[blank->x][blank->y] = BLANK;
				count++;
			}
		}
		break;
		case RIGHT:
		{	if(blank->x != n - 1)
			{	++blank->x;
				temp = s_board[blank->x][blank->y];
				s_board[blank->x - 1][blank->y] = temp;
				s_board[blank->x][blank->y] = BLANK;
				count++;
			}
		}
		break;
		case UP:
		{	if(blank->y != 0)
			{	--blank->y;
				temp = s_board[blank->x][blank->y];
				s_board[blank->x][blank->y + 1] = temp;
				s_board[blank->x][blank->y] = BLANK;
				count++;
			}
		}
		break;
		case DOWN:
		{	if(blank->y != n - 1)
			{	++blank->y;
				temp = s_board[blank->x][blank->y];
				s_board[blank->x][blank->y - 1] = temp;
				s_board[blank->x][blank->y] = BLANK;
				count++;
			}
		}
		break;			
	}
}

int check_win(int **s_board, int n, tile *blank)
{	int i, j;

	s_board[blank->x][blank->y] = n * n;
	for(i = 0;i < n; ++i)
		for(j = 0;j < n; ++j)
			if(s_board[i][j] != j * n + i + 1)
			{	s_board[blank->x][blank->y] = BLANK;
				return FALSE;
			}
	
	s_board[blank->x][blank->y] = BLANK;
	return TRUE;	
}

void init_board(int **s_board, int n, tile *blank)
{	int i, j, k;
	int *temp_board;

	temp_board = (int *)calloc(n * n, sizeof(int));
	srand(time(NULL));
	for(i = 0;i < n * n; ++i)
	{    
repeat :
		k = rand() % (n * n);
		for(j = 0;j <= i - 1; ++j)
			if (k == temp_board[j])
				goto repeat;
			else
				temp_board[i] = k;
	}
	k = 0;
	for (i = 0;i < n;++i)
		for(j = 0;j < n; ++j,++k)
		{	if(temp_board[k] == 0)
			{	blank->x = i;
				blank->y = j;
			}
			s_board[i][j] = temp_board[k];
		}
	free(temp_board);
}

void board(WINDOW *win, int starty, int startx, int lines, int cols, 
	   int tile_width, int tile_height)
{	int endy, endx, i, j;
	
	endy = starty + lines * tile_height;
	endx = startx + cols  * tile_width;
	
	for(j = starty; j <= endy; j += tile_height)
		for(i = startx; i <= endx; ++i)
			mvwaddch(win, j, i, ACS_HLINE);
	for(i = startx; i <= endx; i += tile_width)
		for(j = starty; j <= endy; ++j)
			mvwaddch(win, j, i, ACS_VLINE);
	mvwaddch(win, starty, startx, ACS_ULCORNER);
	mvwaddch(win, endy, startx, ACS_LLCORNER);
	mvwaddch(win, starty, endx, ACS_URCORNER);
	mvwaddch(win, 	endy, endx, ACS_LRCORNER);
	for(j = starty + tile_height; j <= endy - tile_height; j += tile_height)
	{	mvwaddch(win, j, startx, ACS_LTEE);
		mvwaddch(win, j, endx, ACS_RTEE);	
		for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
			mvwaddch(win, j, i, ACS_PLUS);
	}
	for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
	{	mvwaddch(win, starty, i, ACS_TTEE);
		mvwaddch(win, endy, i, ACS_BTEE);
	}
	attrset(A_NORMAL);
	wrefresh(win);
}

void shuffle_board(int **s_board, int n)
{	int i,j, deltax, deltay;
	int startx, starty;

	starty = (LINES - n * HEIGHT) / 2;
	startx = (COLS  - n * WIDTH) / 2;
	clear();
	attrset(COLOR_PAIR(1));
	mvprintw(23, 0, "Press Q to Exit");
	mvprintw(0, 30, "** Jigsaw Puzzle **");
	mvprintw(22, 0, "steps moved : %d",count);
	attrset(A_NORMAL);
	attrset(COLOR_PAIR(2));
	board(stdscr, starty, startx, n, n, WIDTH, HEIGHT);
	attrset(A_NORMAL);
	deltay = HEIGHT / 2;
	deltax = WIDTH  / 2;
	for(j = 0; j < n; ++j)
		for(i = 0;i < n; ++i)
			if(s_board[i][j] != BLANK)
				mvprintw(starty + j * HEIGHT + deltay,
					 startx + i * WIDTH  + deltax,
					 "%-2d", s_board[i][j]);
	refresh();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -