C++编程练习——五子棋游戏

基本规则

(1)对局双方各执一色棋子。
(2)空棋盘开局。
(3)黑先、白后,交替下子,每次只能下一子。
(4)棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
(5)黑方的第一枚棋子可下在棋盘任意交叉点上。
(6)轮流下子是双方的权利,但允许任何一方放弃下子权(即:PASS权)
//五子棋对局,执行黑方指定开局、三手可交换、五手两打的规定。整个对局过程中黑方有禁手,白方无禁手。
//黑方禁手有三三禁手、四四禁手和长连禁手三种。

重点

  1. 先弄个棋盘,决定用string类数组。
  2. 一个用于落子的函数
  3. 一个显示棋盘目前状况的函数
  4. 一个判断输赢的函数
  5. 一个可以重复落子的结构,这里打算用while,后由于判断输赢的需要改成do while

基本准备

#include<iostream>
#include<stdlib.h>
using namespace std;
#define X  15//棋盘大小
string qizi_1 = "X";//黑方
string qizi_2 = "O";//白方
string qipan[X*2+4][X*2+4];
int i = 0;//循环变量
int j = 0;//循环变量

棋盘

void xian_shi_qi_pan()//显示棋盘
{
	for (j = 1; j <= X*2+2; j++)
	{
		for (i = 1; i <= X*2+2; i++)
		{
			cout << qipan[i][j];
		}
		cout << endl;
	}
}
void fang_ge_qi_pang()//放个棋盘
{
	for (j = 1; j <= X * 2 + 2; j++)
	{
		for (i = 1; i <= X * 2 + 2; i++)
		{
			qipan[i][j] = "  ";
		}
	}
	for (j = 1; j <= X * 2 + 2; j++)//棋盘初始化
	{
		for (i = 1; i <= X * 2 + 2; i++)
		{
			if (j % 2 == 1&&j<=X*2+2&&i<=X*2) qipan[i][j] = "—";
			if (i % 2 == 1 && j % 2 == 0&&i<=X*2+2&&j<=X*2+1) qipan[i][j] = "| ";
			
		}
	}
	xian_shi_qi_pan();
}

