五子棋的c语言源码

这是实现五子棋落子和判断胜负的源代码,电脑落子涉及的人工智能算法(目前AI属于弱智的随机落子)暂时没有实现。本文重点讲一下胜负判断功能的实现,我们都知道五子棋中获胜的条件就是五联子,而五联子的方向有四种:水平、竖直和两个对角线方向。扫描的思想是在每个落子的位置判断各个方向能扫描的次数(最多为5)。以水平方向为例,数组下标为【5】【5】的从【5】【0】开始判断连往右的五个坐标(即数组元素)的值是否相等,如果是则表明获胜。

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

};

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

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

}

时间: 2024-11-08 16:20:08

五子棋的c语言源码的相关文章

比特币挂机网赚易语言源码日赚200已上+网站+视频全套

是于易语言开发而成 在线挂机获取收益 软件内设VIP系统 提款系统 推广系统 等多功能化 如而要易语言程序源码的可以联系我QQ 382913699 注册的话需要下载软件,软件大小不到2M,下载下来后注册下,一般一天可以挖200块钱左右!提现的不是VIP一天只能提现1次,一次0.3元! VIP没有这个限制!首先我不是VIP所以不敢断言一定 所以请大家帮个忙,复制下网址访问下就可以了! 等访问量达到500一定给大家反馈下!就算是假的 一天领0.3元也好啊

Go语言源码中的Rabin-Karp算法

strings.go包实现了一个Rabin-Karp算法.有点意思. 关于这个算法: 图灵社区的有一篇: 图说Rabin-Karp字符串查找算法 关于Go源码实现: 网友GoLove已写一个篇非常详细的说明了. http://www.cnblogs.com/golove/p/3234673.html GoLove那个已经分析的非常清楚了,只是前面那一串说明太长了.我把他的说明替换成代码形式. 直接跑起来,这样更能看得清楚些. package main import ( "fmt" &q

Go语言源码中Replacer查找部份的笔记

用过strings.NewReplacer,replacer.Replace(),它按对传入参数后,能依优先级替换,并能处理中文字符串参数. 觉得功能强大,特别好用.对它的查找和优先级怎么处理有点兴趣,花时间研究了下源码,在这记录一下个人理解. package main //author:xcl //2014-1-20 记录 import ( "fmt" "strings" ) func main(){ patterns := []string{ "y&q

go语言源码赏析之strings

0.字符串为不可变类型,内部使用指针指向UTF-8字节数组 不过要修改字符串可以先将其转换成[]byte或者[]rune.如下 package main func main() { s := "abcd" bs := []byte(s) bs[1] = 'B' println(string(bs)) u := "电脑" us := []rune(u) us[1] = '话' println(string(us)) } 输出: aBcd 电话 for遍历字符串有byt

栈的C语言源码

1.导言(为什么要用栈?) 通常来说,决定采用何种方式来存储数据是非常重要的,这样便于对数据检索时,数据会自动按照某种规定的顺序给出.栈和队列是检索数据的一种常用的数据结构.栈和队列是两种非常重要的数据结构,从数据结构来看,栈和队列也是线性表.是操作受限的线性表,栈只能在一端(栈顶)进行插入和删除,队列只能在一端(队尾)进行插入在另一端(队头)进行删除.但是从数据类型来说,栈和队列是和线性表不大相同两类重要的抽象数据类型.这里,首先重点介绍栈,以及栈的先关操作的c语言实现.栈是按照后进先出(LI

华为面试题:扑克牌大小 C语言源码

扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A.2各4张,小王1张,大王1张.牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王): 3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER 输入两手牌,两手牌之间用"-"连接,每手牌的每张牌以空格分隔,"-"两边没有空格,如:4 4 4 4-joker JOKER. 请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR. 基本规则

简易计算器c语言源码,

本人新学, 用的都是最基本的语句, 程序功能不完善, 有以下问题, 1.大数据无法计算, 2.较大整型数据输出为浮点型,(因为是老师布置的作业,有要求含实数的算术计算输出要含小数.) 3.无法用()提升运算优先级, 欢迎提出改进意见 代码附上: void fun1()//算术运算函数{ char a[20][30],b[20]; double c[20],s; int i,j,k,flag; system("cls");// printf("输入算术式\n格式如:31+42*

华为面试题:识别有效的ip地址和子网掩码并分类 C语言源码

识别有效的ip地址和子网掩码并分类: 按行输入多组数据 10.8.9.2~255.0.0.0 180.8.9.2~255.254.0.0 打印:A B C D E 错误的ip或掩码 私有ip 的个数 #include "stdio.h" #include "stdlib.h" #include "string.h" #define MAX_PATH 256 int maze[10][10] = {0}; int route[100][2] = {

华为面试题:开放的书名检索库 c语言源码

开放的书名检索库 实现一个开放的书名检索库.库中存储了若干个书名.用户可以:指定搜索条件,搜索库中符合条件的书名 重要格式说明 单词 由小写英文字母组成,不含其它字符. 书名 由一个或多个单词组成. 当包含多个单词时,单词间用一个空格分隔:第一个单词前和最后一个单词后没有空格. 若只包含一个单词,则该单词前后均无空格. 搜索条件 1.由一个或多个不重复的关键字组成,每个关键字是一个单词. 2.当包含多个关键字时,关键字间用一个空格分隔:第一个关键字前和最后一个关键字后没有空格. 3.若只包含一个