C 语言小游戏 - 独立钻石棋

#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <signal.h>

#define SIZE 9

typedef struct {
	int8_t x,y;
} position_s;

typedef struct {
	int8_t size;
	int8_t field[SIZE][SIZE];
	position_s cursor;
	position_s win;
	bool selected;
} board_s;

void drawBoard(board_s *board) {
	int8_t x,y,count=0;

	// move cursor to home position
	printf("\033[H");

	for (y=0;y<(*board).size;y++) {
		for (x=0;x<(*board).size;x++) {
			count+=(*board).field[x][y]=='o';
		}
	}
	printf("peg-solitaire.c %7d pegs\n",count);
	printf("\n");

	for (y=0;y<(*board).size;y++) {
		for (x=0;x<14-(*board).size;x++) {
			printf(" ");
		}
		for (x=0;x<(*board).size;x++) {
			if ((*board).cursor.x == x && (*board).cursor.y == y) {
				if ((*board).selected) {
					printf("\b|\033[7m%c\033[27m|",(*board).field[x][y]);
				} else {
					printf("\033[7m%c\033[27m ",(*board).field[x][y]);
				}
			} else {
				printf("%c ",(*board).field[x][y]);
			}
		}
		for (x=0;x<14-(*board).size;x++) {
			printf(" ");
		}
		printf("\n");
	}
	printf("                            \n");
	printf("   W,A,S,D, q or enter   \n");
	printf("\033[A"); // one line up
}

void rotateBoard(board_s *board) {
	int8_t i,j,n=(*board).size;
	int8_t tmp;
	for (i=0; i<n/2; i++){
		for (j=i; j<n-i-1; j++){
			tmp = (*board).field[i][j];
			(*board).field[i][j] = (*board).field[j][n-i-1];
			(*board).field[j][n-i-1] = (*board).field[n-i-1][n-j-1];
			(*board).field[n-i-1][n-j-1] = (*board).field[n-j-1][i];
			(*board).field[n-j-1][i] = tmp;
		}
	}
	i = (*board).cursor.x;
	j = (*board).cursor.y;

	(*board).cursor.x = -(j-n/2)+n/2;
	(*board).cursor.y = (i-n/2)+n/2;
}

bool selectk(board_s *board) {
	int8_t x,y,(*field)[SIZE];
	bool selected;

	x = (*board).cursor.x;
	y = (*board).cursor.y;
	field = (*board).field;
	selected = (*board).selected;

	if (field[x][y]!='o') return false;
	(*board).selected = !selected;
	return true;
}

bool moveUp(board_s *board) {
	int8_t x,y,(*field)[SIZE];
	bool selected;

	x = (*board).cursor.x;
	y = (*board).cursor.y;
	field = (*board).field;
	selected = (*board).selected;

	if (selected) {
		if (y<2) return false;
		if (field[x][y-2]!='.') return false;
		if (field[x][y-1]!='o') return false;
		if (field[x][y-0]!='o') return false;
		field[x][y-2] = 'o';
		field[x][y-1] = '.';
		field[x][y-0] = '.';
		(*board).cursor.y = y-2;
		(*board).selected = false;
	} else {
		if (y<1) return false;
		if (field[x][y-1]==' ') return false;
		(*board).cursor.y = y-1;
	}
	return true;
}

bool moveLeft(board_s *board) {
	bool success;
	rotateBoard(board);
	success = moveUp(board);
	rotateBoard(board);
	rotateBoard(board);
	rotateBoard(board);
	return success;
}

bool moveDown(board_s *board) {
	bool success;
	rotateBoard(board);
	rotateBoard(board);
	success = moveUp(board);
	rotateBoard(board);
	rotateBoard(board);
	return success;
}

bool moveRight(board_s *board) {
	bool success;
	rotateBoard(board);
	rotateBoard(board);
	rotateBoard(board);
	success = moveUp(board);
	rotateBoard(board);
	return success;
}

