Unix 系统下用C语言写的中国象棋程序(使用光标库)

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <locale.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>


#define StartX 28 //光标起始位置
#define StartY 14
#define INTERVAL 1          //计时间隔 1 秒
#define N 32 //棋子个数
#define COL 75
#define ROW 25


/***************************************************************************
中国象棋 C语言版
游戏说明:通过键盘上的方向键来控制光标的移动,光标落到棋子上时,按下空格键
即选定要移动的棋子,然后移动光标到目标位置,再按下空格键,即放定棋子。
编译时要加入动态链接库 gcc filename.c -lncurses
作者:ThomasHwak
运行环境: OS X 10.7.4
最后一次修改时间:2013-9-25
版本号:1.0
***************************************************************************/
typedef struct chess
{
	int x;
	int y;
	int prev_x;
	int prev_y;
	char *name; 
} CHESS;         //定义棋子结构体,存储棋子的属性

CHESS array[N];

int x=StartX;
int y=StartY;
int ch=0;       //读取键盘字符
int cnt=0;      //统计空格按下次数
int i=0,j=0;
int second=0;
int minute=0;    //计时用分钟,秒
int startOrPause=1;
int flag=0;      
int board[ROW][COL]={0};   //保存棋盘坐标

void chess_init(void);     //初始化棋子,界面
void menu_show(void);
void interface_Init(void);
void curse_Init(void);
void doAction(int sig);
int chess_control(void);
void key_check(void);
void setMyTimer(int val);
void put_chess(void);
int check_rule(struct chess current_chess,int x,int y);

