龙空技术网

C语言编写的五子棋(新手学习源码)

沉迷与C语言日渐消瘦 1489

前言:

此时看官们对“五子棋源代码c完美版”可能比较着重,姐妹们都需要剖析一些“五子棋源代码c完美版”的相关内容。那么小编也在网摘上网罗了一些关于“五子棋源代码c完美版””的相关知识,希望大家能喜欢,看官们一起来了解一下吧!

这是实现五子棋落子和判断胜负的源代码,电脑落子涉及的人工智能算法(目前AI属于弱智的随机落子)暂时没有实现。本文重点讲一下胜负判断功能的实现,我们都知道五子棋中获胜的条件就是五联子,而五联子的方向有四种:水平、竖直和两个对角线方向。扫描的思想是在每个落子的位置判断各个方向能扫描的次数(最多为5)。以水平方向为例,数组下标为【5】【5】的从【5】【0】开始判断连往右的五个坐标(即数组元素)的值是否相等,如果是则表明获胜。 建议:如果有想学习编程的加qq群 590750544 大家一起学习交流共同进步,群里有老司机可以带我们,有工具学习资料和教学视频。

#include <stdio.h>

#include <stdlib.h>

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

};

//定义一个二维数组来充当棋盘

constchar *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<BOARD_SIZE; i++)

{

for (int k =0; k<BOARD_SIZE; k++)

{

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<BOARD_SIZE; i++)//行

{

printf("%02d ",i);

for (int k =0; k<BOARD_SIZE; k++)//列

{

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<11&&y<11)

{

temp=x<=y?x:y;

count=7-abs(temp-7);

}

else if (x>3&&y>3)

{

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<14)

{

if (x==11||y==11)

{

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(x<11&&y>3)

{

temp=(abs(x-7))>=(abs(y-7))?x:y;

count=7-abs(temp-7);

}

else if (x>3&&y<11)

{

temp=(abs(x-7))>=(abs(y-7))?x:y;

count=7-abs(temp-7);

}

else if ((x+y)==4||(x+y)==24)

{

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;

} 建议:如果有想学习编程的加qq群 590750544 大家一起学习交流共同进步

标签: #五子棋源代码c完美版 #五子棋c语言编程教程 #c语言实现五子棋 #c语言实现五子棋悔棋 #值算法做了个简单的五子棋