bool won(board_s *board) {
	int8_t x,y;
	int8_t count=0;
	position_s last;

	for (x=0;x<(*board).size;x++) {
		for (y=0;y<(*board).size;y++) {
			if ((*board).field[x][y]=='o') {
				count++;
				last.x = x;
				last.y = y;
			}
		}
	}
	return count==1&&last.x==(*board).win.x&&last.y==(*board).win.y;
}

int8_t validMovesUp(board_s *board) {
	int8_t x,y;
	int8_t count=0;
	for (x=0;x<(*board).size;x++) {
		for (y=(*board).size-1;y>1;y--) {
			if ((*board).field[x][y]=='o') {
				if ((*board).field[x][y-1]=='o') {
					if ((*board).field[x][y-2]=='.') {
						count++;
					}
				}
			}
		}
	}
	return count;
}

bool gameEnded(board_s *board) {
	int8_t i,count=0;
	for (i=0;i<4;i++) {
		count+=validMovesUp(board);
		rotateBoard(board);
	}
	return count==0;
}

void initialize(board_s *board, int8_t layout) {
	int8_t x,y;
	int8_t configuration[5][SIZE][SIZE*2] = {{
		"                  ",
		"      o o o       ",
		"    o o o o o     ",
		"  o o o . o o o   ",
		"  o o o o o o o   ",
		"  o o o o o o o   ",
		"    o o o o o     ",
		"      o o o       ",
		"                  "
	},{
		"      o o o       ",
		"      o o o       ",
		"      o o o       ",
		"o o o o o o o o o ",
		"o o o o . o o o o ",
		"o o o o o o o o o ",
		"      o o o       ",
		"      o o o       ",
		"      o o o       "
	},{
		"      o o o       ",
		"      o o o       ",
		"      o o o       ",
		"  o o o o o o o o ",
		"  o o o . o o o o ",
		"  o o o o o o o o ",
		"      o o o       ",
		"      o o o       ",
		"                  "
	},{
		"                  ",
		"      o o o       ",
		"      o o o       ",
		"  o o o o o o o   ",
		"  o o o . o o o   ",
		"  o o o o o o o   ",
		"      o o o       ",
		"      o o o       ",
		"                  "
	},{
		"        o         ",
		"      o o o       ",
		"    o o o o o     ",
		"  o o o o o o o   ",
		"o o o o . o o o o ",
		"  o o o o o o o   ",
		"    o o o o o     ",
		"      o o o       ",
		"        o         "
	}};
	(*board).size = 9;
	(*board).cursor.x = 4;
	(*board).cursor.y = 4;
	(*board).win.x = 4;
	(*board).win.y = (layout==0)?5:4;
	(*board).selected = false;

	memset((*board).field,0,sizeof((*board).field));
	for (y=0;y<(*board).size;y++) {
		for (x=0;x<(*board).size;x++) {
			(*board).field[x][y]=configuration[layout][y][x*2];
		}
	}
}

void setBufferedInput(bool enable) {
	static bool enabled = true;
	static struct termios old;
	struct termios new;

	if (enable && !enabled) {
		// restore the former settings
		tcsetattr(STDIN_FILENO,TCSANOW,&old);
		// set the new state
		enabled = true;
	} else if (!enable && enabled) {
		// get the terminal settings for standard input
		tcgetattr(STDIN_FILENO,&new);
		// we want to keep the old setting to restore them at the end
		old = new;
		// disable canonical mode (buffered i/o) and local echo
		new.c_lflag &=(~ICANON & ~ECHO);
		// set the new settings immediately
		tcsetattr(STDIN_FILENO,TCSANOW,&new);
		// set the new state
		enabled = false;
	}
}

void signal_callback_handler(int signum) {
	printf("         TERMINATED         \n");
	setBufferedInput(true);
	printf("\033[?25h\033[0m");
	exit(signum);
}

