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