五子棋的c语言源码 | 您所在的位置:网站首页 › 五子棋编程代码 › 五子棋的c语言源码 |
这是实现五子棋落子和判断胜负的源代码,电脑落子涉及的人工智能算法(目前AI属于弱智的随机落子)暂时没有实现。本文重点讲一下胜负判断功能的实现,我们都知道五子棋中获胜的条件就是五联子,而五联子的方向有四种:水平、竖直和两个对角线方向。扫描的思想是在每个落子的位置判断各个方向能扫描的次数(最多为5)。以水平方向为例,数组下标为【5】【5】的从【5】【0】开始判断连往右的五个坐标(即数组元素)的值是否相等,如果是则表明获胜。 #include #include
#define NO_CHESS "十" #define RED_CHESS "❤️" #define BLACK_CHESS "♠️" #define BOARD_SIZE 15 //定义棋盘的大小 typedef int DataType; struct Stack { DataType arr[BOARD_SIZE][BOARD_SIZE]; int top; };
//定义一个二维数组来充当棋盘 const char *Chesses[BOARD_SIZE][BOARD_SIZE];
//----函数的声明-----
//初始化棋盘 void initChess(void); //输出棋盘 void prChess(void); //判断输赢 void winJudge(char* corlor,int x,int y); //提示获得胜利 void printWin(char* color); //横向扫描函数 void horizonScan(char* color,int x,int y); //纵向扫描函数 void verticalScan(char* color,int x,int y); //正对角线扫描函数 void diagonalScan(char* color,int x,int y); //反对角线扫描函数 void opposeDiagonalScan(char* color,int x,int y); //悔棋函数 void retract();
//-----函数的实现----- //初始化棋盘 void initChess(void) { //把每一个元素赋值为 "十" 用于控制台画出棋盘 for (int i =0; i Chesses[i][k] = NO_CHESS; } }
}
//输出棋盘 void prChess(void) {
printf(" 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14\n"); //打印每个数组元素的值 for (int i =0; i printf("%s ",Chesses[i][k]); }
//换行 printf("\n"); } }
//判断输赢 void winJudge(char* color,int x,int y) { //横向扫描 horizonScan(color, x, y); //纵向扫描 verticalScan(color, x, y); //对角线方向扫描 diagonalScan(color, x, y); //反对角线方向扫描 opposeDiagonalScan(color, x, y); } //横向扫描函数 void horizonScan(char* color,int x,int y) { //count存储扫描的次数 int count; //存储变量 int sign; if((8-abs(y-7))>4) { count=4; }else{ count=7-abs(y-7); } //4-10列扫描五次,0和14列扫描一次;其中0列从当前位置开始扫描,而14列从10列扫描;其他列类似 for (int i=count; i>=0; i--) { //前4列只能扫描到第0列,不能越界 if (y>7) { sign=i-4; }else { sign=0-i; } //扫描是否五联子 if ((*Chesses[x][y+sign]==*color)&&(*Chesses[x][y+sign+1]==*color)&&(*Chesses[x][y+sign+2]==*color)&&(*Chesses[x][y+sign+3]==*color)&&(*Chesses[x][y+sign+4]==*color))
printWin(color);
}
} //纵向扫描函数 void verticalScan(char* color,int x,int y) { //count存储扫描的次数 int count; //存储变量 int sign; if((8-abs(x-7))>4) { count=4; }else { count=7-abs(x-7); } //4-10行扫描五次,0和14行扫描一次;其中0行从当前位置开始扫描,而14行列从10行扫描;其他行类似 for (int i=count; i>=0; i--) { //前4行只能扫描到第0行,不能越界 if (x>7) { sign=i-4; }else { sign=0-i; } //扫描是否五联子 if ((*Chesses[x+sign][y]==*color)&&(*Chesses[x+sign+1][y]==*color)&&(*Chesses[x+sign+2][y]==*color)&&(*Chesses[x+sign+3][y]==*color)&&(*Chesses[x+sign+4][y]==*color))
printWin(color);
}
} //对角线扫描函数/Users/tarena0036/Desktop/屏幕快照 2016-05-04下午2.16.17.png void diagonalScan(char* color,int x,int y) { //count用于存储扫描的次数 int count; //存储变量 int sign; //用于存储临时数据 int temp; if((8-abs(x-7))>4&&(8-abs(y-7))>4) { count=4; } else if(x temp=x>=y?x:y; count=7-abs(temp-7);
} else if (abs(x-y)==10) { count=0; } else if (abs(x-y)==9) { count=1; } else if (abs(x-y)==8) { count=2; } else { //其他情况无需扫描 count=-1; } //(4-10)*(4-10)区域扫描五次,0和14行/列扫描一次;其中0行/列从当前位置开始扫描,而14行/列从10行/列扫描;其他行类似 for (int i=count; i>=0; i--) { //前4行只能扫描到第0行,不能越界 if (x+y sign=-(i+1); } else sign=-i; }else { if (x==2||y==2) { sign=i-2; } else if (x==3||y==3) { sign=i-3; } else sign=i-4; } //扫描是否五联子 if ((*Chesses[x+sign][y+sign]==*color)&&(*Chesses[x+sign+1][y+sign+1]==*color)&&(*Chesses[x+sign+2][y+sign+2]==*color)&&(*Chesses[x+sign+3][y+sign+3]==*color)&&(*Chesses[x+sign+4][y+sign+4]==*color))
printWin(color);
}
} //反对角线扫描 void opposeDiagonalScan(char* color,int x,int y) { //count用于存储扫描的次数 int count; //存储变量 int sign; //用于存储临时数据 int temp; if((8-abs(x-7))>4&&(8-abs(y-7))>4) { count=4; } else if(x3) { temp=(abs(x-7))>=(abs(y-7))?x:y; count=7-abs(temp-7); } else if (x>3&&y count=0; } else if ((x+y)==5||(x+y)==23) { count=1; } else if ((x+y)==6||(x+y)==22) { count=2; } else { //其他情况无需扫描 count=-1; } //(4-10)*(4-10)区域扫描五次,0和14行/列扫描一次;其中0行/列从当前位置开始扫描,而14行/列从10行/列扫描;其他行类似 for (int i=count; i>=0; i--) { //前4行只能扫描到第0行,不能越界 if (x>y) { if (x==3||y==11) { sign=i+1; } else sign=i; }else { if (x==12||y==2) { sign=i+2; } else if (x==11||y==3) { sign=i+3; } else sign=i+4; } //扫描是否五联子 if ((*Chesses[x+sign][y-sign]==*color)&&(*Chesses[x+sign-1][y-sign+1]==*color)&&(*Chesses[x+sign-2][y-sign+2]==*color)&&(*Chesses[x+sign-3][y-sign+3]==*color)&&(*Chesses[x+sign-4][y-sign+4]==*color))
printWin(color);
} } //悔棋功能 void retract() {
}
//输出获胜信息 void printWin(char* color) { printf("%s Win!\n",color); //结束程序 exit(1); }
//主函数 int main(int argc,const char * argv[]) { //初始化二维数组,存储棋盘坐标点的是否已经有棋子信息 int info1[BOARD_SIZE][BOARD_SIZE]={0}; //定义栈,用于存储坐标,悔棋时取出栈顶元素将对应位置的点复位
//调用函数 initChess(); prChess();
//开始循环下棋 while (1) {
int xPos; int yPos; menu: printf("请输入您下棋的坐标,如x y(输入15 15为悔棋) \n"); scanf("%d %d",&xPos,&yPos); if (xPos>BOARD_SIZE||yPos>BOARD_SIZE) { printf("请在边界内输入有效数字!\n"); goto menu; } else if(xPos==BOARD_SIZE&&yPos==BOARD_SIZE) { retract(); } if (1==info1[xPos][yPos]) { printf("您输入的位置已经有棋子,请重新输入:\n"); goto menu; } //将已经落子的点标记为1 info1[xPos][yPos]=1; //把对应的数组元素赋值成红棋 Chesses[xPos][yPos] = RED_CHESS; //刷新棋盘 prChess(); //判断是否获胜 winJudge(Chesses[xPos][yPos],xPos,yPos);
int macXPos,macYPos; macPosition: //随机生成2个 0~15之间的数作为电脑下棋的坐标 macXPos = arc4random()%BOARD_SIZE; macYPos = arc4random()%BOARD_SIZE; //判断生成的坐标的对应的点是否已经有棋子了 if (1==info1[macXPos][macYPos]) { goto macPosition; } //将电脑下棋的坐标赋值 为 黑旗 Chesses[macXPos][macYPos] = BLACK_CHESS; //将已经落子的点标记为1 info1[macXPos][macYPos]=1; //刷新棋盘 prChess(); //判断黑棋是否获胜 winJudge(Chesses[macXPos][macYPos],macXPos,macYPos);
}
/* 上面的代码还涉及到如下需要改进的地方 1、用户输入坐标的有效性,只能是数字,不能超出棋盘的范围(暂时没有对整个棋盘是否落满子进行判断) 2、如果是已经下棋的点,不能重复下棋(实现) 3、每次下棋后,需要扫描谁赢了
4、悔棋功能 */ return 0; }
|
CopyRight 2018-2019 实验室设备网 版权所有 |