五(N)子棋,可定义N值,棋盘大小,自动判断游戏是否结束【学习记录】

目录

前言

一、引用头文件

二、代码

1、主函数

2、头文件

3、函数文件

三、编写时出现的问题

总结


前言

在哔哩哔哩上比特鹏哥的课程上学习C++的时候看见了一个三子棋的编程教学,本着跟着学一学项目编写的目的跟着编写了一部分,在看到电脑落子是随机的的时候决定剩下的自己写,于是把原来的三子棋拓展为了一个标准的五子棋,并自行编写了判断是否游戏结束的函数。运行效果还行,发出来纪念一下,第一个半自主编写的小项目


提示:以下是本篇文章正文内容,下面案例可供参考

一、引用头文件

        该项目引用了iostream和stdio.h两个头文件

#include <stdio.h>
#include <iostream>
using namespace  std;

        其实本来只用引入<:stdio.h>的,但是不知道为什么scanf函数出了些问题,就不得不改用cin做次级替代了。

二、代码

        啥都不说了直接贴代码吧。

1、主函数

        主函数基本和鹏哥的一致。

#define _CPR_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "game.h"
#include <iostream>
using namespace std;
//#include "game.c"
void menu()
{
	printf("______________________________\n");
	printf("____________五子棋____________\n");
	printf("____________1.play____________\n");
	printf("____________0.exit____________\n");
	printf("___________by__Weber__________\n");
	printf("______________________________\n");
}
void game()
{
	char board[ROW][COL];
	InitBoard(board,ROW,COL);
	DisplayBoard(board,ROW,COL);
	while(1)
	{
		Player1Move(board,ROW,COL);
		DisplayBoard(board,ROW,COL);
	//	cout<<Check1Done(board,ROW,COL)<<endl;
		if(Check1Done(board,ROW,COL))
		{
			printf("玩家1胜利\n");
			break;
		}
		Player2Move(board,ROW,COL);
		DisplayBoard(board,ROW,COL);
		if(Check2Done(board,ROW,COL))
		{
			printf("玩家2胜利\n"); 
			break;
		}
	}
}


int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d",&input);
		switch (input)
		{
			case 1:
				printf("正在初始化\n");
				game();
				break;
			case 0:
				printf("正在退出游戏\n");
				break;
			default:
				printf("选择错误,请从新选择\n");
				break;
		}
	} while (input);
	return 0;
} 

2、头文件

        通过改变头文件中定义的三个值,可以改变棋盘的长宽(不过建议这两个值保持一致,后面写的时候有点写糊涂了,两个值不一样可能导致函数出错)和获胜条件(五子相连)。

#define ROW 21 
#define COL 21
#define N 5
 
//初始化棋盘 
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘 
void DisplayBoard(char board[ROW][COL],int row,int col);
//player1下棋 
void Player1Move(char board[ROW][COL],int row,int col); 
// player2下棋
void Player2Move(char board[ROW][COL],int row,int col); 
//确认是否游戏结束 
bool Check1Done(char board[ROW][COL],int row,int col);
bool Check2Done(char board[ROW][COL],int row,int col);

3、函数文件

从上到下函数依次为:

1、清空棋盘(二维数组)

2、展示棋盘(输出二维数组)

3 4、玩家1、2落子(我把鹏哥的电脑做成了玩家2,由于要区分*和#所以写了两个)

5 6、检测玩家1、2是否达成胜利条件(两个函数,原因同上),四个循环嵌套,分别扫描行列和左斜、右斜

#include "game.h"
#include <stdio.h>
#include <iostream>
using namespace  std;
void InitBoard(char board[ROW][COL],int row,int col)
{
	int i = 0;
	int j = 0;
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			board[i][j]=' ';
		}
	} 
}

void DisplayBoard(char board[ROW][COL],int row,int col)
{
	int i = 0;
	for(i=0;i<row;i++)
	{
		int j = 0;
		for(j=0;j<col;j++)
		{
			printf(" %c ",board[i][j]);
			if(j<col-1)
				printf("|");
		} 
		printf("\n");
		if(i<row-1)
		{
			for(j=0;j<col;j++)
			{
				printf("---");
				if(j<col-1)
					printf("|");	 
			}
			printf("\n");
		}
			
	} 
}

