C语言实现天生棋局案例

天生棋局

1.案例描述

要求创建一个棋盘,在棋盘生成的同时初始化棋盘,根据初始化后棋盘中棋子的位置来判断此时的棋局是否是一局好棋。具体要求如下:
(1)棋盘的大小根据用户的指令确定;
(2)棋盘中棋子的数量也由用户设定;
(3)棋子的位置由随机数函数随机确定,若生成的棋盘中有两颗棋子落在同一行或同一列,则判定为“好棋”,否则判定为“不是好棋”。

2.案例设计

(根据案例分析中的棋局生成步骤设计程序,可将程序代码模块化为4个功能函数和1个主函数。
(1)创建棋盘
案例分析中提出,棋盘信息存放在动态生成的空间中。首先创建一个函数,并设计一个(2n+1)(2n+1)的二维数组,用于存放棋盘数据,使用void calloc (size_t num, size_t size)函数动态分布棋盘空间,初始化棋盘数据为0,并返回一个指向该棋盘地址的二级指针
(2)生成棋子数据
创建两个奇数随机数作为作为棋子的坐标,并判断该位置是否已经有棋子,有则重新生成,没有则使该位置为1,代表棋子。
(3)输出棋盘
将棋盘数据中的偶数位作为棋盘边框,奇数位作为存放棋子的位置。奇数位若为1,则放棋子,为零则放空格
(4)判断是否为好棋
将棋盘的每行或者每列奇数位之和计算出来,若同一行或者同一列之和大于1则使好棋。
(5)释放指针空间
在创建棋盘时申请的空间,在使用完毕后手动释放。使用void free (void* ptr)函数。

3.代码实现

方案一:

//天生棋局 

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
	srand((unsigned)time(NULL));
	int row,column,num,**p;
	//加载函数 
	int **creat_checkerboard(int row,int column);
	void creat_piece(int **p,int num,int row,int column);
	void print_checkerboard(int **p,int row,int column);
	void is_good(int **p,int row,int column);
	void free_board(int **p, int row);
	 
	printf("请输入行和列的数量:"); 
	scanf("%d%d",&row,&column);
	printf("请输入棋子的数量:"); 
	scanf("%d",&num);
	row=2*row+1;
	column=2*column+1;
	

	p=creat_checkerboard(row,column);//获取棋盘指针 
	creat_piece(p,num,row,column);//创建棋子数据 
	print_checkerboard(p,row,column);//输出棋盘 
	is_good(p,row,column);//判断是否为好棋 
	printf("row = %d column = %d\n",row,column);
	printf("num = %d\n",num);
	free_board(p,row); //释放内存空间 
	return 0; 
} 
int ** creat_checkerboard(int row,int column){//创建棋盘,并初始化为零 
		int **p = (int**)calloc(sizeof(int*), row);
		/*
		头文件:#include <stdlib.h>

		原型: 
        void* calloc (size_t num, size_t size);
        作用:用于分配num个size大小的连续内存空间,且初始化每个字节都为零
		返回值:为未指定类型,需要强转 
		*/
		int i = 0;
		for (i = 0; i < row; i++)
		{
			p[i] =(int*)calloc(sizeof(int), column);
		}
		for(int x=0;x<row;x++)//将棋盘数据全部赋值为零 
			for(int y=0;y<column;y++)
				p[x][y]=0;
		/*		
		for(int x=0;x<row;x++)//输出棋盘数据确认 
			{for(int y=0;y<column;y++)
				printf(" %d",p[x][y]);
				printf("\n");
			}
			printf("\n");*/
	return p;
}

