基本规则
(1)对局双方各执一色棋子。
(2)空棋盘开局。
(3)黑先、白后,交替下子,每次只能下一子。
(4)棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
(5)黑方的第一枚棋子可下在棋盘任意交叉点上。
(6)轮流下子是双方的权利,但允许任何一方放弃下子权(即:PASS权)
//五子棋对局,执行黑方指定开局、三手可交换、五手两打的规定。整个对局过程中黑方有禁手,白方无禁手。
//黑方禁手有三三禁手、四四禁手和长连禁手三种。
重点
- 先弄个棋盘,决定用string类数组。
- 一个用于落子的函数
- 一个显示棋盘目前状况的函数
- 一个判断输赢的函数
- 一个可以重复落子的结构,这里打算用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 + " ";
}
因为格子里是两个空格,只放棋子看起来棋子会偏向一侧,所以我微调了之前的空棋盘,把“|”改成了“| ”,然后把棋子后面加了个空格,保证了棋子在格子中间。
效果如图:
判断输赢
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;
}