int check_rule(struct chess current_chess,int x,int y)
{
	int min_x=0;
	int min_y=0;
	if(strcmp(current_chess.name,"馬")==0)
	{
		if(y>=5 && y<=23 && x>=30 && x<=70)
		{
			if(((abs(x-current_chess.x)==5 && abs(y-current_chess.y)==4)) || 
				(abs(x-current_chess.x)==10 && abs(y-current_chess.y)==2))
			{
				if(flag==1)
				{
					mvprintw(15,8,"               ");
					flag=0;
				} 
				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"馬行一步一尖冲!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"車")==0)
	{
		if(y>=5 && y<=23 && x>=30 && x<=70)
		{
			if(((abs(x-current_chess.x)==0 && abs(y-current_chess.y)%2==0)) ||
				(abs(x-current_chess.x)%5==0 && abs(y-current_chess.y)==0))
			{

				min_x = x<current_chess.x ? x:current_chess.x;
				min_y = y<current_chess.y ? y:current_chess.y;

				if(flag==1)
				{
					mvprintw(15,8,"                ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"車行直路任西东!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"象")==0 || strcmp(current_chess.name,"相")==0)
	{
		if(y>=5 && y<=23 && x>=30 && x<=70)
		{
			if((abs(x-current_chess.x)==10 && abs(y-current_chess.y)==4))
			{
				if(flag==1)
				{
					mvprintw(15,8,"                  ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"象飞四方营四角!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"士")==0 || strcmp(current_chess.name,"仕")==0)
	{
		if((y>=5 && y<=9 && x>=45 && x<=55) || (y>=19 && y<=23 && x>=45 && x<=55))
		{
			if((abs(x-current_chess.x)==5 && abs(y-current_chess.y)==2))
			{
				if(flag==1)
				{
					mvprintw(15,8,"                  ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"士止相随不出宫!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"将")==0 || strcmp(current_chess.name,"帅")==0)
	{
		if((y>=5 && y<=9 && x>=45 && x<=55) || (y>=19 && y<=23 && x>=45 && x<=55))
		{
			if((abs(x-current_chess.x)==0 && abs(y-current_chess.y)==2) || 
				(abs(x-current_chess.x)==5 && abs(y-current_chess.y)==0))
			{
				if(flag==1)
				{
					mvprintw(15,8,"                 ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"将军不离九宫内!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"卒")==0)
	{
		if((y>=5 && y<=23 && x>=30 && x<=70))
		{
			if( (abs(x-current_chess.x)==0 && y-current_chess.y==2 ) || 
				(abs(x-current_chess.x)==5 && y-current_chess.y==0 && y>=15))
			{
				if(flag==1)
				{
					mvprintw(15,8,"               ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"小卒过河横竖闯!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"兵")==0)
	{
		if((y>=5 && y<=23 && x>=30 && x<=70))
		{
			if( (abs(x-current_chess.x)==0 && y-current_chess.y==-2 ) || 
				(abs(x-current_chess.x)==5 && y-current_chess.y==0 && y<=13))
			{
				if(flag==1)
				{
					mvprintw(15,8,"               ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"小卒过河横竖闯!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}
	if(strcmp(current_chess.name,"炮")==0)
	{
		if(y>=5 && y<=23 && x>=30 && x<=70)
		{
			if(((abs(x-current_chess.x)==0 && abs(y-current_chess.y)%2==0)) ||
				(abs(x-current_chess.x)%5==0 && abs(y-current_chess.y)==0))
			{
				if(flag==1)
				{
					mvprintw(15,8,"                ");
					flag=0;
				}

				return 1;
			}
			else
			{
				attron(A_BOLD);
				mvprintw(15,8,"炮需隔子打一子!");
				attrset(A_NORMAL);
				flag=1;
				return 0;
			} 
		}
		else
			return 0;
	}

}


void put_chess(void)
{
	int i=0;
	for(i=0;i<N;i++)
	{
		if(i<=15)
			mvprintw(array[i].y,array[i].x,array[i].name);
		else
		{
			attron(A_REVERSE);
			mvprintw(array[i].y,array[i].x,array[i].name);
			attrset(A_NORMAL);
		}
	}
}

void chess_init(void)
{
	int i=0;
	int y=0;
	int x=0;
	curse_Init();
/***********************  初始化结构体数组  *******************/

	for(i=0;i<N;i++)            
	{
		if(i==0 || i==8 || i==16 ||i==24)
		{
			array[i].name="車";
		}
		if(i==1 || i==7 || i==17 || i==23)
		{
			array[i].name="馬";
		} 
		if(i==2 || i==6)
		{
			array[i].name="象";
		}
		if(i==18 || i==22)
		{
			array[i].name="相";
		}
		if(i==3 || i==5)
		{
			array[i].name="士";
		}
		if(i==19 || i==21)
		{
			array[i].name="仕";
		}
		if(i==4)
		{
			array[i].name="将";
		}
		if(i==20)
		{
			array[i].name="帅";
		}
		if(i==9 || i==10 ||i==25 ||i==26)
		{
			array[i].name="炮";
		}
		if(i==11 || i==12 || i==13 || i==14 ||i==15)
		{
			array[i].name="卒";
		}
		if(i==27 || i==28 || i==29 || i==30 || i==31)
		{
			array[i].name="兵";
		}
	}

/********************  棋盘上半部分 ********************/

	for(i=0,y=5,x=30;x<=70;x+=5,i++)
	{
		array[i].x=x;
		array[i].y=y;
		board[y][x]=1;
	}

	for(i=11,y=11,x=30;x<=70;x+=10,i++)
	{
		array[i].x=x;
		array[i].y=y;
		board[y][x]=1;
	}

	for(i=9,y=9,x=35;x<=65;x+=30,i++)
	{
		array[i].x=x;
		array[i].y=y;
		board[y][x]=1;

	}
/*********************  棋盘下半部分 *****************/



	for(i=16,y=23,x=30;x<=70;x+=5,i++)
	{
		array[i].x=x;
		array[i].y=y;
		board[y][x]=1;
	}

	for(i=25,y=19,x=35;x<=65;x+=30,i++)
	{
		array[i].x=x;
		array[i].y=y;
		board[y][x]=1;
	}

	for(i=27,y=17,x=30;x<=70;x+=10,i++)
	{
		array[i].x=x;
		array[i].y=y;
		board[y][x]=1;
	}

}


void key_check(void)
{
	do
	{
		if(startOrPause==-1)
			setMyTimer(INTERVAL);
		else
			setMyTimer(10000);

		ch=getch();
		chess_control();
		switch(ch)
		{
			case KEY_UP:
			--y;
			break;

			case KEY_DOWN:
			++y;
			break;

			case KEY_LEFT:
			--x;
			break;

			case KEY_RIGHT:
			++x;
			break;

			case '\t':
			x+=7;
			break;

			case '\r':
			startOrPause=0-startOrPause;
			break;

			case KEY_BACKSPACE:
			mvaddch(y,--x,' ');
			break;

			case 27:
			endwin();
			exit(1);

			default:
//addch(ch);
			x=x;
			break; 
		}
		move(y,x); 
	}while(1);
}

int chess_control(void)
{


	if(ch==' ')
	{
		if(cnt==1)
		{
			if(check_rule(array[i],x,y)==0)
			{
				cnt=0;
				return 0;
			}


			for(j=0;j<32;j++)
			{
				if(array[j].y==y && array[j].x==x)
				{
					if((i<=15 && j<= 15) || (i>=16 && j>=16))
						return 0;

					board[array[j].y][array[j].x]=0;

					array[j].x=300;
//mvprintw(array[j].y,array[j].x,"|");
					if(j==4)
					{
						attron(A_BLINK);
						mvprintw(14,8,"黑方胜!");
						attrset(A_NORMAL);
					}
					if(j==20)
					{
						attron(A_BLINK);
						mvprintw(14,8,"白方胜!");
						attrset(A_NORMAL);
					}
				} 
			}

			board[array[i].y][array[i].x]=0;

			array[i].y=y;
			array[i].x=x;
			interface_Init();
			if(i<=15)
			{
				mvprintw(array[i].y,array[i].x,array[i].name);
			}
			else
			{
				attron(A_REVERSE);
				mvprintw(array[i].y,array[i].x,array[i].name);
				attrset(A_NORMAL);
			} 

			cnt=0;
		} 
		else
		{
			for(i=0;i<32;i++)
			{
				if(array[i].y==y && array[i].x==x && cnt==0)
				{
					cnt=1;
					break;
				}
			} 
		}

	} 
}

void curse_Init(void)
{
	initscr();
	cbreak();
	nonl();
	noecho();
	intrflush(stdscr,FALSE);
	keypad(stdscr,TRUE);
	refresh();
}


void interface_Init(void)
{
	curse_Init();


	int rows=0;
	int cols=30;
/**************************  画棋盘  ******************/

for(rows=5;rows<=24;rows=rows+2)    //画横线
{   
	move(rows,cols);
	whline(stdscr,'-',40);
}
rows=5;
for(cols=30;cols<=70;cols=cols+5)
{
	move(rows,cols);
	wvline(stdscr,'|',19);
}
move(14,31);
whline(stdscr,' ',39);
mvprintw(14,37,"楚");
mvprintw(14,43,"河");
mvprintw(14,56,"汉");
mvprintw(14,62,"界");
attron(A_BOLD|A_UNDERLINE);
mvprintw(1,47,"中国象棋");
attrset(A_NORMAL);

put_chess();

move(y,x); 
}


void menu_show(void)
{
	int k=0;
	curse_Init();
	attron(A_BOLD);
	mvprintw(8,85,"回车键开始计时");
	mvprintw(10,85,"Esc键退出");
	attrset(A_NORMAL);
	mvaddstr(1,75,"╭∩╮(︶︿︶)╭∩╮");
	mvaddstr(1,10,"╭∩╮(︶︿︶)╭∩╮");
	refresh();
}


void doAction(int sig)
{
	curse_Init();
	if(second==59)
	{
		minute++;
		second=0;
	}
	mvprintw(5,85,"游戏已经开始 %d 分钟 %d 秒",minute,second);
	second++;
	interface_Init();
	refresh();
	signal(SIGALRM,doAction);
}


void setMyTimer(int val)
{
	struct itimerval value;
	value.it_value.tv_sec=val;
	value.it_value.tv_usec=0;
value.it_interval.tv_sec=val;  //val 秒
value.it_interval.tv_usec=0;
signal(SIGALRM,doAction);
setitimer(ITIMER_REAL,&value,NULL);
}


int main(void)
{
	setlocale(LC_ALL,"");
	menu_show();
	chess_init();
	interface_Init();
	key_check();

	return 0;
}











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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值