int main(int argc, char *argv[]) {
	board_s board_alloc,*board=&board_alloc;
	board_s history[SIZE*SIZE];
	int8_t moves = 0;
	char c;
	bool success,move;
	int8_t layout = 3;

	if (true&& argc == 2 && strcmp(argv[1],"french")==0) {
		layout = 0;
	} else if (argc == 2 && strcmp(argv[1],"german")==0) {
		layout = 1;
	} else if (argc == 2 && strcmp(argv[1],"asymmetric")==0) {
		layout = 2;
	} else if (argc == 2 && strcmp(argv[1],"english")==0) {
		layout = 3;
	} else if (argc == 2 && strcmp(argv[1],"diamond")==0) {
		layout = 4;
	}

	// reset, hide cursor and clear screen
	printf("\033[0m\033[?25l\033[2J");

	// register signal handler for when ctrl-c is pressed
	signal(SIGINT, signal_callback_handler);

	initialize(board,layout);
	memcpy(&history[moves],board,sizeof(*board));
	drawBoard(board);
	setBufferedInput(false);
	while (true) {
		c=getchar();
		move = (*board).selected;
		switch(c) {
			case 97:	// 'a' key
			case 104:	// 'h' key
			case 68:	// left arrow
				success = moveLeft(board);  break;
			case 100:	// 'd' key
			case 108:	// 'l' key
			case 67:	// right arrow
				success = moveRight(board); break;
			case 119:	// 'w' key
			case 107:	// 'k' key
			case 65:	// up arrow
				success = moveUp(board);    break;
			case 115:	// 's' key
			case 106:	// 'j' key
			case 66:	// down arrow
				success = moveDown(board);  break;
			case 10:	// enter key
			case 13:	// enter key
				success = selectk(board);
				move    = false;            break;
			default: success = false;
		}
		if (success) {
			if (move) {
				moves++;
				memcpy(&history[moves],board,sizeof(*board));
			}
			drawBoard(board);
			if (won(board)) {
				printf("          YOU WON           \n");
				break;
			}
			if (gameEnded(board)) {
				printf("         GAME OVER          \n");
				break;
			}
		}
		if (c=='q') {
			printf("        QUIT? (y/n)         \n");
			c=getchar();
			if (c=='y'){
				break;
			}
			drawBoard(board);
		}
		if (c=='r') {
			printf("       RESTART? (y/n)       \n");
			c=getchar();
			if (c=='y'){
				initialize(board,layout);
				moves=0;
				memcpy(&history[moves],board,sizeof(*board));
			}
			drawBoard(board);
		}
		if (c=='u') {
			printf("        UNDO? (y/n)         \n");
			c=getchar();
			if (c=='y' && moves){
				moves--;
				memcpy(board,&history[moves],sizeof(*board));
			}
			drawBoard(board);
		}
	}
	setBufferedInput(true);
	printf("\033[?25h\033[0m");

	return EXIT_SUCCESS;
}

C 语言小游戏 - 独立钻石棋

独立钻石是源于18世纪法国的宫廷贵族的自我挑战类单人棋游戏,可以锻炼逻辑思维能力。它与中国人发明的华容道、匈牙利人发明的魔方并称智力游戏界的三大不可思议

游戏玩法似中国跳棋,但不能走步,只能跳。棋子只能跳过相邻的棋子到空位上,并且把被跳过的棋子吃掉。棋子可以沿格线横、纵方向跳,但是不能斜跳,剩下越少棋子越好。

游戏级别

剩下6只或以上棋子是“一般”;

剩下5只棋子是“颇好”;

剩下4只棋子是“很好”;

剩下3只棋子是“聪明”;

剩下2只棋子是“尖子”;

剩下1只棋子是“大师”;

最后剩下1只,而且在正中央是“天才”。

控制方式:按WASD代表上下左右回车键代表确定与取消Q表示退出。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨得江-君临天下wyj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值