C++之简单五子棋的语言设计实现

算法思路在上一篇[C++之简单五子棋的设计思路](http://blog.csdn.net/black_kyatu/article/details/79293392)中描述的较为清晰了。接下来则是设计数据类型和语言实现部分。

类及类的实现

#ifndef RENJU_H
#define RENJU_H
#include <iostream>
#include <windows.h>
#include <string>
#define hor 7
#define ver 4
using namespace std;


//用于记录坐标
struct  position
{
	int x;
	int y;
	position()
	{
		x = 0;
		y = 0;
	}
	position(int a,int b)
	{
		x = a;
		y = b;
	}
};


//用于记录棋子颜色和节点状态
enum state
{
	blank=0,black=1,white=2


};


//用于存储棋局分析信息:未完赛,犯规,平局,黑方胜,白方胜
enum result
{
	go_on,error,draw,black_win,white_win
};


// 设置光标
void setpos(COORD a)   
{
	HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(out, a);
}


// 设置光标
void setpos(int i, int j)
{
	COORD pos = { i, j };
	setpos(pos);
}


//绘图函数,用于在指定坐标输出指定字符
inline void gps(int x,int y,char c)
{
	setpos(y,x);
	cout<<c;
}


//绘图函数,用于在指定坐标输出整数
inline void  gps(int x,int y,int i)
{
	setpos(y,x);
	if(i>=10)
		cout<<i;
	else
		cout<<0<<i;
}


//绘图函数,用于在指定坐标输出字符串
inline void  gps(int x,int y,string s)
{
	setpos(y,x);
	cout<<s;
}


//绘图函数,用于在给定坐标打印棋盘中的一格
void tab(int x,int y,state str)
{
	string s;
	switch (str)
	{
	case blank:
		s="  ";	
		break;
	case black:
		s="黑";
		break;
	case white:
		s="白";
		break;
	default:
		break;
	}
	setpos(y,x);
	cout<<" ------ ";
	setpos(y,x+1);
	cout<<"|      |";
	setpos(y,x+2);
	cout<<"|  "<<s<<"  |";
	setpos(y,x+3);
	cout<<"|      |";
	setpos(y,x+4);
	cout<<" ------ ";
}


//查找最大值
int MAX(const int *a,int n)
{
	int max = a[0];
	for(int i =1; i < n ;i++)
	{
		if(a[i] > max)
			max = a[i];
	}
	return max;
}


//检测是否符合胜利条件


//棋子类
class chess
{
public:
	inline chess(int x=0,int y=0,state c=blank)
	{ point.x=x,point.y=y;
		color=c;
	};
	inline chess(chess &ch) 
	{ point=ch.drop_point();
		color=ch.get_color();
	}
	~chess(){};
	struct position drop_point()const;//用于向外部提供棋子位置
	inline state get_color() const { return color;}//提供棋子颜色信息
	void set_point();//用于从外部获取棋子位置
	void set_point(int x,int y){ point.x=x,point.y=y;}
	void set_point(position p){ point.x=p.x,point.y=p.y;}
	void set_color(state c){ color=c;}//设置棋子颜色
private:
		position point;
		enum state color;
	};


position chess::drop_point()const
{
	return point;		
}
		
void chess::set_point()
{
	if(color==black)
	{
		setpos(110,1);
		cout<<"请黑方输入落子列数和行数,空格隔开:";
		cin>>point.x>>point.y;
		while(point.x<1||point.x>15)
		{
			setpos(110,1);
			cout<<"列数输入超出范围,请重新输入1~15之间数字      ";
			cin>>point.x;
		}
		while(point.y<1||point.y>15)
		{
			setpos(110,2);
			cout<<"行数输入超出范围,请重新输入1~15之间数字    ";
			cin>>point.y;
		}
	}
	else if(color==white)
	{
		setpos(110,1);
		cout<<"请白方输入落子列数和行数,空格隔开:";
		cin>>point.x>>point.y;
		while(point.x<1||point.x>15)
		{
			setpos(110,1);
			cout<<"列数输入超出范围,请重新输入1~15之间数字      ";
			cin>>point.x;
		}
		while(point.y<1||point.y>15)
		{
			setpos(110,2);
			cout<<"行数输入超出范围,请重新输入1~15之间数字    ";
			cin>>point.y;
		}
	}
	point.x--;
	point.y--;
}


//棋盘类
class chessboard
{
public:
	chessboard()
	{
		for(int i=0;i<15;i++)
			for(int j=0;j<15;j++)
			{
				square[i][j]=blank;
			}
	}
	chessboard(chessboard *cb)
	{
		for(int i=0;i<15;i++)
			for(int j=0;j<15;j++)
			{
				square[i][j]=cb->viewboard(i,j);
			}
	}
	inline state viewboard(position p_c) const;//接收坐标,返回该位置的状态
	inline state viewboard(int x,int y) const;//接收整数坐标,返回该位置的状态
	void update(chess ch);//接收新棋子,更新棋盘状态
	void display()const;//向外输出棋盘状态
	result judge(chess ch)const;//规则函数,判断走棋是否犯规和输赢
	void clear()//清空棋盘
		{
			for(int i=0;i<15;i++)
			for(int j=0;j<15;j++)
			{
				square[i][j]=blank;
			}
	}
private:
	state square[15][15];
};
int check_five(chessboard bd,chess ch)
{
	position ori=ch.drop_point();
	int count=1;//计数器,统计同色个数
	int sum[4]={0};
	bool locked=0;//逻辑标记量,用来标记是否遇到了非同色节点
	//水平方向检测
	for(int i=0,locked=0;i<5&&((ori.x-i)>=0)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x-i,ori.y))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[0]=count-1;
	for(int i=0,locked=0;i<5&&((ori.x+i)<=14)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x+i,ori.y))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[1]=count-sum[0]-2;
	sum[0]=count;
	if(count>=5)
		return count;
	//竖直方向检测
	count=1;
	for(int i=0,locked=0;i<5&&((ori.y-i)>=0)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x,ori.y-i))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[2]=count-1;
	for(int i=0,locked=0;i<5&&((ori.y+i)<=14)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x,ori.y+i))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[3]=count-sum[2]-2;
	sum[1]=count;
	if(count>=5)
		return count;
	//左上到右下斜向检测
	count=1;
	for(int i=0,locked=0;i<5&&((ori.y-i)>=0)&&((ori.x-i)>=0)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x-i,ori.y-i))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[4]=count-1;
	for(int i=0,locked=0;i<5&&((ori.x+i)<=14)&&((ori.y+i)<=14)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x+i,ori.y+i))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[5]=count-sum[4]-2;
	sum[2]=count;
	if(count>=5)
		return count;
	//左下到右上斜向检测
	count=1;
	for(int i=0,locked=0;i<5&&((ori.y+i)<=14)&&((ori.x-i)>=0)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x-i,ori.y+i))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[6]=count-1;
	for(int i=0,locked=0;i<5&&((ori.x+i)<=14)&&((ori.y-i)>=0)&&(!locked);i++)//终止循环条件:同色超过4个或触碰到棋盘边界或遇到非同色节点
		if(ch.get_color()==bd.viewboard(ori.x+i,ori.y-i))
			count++;
		else
			if(i!=0)
			locked=1;
	//sum[7]=count-sum[6]-2;
	sum[3]=count;
	if(count>=5)
		return count;
	return MAX(sum,4);
}