void creat_piece(int **p,int num,int row,int column){//生成棋子数据 
	int x,y,count=0;
	while(count!=num){
		x = rand()%row;
		y = rand()%column;
		if(x%2==1&&y%2==1&&p[x][y]==0){//把棋子放到棋盘的奇数位 
			p[x][y]=1;
			count++;
		}

	}
	/*
	for(int x=0;x<row;x++)//查看赋值是否正常 
			{for(int y=0;y<column;y++)
				printf(" %d",p[x][y]);
				printf("\n");
			}*/
}
void print_checkerboard(int **p,int row,int column){//输出棋盘 
	for(int x=0;x<row;x++){
		if(x%2==0)
			for(int y=0;y<column;y++)//行偶数位为边框 
				printf("—");
		else{
			for(int y=0;y<column;y++)
				
				if(p[x][y]==1)//值为1的位置放棋子 
					printf("o ");
				else 
					if(y%2==0)
						printf("| ");//列的偶数位为边框 
					else
						printf("  ");//没有棋子的奇数位为空格 
		}
		printf("\n");
				
	}
}
void is_good(int **p,int row,int column){
	int flag=0,row_sum,column_sum;
	for(int x = 1;x<row;x += 2){//确保x为奇数位 
		row_sum=0;//遍历一行后归零
		for(int y = 1;y<column-2;y += 2){//确保y为奇数位
			row_sum +=p[x][y];//行之和大于1,是好棋
			if(row_sum>1){
				flag=1;
				break;
			}
		}
	}
	for(int y= 1;y<column;y+= 2){//确保y为奇数位 
		column_sum=0;//遍历一列后归零 
		for(int x = 1;x<row-2;x += 2){//确保x为奇数位
			column_sum +=p[x][y];
			if(column_sum>1){//列之和大于1,是好棋 
				flag=1;
				break;
			}
		}
			
	}
		
	printf("flag=%d\n",flag);
	if(flag)
		printf("是好棋\n") ;
	else
		printf("不是好棋\n") ;
	
}
//释放内存空间 
void free_board(int **p, int row){
	/*
	头文件:#include <stdlib.h>
	原型为:
    void free (void* ptr);
    作用:释放某一级的指针指向的内存空间 
    返回值:空 
	*/
	for (int i = 0; i < row; ++i)
	{
		free(p[i]);			//释放一级指针指向的空间 
	}
	free(p);				//释放二级指针指向的空间
}

方案二:(相邻位子上有棋子才算好棋)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
int ** createBoard(int n)//用返回类型是二维指针的类型,创建一个棋盘,长度由主函数传递来
{
	int **p = (int**)calloc(sizeof(int*), n);
	int i = 0;
	for (i = 0; i < n; i++)
	{
		p[i] = calloc(sizeof(int), n);
	}
	return p;
}
//初始化棋盘
int initBoard(int **p, int n, int tmp)//用随机数下棋
{
	int i, j;
	int t = tmp;
	while (t > 0)
	{
		i = rand() % n;
		j = rand() % n;
		if (p[i][j] == 1)//坐标内已有棋子则再次循环
			continue;
		else
		{
			p[i][j] = 1;
			t--;
		}
	}
	return 0;
}
//输出棋盘
int printfBoard(int **p, int n)
{
	int i, j;
	for (i = 0; i < n; i++)//用行列计数变量检测同一行或列是否多于2个棋子
	{
		for (j = 0; j < n; j++)
		{
			if (p[i][j] == 1)						//输出棋子
			{
				printf("●");
			}
			else									//搭建棋盘
			{
				if (i == 0 && j == 0)
					printf("┏");
				else if (i == 0 && j == n - 1)
					printf("┓");
				else if (i == n - 1 && j == 0)
					printf("┗");
				else if (i == n - 1 && j == n - 1)
					printf("┛");
				else if (j == 0)
					printf("┠");
				else if (i == n - 1)
					printf("┷");
				else if (j == n - 1)
					printf("┨");
				else if (i == 0)
					printf("┯");
				else
					printf("┼");
			}
		}
		putchar('\n');
	}
	for (i = 0; i < n; i++)//用行列两个循环判断是否行列上有两个相邻的棋子
	{
		for (j = 0; j<n; j++)
		{
			if (p[i][j] == 1)
			{
				if (j>0 && p[i][j - 1] == 1)		//判断同一行有无相邻棋子
				{
					printf("好棋!\n");
					return 0;
				}
				if (i > 0 && p[i - 1][j] == 1)		//判断同一列有无相邻棋子
				{
					printf("好棋\n");
					return 0;
				}
			}
		}
	}
	printf("不是好棋\n");
	return 0;
}
//销毁棋盘
void freeBoard(int **p, int n)
{
	int i;
	for (i = 0; i < n; ++i)
	{
		free(p[i]);						//释放一级指针指向的空间
	}
	free(p);							//释放二级指针指向的空间
}
int main()
{
	srand((unsigned int)time(NULL));
	int n = 0, tmp = 0;
	printf("设置棋盘大小:");
	scanf("%d", &n);					//输入棋盘行(列)值
	int **p = createBoard(n);			//创建棋盘
	printf("设置棋子数量 :");
	scanf("%d", &tmp);					//输入棋盘上的棋子数量
	initBoard(p, n, tmp);				//初始化棋盘
	printfBoard(p, n);					//打印棋盘
	freeBoard(p, n);					//释放棋盘
	return 0;
}

4.运行结果

方案一:
在这里插入图片描述

方案二:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值