这里棋盘上不能只有棋子,要有格子,我使用了“|”和“—”,用Excel表格模拟应该是这样的:
![(https://img-blog.csdnimg.cn/9ca24d27062845bcbf1f617dc10a0e33.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA56CB5Luj56CB5L2_5oiR5b-r5LmQ,size_20,color_FFFFFF,t_70,g_se,x_16)

棋盘模拟
上面的格子,浅蓝色应该是“—”深蓝色应该是“|”,灰色的格子在最初应该是两个空格,同时在这个图右侧和下侧都没有封口,写函数的时候应该注意多一个if语句补上。

最终在黑框中的效果:
黑框的效果

落子

void fang_ge_qi_zi(int x0,int y0,string& qizi)//放置棋子
{
	if (x0 == 0 && y0 == 0) return;//按照提示输入0 0 即此轮弃权,没有落子
	qipan[x0][y0] = qizi + " ";
}

因为格子里是两个空格,只放棋子看起来棋子会偏向一侧,所以我微调了之前的空棋盘,把“|”改成了“| ”,然后把棋子后面加了个空格,保证了棋子在格子中间。
效果如图:
效果1

判断输赢

bool pan_duan_shu_yin(string& qizi)//输入棋子,判断此棋子持有方是否赢了
{
	for (i = 2; i <= X * 2; i += 2)
	{
		for (j = 2; j <= X * 2; j += 2)
		{
			if (qipan[i][j] == qipan[i + 2][j] &&
				qipan[i][j] == qipan[i + 4][j] &&
				qipan[i][j] == qipan[i + 6][j] &&
				qipan[i][j] == qipan[i + 8][j] &&
				qipan[i][j] == qizi+" ")
				return true;
			if (qipan[i][j] == qipan[i + 2][j] &&
				qipan[i][j] == qipan[i + 4][j] &&
				qipan[i][j] == qipan[i + 6][j] &&
				qipan[i][j] == qipan[i + 8][j] &&
				qipan[i][j] == qizi + " ")
				return true;
			if (qipan[i][j] == qipan[i + 2][j+2] &&
				qipan[i][j] == qipan[i + 4][j+4] &&
				qipan[i][j] == qipan[i + 6][j+6] &&
				qipan[i][j] == qipan[i + 8][j+8] &&
				qipan[i][j] == qizi + " ")
				return true;
		}
	}
	return false;
}

暂时没想出更好的办法,如果要这样遍历完数组的话如果棋盘很大的话就慢了,现在是15*15暂时不用担心。这个方法应该也可以进一步精简,比如如果这个格子是空的就直接跳过。

判断落子是否有效

bool shi_fou_you_xiao(int x, int y)//检查落子是否有效,有没有重叠,有没有落到棋盘外面
{
	if (qipan[x][y] != "  "&& !(x==0&&y==0))//要排除掉0 0 弃权的行为
	{
		cout << "你的落子无效" << endl;
		return false;
	}
	if (x > X * 2+1 || x < 0 || y>X * 2+1 || y < 0)
	{
		cout << "你的落子在棋盘外" << endl;
		return false;
	}
	return true;
}

主函数

int main()
{
	int change = 1;
	while (change)
	{
		cout << "****************************************************************" << endl;
		cout << "**************请选择游戏****************************************" << endl;
		cout << "**************0.退出********************************************" << endl;
		cout << "**************1.电脑vs玩家**************************************" << endl;
		cout << "**************2.玩家vs玩家**************************************" << endl;
		cin >> change;
		switch (change)
		{
			case 1:break;
			case 2:
			{
				int x1, x2, y1, y2;
				fang_ge_qi_pang();
				cout << "游戏开始!" << endl;
				do
				{
					cout << "请玩家1(黑子方)输入棋子坐标:(输入0 0即为此轮弃权没有落子)" << endl;
					cin >> x1 >> y1;//这个坐标是第x1行第y1列,所以下面对应的二维数组下标要反过来
					while (!shi_fou_you_xiao(y1 * 2, x1 * 2))//判断落子是否有效
					{
						cout << "请重新输入坐标:" << endl;
						cin >> x1 >> y1;
					}
					system("cls");
					fang_ge_qi_zi(y1 * 2, x1 * 2, qizi_1);
					xian_shi_qi_pan();
					if (pan_duan_shu_yin(qizi_1))
					{
						cout << "游戏已结束,黑方胜" << endl;
						break;//下完就判断,如果胜负已定就不需要继续下了
					}
					cout << "请玩家2(白子方)输入棋子坐标:(输入0 0即为此轮弃权没有落子)" << endl;
					cin >> x2 >> y2;//这个坐标是第x2行第y2列,所以下面对应的二维数组下标要反过来
					while (!shi_fou_you_xiao(y2 * 2, x2 * 2))
					{
						cout << "请重新输入坐标:" << endl;
						cin >> x2 >> y2;
					}
					system("cls");
					fang_ge_qi_zi(y2 * 2, x2 * 2, qizi_2);
					xian_shi_qi_pan();
					if (pan_duan_shu_yin(qizi_2))
					{
						cout << "游戏已结束,白方胜" << endl;
						break;//下完就判断,如果胜负已定就不需要继续下了
					}
				} while ((!pan_duan_shu_yin(qizi_1) == 1 || !pan_duan_shu_yin(qizi_2)));
			}
			case 0: break;
		}
	}
	
	system("pause");
	return 0;
}

这里只有玩家vs玩家,电脑怎么下还没想好……

第一版 只有玩家vs玩家,有清屏,黑框

全部代码如下:

//(1)对局双方各执一色棋子。
//(2)空棋盘开局。
//(3)黑先、白后,交替下子,每次只能下一子。
//(4)棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
//(5)黑方的第一枚棋子可下在棋盘任意交叉点上。
//(6)轮流下子是双方的权利,但允许任何一方放弃下子权(即:PASS权)
//五子棋对局,执行黑方指定开局、三手可交换、五手两打的规定。整个对局过程中黑方有禁手,白方无禁手。
//黑方禁手有三三禁手、四四禁手和长连禁手三种。
#include<iostream>
#include<stdlib.h>
using namespace std;
#define X  16
string qizi_1 = "X";//黑方
string qizi_2 = "O";//白方
string qipan[X*2+4][X*2+4];
int i = 0;
int j = 0;
void xian_shi_qi_pan()
{
	for (j = 1; j <= X*2+2; j++)
	{
		for (i = 1; i <= X*2+2; i++)
		{
			cout << qipan[i][j];
		}
		cout << endl;
	}
}
void fang_ge_qi_pang()//放个棋盘
{
	for (j = 1; j <= X * 2 + 2; j++)
	{
		for (i = 1; i <= X * 2 + 2; i++)
		{
			qipan[i][j] = "  ";
		}
	}
	for (j = 1; j <= X * 2 + 2; j++)//棋盘初始化
	{
		for (i = 1; i <= X * 2 + 2; i++)
		{
			if (j % 2 == 1&&j<=X*2+2&&i<=X*2) qipan[i][j] = "—";
			if (i % 2 == 1 && j % 2 == 0&&i<=X*2+2&&j<=X*2+1) qipan[i][j] = "| ";
			
		}
	}
	xian_shi_qi_pan();
}
void fang_ge_qi_zi(int x0,int y0,string& qizi)//放置棋子
{
	if (x0 == 0 && y0 == 0) return;//按照提示输入0 0 即此轮弃权,没有落子
	qipan[x0][y0] = qizi + " ";
}
bool pan_duan_shu_yin(string& qizi)//输入棋子,判断此棋子持有方是否赢了
{
	for (i = 2; i <= X * 2; i += 2)
	{
		for (j = 2; j <= X * 2; j += 2)
		{
			if (qipan[i][j] == qipan[i + 2][j] &&
				qipan[i][j] == qipan[i + 4][j] &&
				qipan[i][j] == qipan[i + 6][j] &&
				qipan[i][j] == qipan[i + 8][j] &&
				qipan[i][j] == qizi+" ")
				return true;
			if (qipan[i][j] == qipan[i + 2][j] &&
				qipan[i][j] == qipan[i + 4][j] &&
				qipan[i][j] == qipan[i + 6][j] &&
				qipan[i][j] == qipan[i + 8][j] &&
				qipan[i][j] == qizi + " ")
				return true;
			if (qipan[i][j] == qipan[i + 2][j+2] &&
				qipan[i][j] == qipan[i + 4][j+4] &&
				qipan[i][j] == qipan[i + 6][j+6] &&
				qipan[i][j] == qipan[i + 8][j+8] &&
				qipan[i][j] == qizi + " ")
				return true;
		}
	}
	return false;
}
bool shi_fou_you_xiao(int x, int y)//检查落子是否有效,有没有重叠,有没有落到棋盘外面
{
	if (qipan[x][y] != "  "&& !(x==0&&y==0))
	{
		cout << "你的落子无效" << endl;
		return false;
	}
	if (x > X * 2+1 || x < 0 || y>X * 2+1 || y < 0)
	{
		cout << "你的落子在棋盘外" << endl;
		return false;
	}
	return true;
}
int main()
{
	int change = 1;
	while (change)
	{
		cout << "****************************************************************" << endl;
		cout << "**************请选择游戏****************************************" << endl;
		cout << "**************0.退出********************************************" << endl;
		cout << "**************1.电脑vs玩家**************************************" << endl;
		cout << "**************2.玩家vs玩家**************************************" << endl;
		cin >> change;
		switch (change)
		{
			case 1:break;
			case 2:
			{
				int x1, x2, y1, y2;
				fang_ge_qi_pang();
				cout << "游戏开始!" << endl;
				do
				{
					cout << "请玩家1(黑子方)输入棋子坐标:(输入0 0即为此轮弃权没有落子)" << endl;
					cin >> x1 >> y1;//这个坐标是第x1行第y1列,所以下面对应的二维数组下标要反过来
					while (!shi_fou_you_xiao(y1 * 2, x1 * 2))//判断落子是否有效
					{
						cout << "请重新输入坐标:" << endl;
						cin >> x1 >> y1;
					}
					system("cls");
					fang_ge_qi_zi(y1 * 2, x1 * 2, qizi_1);
					xian_shi_qi_pan();
					if (pan_duan_shu_yin(qizi_1))
					{
						cout << "游戏已结束,黑方胜" << endl;
						break;//下完就判断,如果胜负已定就不需要继续下了
					}
					cout << "请玩家2(白子方)输入棋子坐标:(输入0 0即为此轮弃权没有落子)" << endl;
					cin >> x2 >> y2;//这个坐标是第x2行第y2列,所以下面对应的二维数组下标要反过来
					while (!shi_fou_you_xiao(y2 * 2, x2 * 2))
					{
						cout << "请重新输入坐标:" << endl;
						cin >> x2 >> y2;
					}
					system("cls");
					fang_ge_qi_zi(y2 * 2, x2 * 2, qizi_2);
					xian_shi_qi_pan();
					if (pan_duan_shu_yin(qizi_2))
					{
						cout << "游戏已结束,白方胜" << endl;
						break;//下完就判断,如果胜负已定就不需要继续下了
					}
				} while ((!pan_duan_shu_yin(qizi_1) == 1 || !pan_duan_shu_yin(qizi_2)));
			}
			case 0: break;
		}
	}
	
	system("pause");
	return 0;
}


  • 10
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
c++编写的五子棋游戏 // Five.cpp: implementation of the CFive class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "gobang.h" #include "Five.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif BOOL debugqian = false; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CFive::CFive() { } CFive::~CFive() { } BOOL CFive::has_five(int color) { //color = 1表示黑子,color = 2表示白子 //判断是否出现了5个子想连的情况 int m,n,i,j; for(m=1;m<16;m++) for(n=1;n<16;n++) { if(points[m][n]==color) { int p=1,s=1,zx=1,yx=1; for( i=1;i<5;i++) {if(n-i>=0&&points[m][n-i]==color) p++; else break; } for( i=1;i<5;i++) { if(n+i<16&&points[m][n+i]==color) p++; else break; } for( i=1;i<5;i++) { if(m-i>=0&&points[m-i][n]==color) s++; else break; } for( i=1;i<5;i++) { if(m+i<16&&points[m+i][n]==color) s++; else break; } for( i=1;i<5;i++) { if(m-i>=0&&n+i<16&&points[m-i][n+i]==color) zx++; else break; } for( i=1;i<5;i++) { if(n-i>=0&&m+i<16&&points[m+i][n-i]==color) zx++; else break; } for( i=1;i<5;i++) { if(m-i>=0&&n-i>=0&&points[m-i][n-i]==color) yx++; else break; } for( i=1;i<5;i++) { if(m+i<16&&n+i<16&&points[m+i][n+i]==color) yx++; else break; } if(p>=5||s>=5||zx>=5||yx>=5) return true; } } return false; } void CFive::Clear() { int i,j; for(i=1;i<=15;i++) for(j=1;j<=15;j++) { points[i][j] = 0;//先清空 } }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值