state chessboard::viewboard(position p_c) const
{
	return square[p_c.x][p_c.y];
}
state chessboard::viewboard(int x,int y) const
{
	return square[x][y];
}
void chessboard::update(chess ch)
{
	position pos=ch.drop_point();
	square[pos.x][pos.y]=ch.get_color();
}


void chessboard::display()const
{
	system("cls");


	for(int i=0;i<15;i++)//打印列坐标说明
	{
		gps(0,6+i*hor,i+1);
	}
	for(int i=0;i<15;i++)//打印列坐标说明
	{
		gps(16*ver,6+i*hor,i+1);
	}
	for(int i=0;i<15;i++)//打印行坐标说明
	{
		gps(3+i*ver,1,i+1);
	}
		for(int i=0;i<15;i++)//打印行坐标说明
	{
		gps(3+i*ver,1+16*hor,i+1);
	}
	for(int i=0,j=0;i<15;i++)
	{
		for(j=0;j<15;j++)
			tab(1+i*ver,3+hor*j,square[j][i]);
	}
	cout<<endl;
}
result chessboard::judge(chess set)const
{
	bool full=1;
	if(viewboard(set.drop_point())!=blank)
	{
		return error;
	}


	if(check_five(*this,set)>=5&&(set.get_color()==black))
		return black_win;


	if(check_five(*this,set)>=5&&(set.get_color()==white))
		return white_win;


	for(int i=0;i<15;i++)
		for(int j=0;j<15;j++)
		{
			if(square[i][j]==blank)	
				full=0;
		}
	if(full==1)
		return draw;
	else
		return go_on;
}
#endif



主函数,应该再定义game类进行优化,不过设计的时候没有考虑周全,还是按照C的思想写了。

#include "renju.h"
#include "ai.h"
#include <stdlib.h>