void Player1Move(char board[ROW][COL],int row,int col)
{
	int x = 0;
	int y = 0;
	while(1)
	{
		printf("玩家1走>\n");
		//printf("输入样例<num> <num>\n");
		printf("请输入下棋坐标:>\n");
		//scanf("%d %d,&x,&y");
		cout<<"x=";
		cin>>x;
		cout<<"y=";
		cin>>y;
		cout<<endl;
		if((x>=1)&&(x<=row)&&(y>=1)&&(y<=col))
		{
			if(board[x-1][y-1]==' ')
			{
				board[x-1][y-1]='*';
				break;
			} 
			else
			{
				printf("坐标被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}	
	}
}

void Player2Move(char board[ROW][COL],int row,int col)
{
	int x = 0;
	int y = 0;
	
	while(1)
	{
		printf("玩家2走>\n");
		//printf("输入样例<num>*<num>\n");
		printf("请输入下棋坐标:>\n");
		//scanf("%d*%d,&x,&y");
		cout<<"x=";
		cin>>x;
		cout<<"y=";
		cin>>y;
		cout<<endl;
		if((x>=1)&&(x<=row)&&(y>=1)&&(y<=col))
		{
			if(board[x-1][y-1]==' ')
			{
				board[x-1][y-1]='#';
				break;
			}
			else
			{
				printf("坐标被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

bool Check1Done(char board[ROW][COL],int row,int col)
{
	for(int i=0;i<ROW;i++)
	{
		int count = 0;
		for(int j=0;j<COL;j++)
		{
			if(board[i][j]=='*')
			{
				count++;
				if(count==N)
				{
					return(1);
				}
			}
			else
			{
				count = 0;
			}
		}
	} 
	for(int i=0;i<ROW;i++)
	{
		int count = 0;
		for(int j=0;j<COL;j++)
		{
			if(board[j][i]=='*')
			{
				count++;
				if(count==N)
				{
					return(1);
				}
			}
			else
			{
				count = 0;
			}
		}
	}
	for(int i=-ROW+1;i<=ROW-1;i++)
	{
		int count = 0;
		for(int j=0;j<ROW;j++)
		{
			if((i+j>=0)&&(i+j<ROW)) 
			{
				if(board[i+j][j]=='*')
				{
					count++;
					if(count==N)
					{
						return(1); 
					} 
				}
				else
				{
					count = 0;
				}
			}
		}
	}
	for(int i=0;i<(2*ROW-1);i++)
	{
		int count = 0;
		for(int j=0;j<COL;j++)
		{
			if((i-j>=0)&&(i-j<ROW))
			{
				if(board[i-j][j]=='*')
				{
					count++;
					if(count==N)
					{
						return(1);
					}
				}
				else
				{
					count = 0;
				}
			}
		}
	}
	return(0);
} 

bool Check2Done(char board[ROW][COL],int row,int col)
{
	for(int i=0;i<ROW;i++)
	{
		int count = 0;
		for(int j=0;j<COL;j++)
		{
			if(board[i][j]=='#')
			{
				count++;
				if(count==N)
				{
					return(1);
				}
			} 
			else
			{
				count = 0;
			}
		}
	}
	for(int i=0;i<ROW;i++)
	{
		int count = 0;
		for(int j=0;j<COL;j++)
		{
			if(board[j][i]=='#')
			{
				count++;
				if(count==N)
				{
					return(1);
				}
			} 
			else
			{
				count = 0;
			}
		}
	}
	for(int i=-ROW+1;i<=ROW-1;i++)
	{
		int count = 0;
		for(int j=0;j<ROW;j++)
		{
			if((i+j>=0)&&(i+j<ROW)) 
			{
				if(board[i+j][j]=='#')
				{
					count++;
					if(count==N)
					{
						return(1); 
					} 
				}
				else
				{
					count = 0;
				}
			}
		}
	}
	for(int i=0;i<(2*ROW-1);i++)
	{
		int count = 0;
		for(int j=0;j<COL;j++)
		{
			if((i-j>=0)&&(i-j<ROW))
			{
				if(board[i-j][j]=='N')
				{
					count++;
					if(count==N)
					{
						return(1);
					}
				}
				else
				{
					count = 0;
				}
			}
		}
	}
	return(0);  
} 


三、编写时出现的问题

        由于最开始的底层逻辑并不是由本人搭建的,在实现函数5、6时不得不采取全程扫描的方法,浪费了很多算力,如果能输入上一落子的类型和坐标,就能将5、6合并,去除循环嵌套并直接进行米字型计数,然而没有实现,这是很可惜的一点。

总结

这是我第一次编写项目,主要还是熟悉各种文件类型和编写范式,跨文件调用方法,以及编写项目的大局观、思考方式。总的来说,是一次非常值得的尝试。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值