int main()
{
	system("mode con cols=150 lines=150 ");
	system("color 27");
	chessboard bd;
	chess now;
	result final;
	int mode;
	gps(5,40,"==============欢迎使用简易五子棋!==============");
	gps(10,50,">>>>输入1或2进行模式选择<<<<");
	gps(11,50,"     <1> 双人对战 ");
	gps(12,50,"     <2> 人机对战 ");
	do{
		cout<<endl<<"                                  input mode:";
		cin>>mode;
	}while(mode != 1 && mode != 2);
	
	//双人对战
	if (mode==1)
	{
loop1:	now.set_color(black);//执黑先行
		bd.clear();
		bd.display();		//初始化棋盘
		setpos(110,0);
		cout<<"对局开始,黑旗先行";
		//循环判断上一次落子结果,收集下一次输入,直到棋局出结果
		do{	
		now.set_point();//输入
		final=bd.judge(now);
		//判断是否违规
		while(final==error)//犯规输入则重新输入
		{
			system("cls");
			bd.display();
			setpos(110,10);
			cout<<"犯规(输入坐标已有棋子)!";
			now.set_point();
			final=bd.judge(now);
		}
		//正确落子后更新棋盘
		bd.update(now);
		bd.display();
		//反转下一步走棋的颜色
		if(now.get_color()==black)
				now.set_color(white);
			else
				now.set_color(black);
		
		}while(final==go_on);
		switch (final)
		{
		case go_on:
			break;
		case error:
			break;
		case draw:
			setpos(110,10);
			cout<<"平局:游戏结束";
			break;
		case black_win:
			setpos(110,10);
			cout<<"黑旗获胜:游戏结束";
			break;
		case white_win:
			setpos(110,10);
			cout<<"白旗获胜:游戏结束";
			break;
		default:
			break;
		}
		setpos(110,11);
		cout<<"是否继续下一局?Y/N";
		char flag;
		cin>>flag;
		if(flag == 'Y')
			goto loop1;
	}
	if(mode == 2)
	{
		chess ai_ch;
		system("cls");
		gps(5,40,"==============欢迎使用简易五子棋!==============");
		gps(10,50,">>>>输入1或2进行模式选择<<<<");
		gps(11,50,"     <1> 执黑先行 ");
		gps(12,50,"     <2> 执白后行 ");
		do{
			cout<<endl<<"                                  input mode:";
			cin>>mode;
		}while(mode != 1 && mode != 2);
		if(mode == 1)
		{
loop2:		now.set_color(black);//执黑先行
			bd.clear();
			bd.display();		//初始化棋盘
			Ai afago(bd,white);
			setpos(110,0);
			cout<<"对局开始,请您落子";
			now.set_point();
			bd.update(now);
			ai_ch.set_color(white);
			ai_ch.set_point(left(now.drop_point(),false));
			bd.update(ai_ch);
			bd.display();
			//循环判断上一次落子结果,收集下一次输入,直到棋局出结果
			do{	
				now.set_point();//输入
				final=bd.judge(now);
				//判断是否违规
				while(final==error)//犯规输入则重新输入
				{
					system("cls");
					bd.display();
					setpos(110,10);
					cout<<"犯规(输入坐标已有棋子)!";
					now.set_point();
					final=bd.judge(now);
				}
				//正确落子后更新棋盘
				bd.update(now);
				if(final != black_win)
				{
					ai_ch=afago.set_chess();
					final=bd.judge(ai_ch);
					bd.update(ai_ch);
					bd.display();
				}else{bd.display();}
				}while(final==go_on);
			switch (final)
			{
				case go_on:
					break;
				case error:
					break;
				case draw:
					setpos(110,10);
					cout<<"平局:游戏结束";
					break;
				case black_win:
					setpos(110,10);
					cout<<"恭喜您棋艺高超,战胜了AI:游戏结束";
					break;
				case white_win:
					setpos(110,10);
					cout<<"电脑获胜,请继续努力提高自己:游戏结束";
					break;
				default:
					break;
			}
			setpos(110,11);
			cout<<"是否继续下一局?Y/N";
			char flag;
			cin>>flag;
			if(flag=='Y')
				goto loop2;
		}
		if(mode == 2)
		{
loop3:		ai_ch.set_color(black);//AI执黑先行
			now.set_color(white);
			bd.clear();	//初始化棋盘
			Ai afago(bd,black);
			ai_ch.set_point(7,7);
			bd.update(ai_ch);
			bd.display();	
			setpos(110,0);
			cout<<"对局开始,请您落子";
			//循环判断上一次落子结果,收集下一次输入,直到棋局出结果
			do{	
				now.set_point();//输入
				final=bd.judge(now);
				//判断是否违规
				while(final==error)//犯规输入则重新输入
				{
					system("cls");
					bd.display();
					setpos(110,10);
					cout<<"犯规(输入坐标已有棋子)!";
					now.set_point();
					final=bd.judge(now);
				}
				//正确落子后更新棋盘
				bd.update(now);
				if(final != white_win)
				{
				ai_ch=afago.set_chess();
				final=bd.judge(ai_ch);
				bd.update(ai_ch);
				bd.display();
				}else{bd.display();}
				}while(final==go_on);
			switch (final)
			{
				case go_on:
					break;
				case error:
					break;
				case draw:
					setpos(110,10);
					cout<<"平局:游戏结束";
					break;
				case white_win:
					setpos(110,10);
					cout<<"恭喜您棋艺高超,战胜了AI:游戏结束";
					break;
				case black_win:
					setpos(110,10);
					cout<<"电脑获胜,请继续努力提高自己:游戏结束";
					break;
				default:
					break;
			}
			setpos(110,11);
			cout<<"是否继续下一局?Y/N";
			char flag;
			cin>>flag;
			if(flag=='Y')
				goto loop3;
		}
	}
		return 0;
	
}


AI算法待后续补全


猜你喜欢

转载自blog.csdn.net/black_kyatu/article/details/79327680
今日推荐