C++小程序:五子棋

文章目录[x]
  1. 1:一.用2维数组控制棋盘。
  2. 1.1:1.初始化棋盘
  3. 1.2:2.实现下棋
  4. 2:
  5. 3:2.胜负判定

本章你将学到:

1.用2维数组控制棋盘。

2.胜负判定。

3.不败的人工智能。


一.用2维数组控制棋盘。

1.初始化棋盘

头文件及命名空间有这些

#include "stdafx.h"
#include"iostream"
using namespace std;

首先创建一个棋盘

我先弄个结构体来表示游戏整体

typedef struct
{
int map[5][5];  //map
int value = 0;
} game ;
我用一个结构体表示井字棋的一些状态。方便进行修改。
先初始化地图,我用了一个函数来初始化它。
void Initialize_Map(game* s)
{
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++) // 0=empty 1="●"  2="×"  3="■"
if (i == 0 || i == 4 || j == 0 || j == 4)
s->map[i][j] = 3;
else s->map[i][j] = 0;
}
依次遍历里面的元素,并给予赋值
我在这里用0表示可下地,1表示自己的棋,2表示电脑的棋
3为墙壁
遍历完为
33333
30003
30003
30003
33333
这样就对地图进行了初始化。
之后写个绘制地图的函数来依次将这些函数输出出来
void draw(game* s)
{
for (int i = 0; i < 5; i++)
{for (int j = 0; j < 5; j++)
switch (s->map[i][j])
{
case 1: cout << "●"; break;
case 2:  cout << "×"; break;
case 3:  cout << "■"; break;
case 0:cout << "o"; break;
}
cout << endl;
}
}
把这两个放在main函数调试看下
int  main()
{
game s;
Initialize_Map(&s);
draw(&s);
return 0;
}
ok。

2.实现下棋

之后我们来通过按键实现下棋。
首先要想下棋其实就是改变原先数组里的元素的值,之后通过draw函数重新绘制达到
下棋的目的。
我们来创建一个函数来实现玩家下棋。
void player(game* s)
{
int input;
cin >> input;
switch (input)
{
case 1: s->map[3][1] = 0 ? 1 : 0;  break;
case 2: s->map[3][2] = 0 ? 1 : 0;  break;
case 3: s->map[3][3] = 0 ? 1 : 0;  break;
case 4: s->map[2][1] = 0 ? 1 : 0;  break;
case 5: s->map[2][2] = 0 ? 1 : 0;  break;
case 6: s->map[2][3] = 0 ? 1 : 0;  break;
case 7: s->map[1][1] = 0 ? 1 : 0;  break;
case 8: s->map[1][2] = 0 ? 1 : 0;  break;
case 9: s->map[1][3] = 0 ? 1 : 0;  break;
}
}
我通过小键盘上的数字来对应棋盘的位置,之后通过小键盘上的输入值来确定
在哪下棋,即确定应该改变那个元素。
之后我定义了一个变量input来获取按键的值并作出判断。

2.胜负判定

判断胜负的条件很简单,一共有8种情况

横的有三个,竖的有三个,斜的有两个。

我们就分别判断。

第2段是电脑人的获胜条件

int win(game* s)
{
if (   s->map[1][1] == s->map[1][2] && s->map[1][1] == s->map[1][3] && s->map[1][1] == 1
|| (s->map[2][1] == s->map[2][2] && s->map[2][1] == s->map[2][3] && s->map[2][1] == 1 )
|| (s->map[3][1] == s->map[3][2] && s->map[3][1] == s->map[3][3] && s->map[3][1] == 1 )
|| (s->map[1][1] == s->map[2][1] && s->map[1][1] == s->map[3][1] && s->map[1][1] == 1 )
|| (s->map[1][2] == s->map[2][2] && s->map[1][2] == s->map[3][2] && s->map[1][2] == 1 )
|| (s->map[1][3] == s->map[2][3] && s->map[1][3] == s->map[3][3] && s->map[1][3] == 1 )
|| (s->map[1][1] == s->map[2][2] && s->map[1][1] == s->map[3][3] && s->map[1][1] == 1 )
|| (s->map[1][3] == s->map[2][2] && s->map[1][3] == s->map[3][1] && s->map[1][3] == 1 )
)
return 1;
if (
s->map[1][1] == s->map[1][2] &&s->map[1][1] == s->map[1][3] && s->map[1][1] == 2
|| (s->map[2][1] == s->map[2][2] && s->map[2][1] == s->map[2][3] && s->map[2][1] == 2 )
|| (s->map[3][1] == s->map[3][2] && s->map[3][1] == s->map[3][3] && s->map[3][1] == 2 )
|| (s->map[1][1] == s->map[2][1] && s->map[1][1] == s->map[3][1] && s->map[1][1] == 2 )
|| (s->map[1][2] == s->map[2][2] && s->map[1][2] == s->map[3][2] && s->map[1][2] == 2 )
|| (s->map[1][3] == s->map[2][3] && s->map[1][3] == s->map[3][3] && s->map[1][3] == 2 )
|| (s->map[1][1] == s->map[2][2] && s->map[1][1] == s->map[3][3] && s->map[1][1] == 2 )
|| (s->map[1][3] == s->map[2][2] &&s->map[1][3] == s->map[3][1] && s->map[1][3] == 2 )
)
return 2;
return 0;
}

这样只要有3个相同的数字连成1直线,竖线或斜线,就能返回值。通过返回的值来判断谁胜。

3.不败的人工智能。

我用一个函数来执行电脑的操作。

void robot(game* s)
{
//fight
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++) { if (s->map[i][j] == 0)
{
if (i == 1)
if (s->map[i + 1][j] == 2 && s->map[i + 2][j] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 2)
if (s->map[i + 1][j] == 2 && s->map[i - 1][j] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3)
if(s->map[i - 1][j] == 2 && s->map[i - 2][j] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 1)
if (s->map[i][j + 1] == 2 && s->map[i][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 2)
if (s->map[i][j + 1] == 2 && s->map[i][j - 1] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 3)
if (s->map[i][j - 1] == 2 && s->map[i][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }

if (i == 1 && j == 1 && s->map[i + 2][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3 && j == 3 && s->map[i - 2][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 1 && j == 3 && s->map[i + 2][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3 && j == 1 && s->map[i - 2][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
}
}

//defense
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++) { if (s->map[i][j] == 0)
{
if(i == 1)
if(s->map[i + 1][j] == 1 && s->map[i + 2][j] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if(i == 2)
if(s->map[i + 1][j] == 1 && s->map[i - 1][j] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3)
if (s->map[i - 1][j] == 1 && s->map[i - 2][j] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 1)
if( s->map[i][j + 1] == 1 && s->map[i][j + 2] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 2)
if (s->map[i][j + 1] == 1 && s->map[i][j - 1] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 3)
if (s->map[i][j - 1] == 1 && s->map[i][j - 2] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 1 && j == 1 && s->map[i + 2][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3 && j == 3 && s->map[i - 2][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 1 && j == 3 && s->map[i + 2][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3 && j == 1 && s->map[i - 2][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
}
}

//second

if ((s->map[1][2] == 1 || s->map[2][1] == 1) && s->map[1][1] == 0)
{
s->map[1][1] = 2; return;
}
if ((s->map[2][3] == 1 || s->map[3][2] == 1) && s->map[3][3] == 0)
{
s->map[3][3] = 2;  return;
}

if ((s->map[1][1] == 2 && s->map[2][1] == 1) ||

(s->map[3][3] == 2 && s->map[3][2] == 1))
{
if (s->map[1][3] == 0){s->map[1][3] = 2; return;}
}
if ((s->map[1][1] == 2 && s->map[1][2] == 1) ||

(s->map[3][3] == 2 && s->map[2][3] == 1))
{
if (s->map[3][1] == 0){s->map[3][1] = 2; return;}
}

for (int i=0; i < 5; i++)
for (int j=0; j < 5; j++) if (s->map[i][j] == 0&& s->map[2][2] == 2){ s->map[i][j] = 2;  return; }
s->map[2][2] = 2;
}

我们逐个解析一下
首先我们先写出战斗函数,即当2个连成一排或是一竖式时下第3个。
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++) { if (s->map[i][j] == 0)
{
if (i == 1)
if (s->map[i + 1][j] == 2 && s->map[i + 2][j] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (i == 2)
if (s->map[i + 1][j] == 2 && s->map[i - 1][j] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (i == 3)
if (s->map[i - 1][j] == 2 && s->map[i - 2][j] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (j == 1)
if (s->map[i][j + 1] == 2 && s->map[i][j + 2] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (j == 2)
if (s->map[i][j + 1] == 2 && s->map[i][j - 1] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (j == 3)
if (s->map[i][j - 1] == 2 && s->map[i][j - 2] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (i == 1 && j == 1 && s->map[i + 2][j + 2] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (i == 3 && j == 3 && s->map[i - 2][j - 2] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (i == 1 && j == 3 && s->map[i + 2][j - 2] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
if (i == 3 && j == 1 && s->map[i - 2][j + 2] == 2 && s->map[i][j] == 0){ s->map[i][j] = 2;  return; }
}
}

这段代码首先通过for循还找出数组元素里的值为0的元素(及空地
然后用if逐个判断这个空地的前后左右是否有棋子。换句话讲,就是下这里能不能获胜。
如果能的话就修改此数值为2。
之后到防御函数,即玩家将要赢的棋子堵上。
他的性质跟攻击的函数相同,只不过前后判断的是玩家的棋子,而不是自己的。
复制下来在判断条件将2修改为1即可。

//defense
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++) { if (s->map[i][j] == 0)
{
if (i == 1)
if (s->map[i + 1][j] == 1 && s->map[i + 2][j] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 2)
if (s->map[i + 1][j] == 1 && s->map[i - 1][j] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3)
if (s->map[i - 1][j] == 1 && s->map[i - 2][j] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 1)
if (s->map[i][j + 1] == 1 && s->map[i][j + 2] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 2)
if (s->map[i][j + 1] == 1 && s->map[i][j - 1] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (j == 3)
if (s->map[i][j - 1] == 1 && s->map[i][j - 2] == 1 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 1 && j == 1 && s->map[i + 2][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3 && j == 3 && s->map[i - 2][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 1 && j == 3 && s->map[i + 2][j - 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
if (i == 3 && j == 1 && s->map[i - 2][j + 2] == 2 && s->map[i][j] == 0)

{ s->map[i][j] = 2;  return; }
}
}

其它,即当攻击函数和防御函数的条件不满足时。而执行的下法。

这个算法是有技巧的

比如

当你下中间时

x

x o x

x

x只要下4个位置任何一个,都会输。不信?

比如

 

x  o

 

 

第2步

o

x  o

 

这个时候你要堵我

我就

o      o

x  o

x

这样子的话左下角和中间下哪都可以赢。

所以所以你不下那4个位置的话。那么这把基本就是平局了。

我的话就判定哪里有空位下哪。

如代码

//other

if ((s->map[1][2] == 1 || s->map[2][1] == 1) && s->map[1][1] == 0)
{
s->map[1][1] = 2; return;
}
if ((s->map[2][3] == 1 || s->map[3][2] == 1) && s->map[3][3] == 0)
{
s->map[3][3] = 2;  return;
}
if ((s->map[1][1] == 2 && s->map[2][1] == 1) ||
(s->map[3][3] == 2 && s->map[3][2] == 1))
{
if (s->map[1][3] == 0){s->map[1][3] = 2; return;}
}
if ((s->map[1][1] == 2 && s->map[1][2] == 1) ||
(s->map[3][3] == 2 && s->map[2][3] == 1))
{
if (s->map[3][1] == 0){s->map[3][1] = 2; return;}
}

for (int i=0; i < 5; i++)
for (int j=0; j < 5; j++) if (s->map[i][j] == 0&& s->map[2][2] == 2){ s->map[i][j] = 2;  return; }
s->map[2][2] = 2;
}

之后main函数为这样就可以了。

int main()
{
game s;
Initialize_Map(&s);
for (; s.value < 4; s.value++)
{
cout << "棋盘的位置为小键盘的9到1依次对应下来" << endl;
robot(&s);
robot(&s);
draw(&s);
if (win(&s) == 1){cout << "you win.impossible" << endl; break;}
if (win(&s) == 2){cout << "you lost,hahaha" << endl; break;}
player(&s);
system("cls");
}
if (win(&s)!=2&&win(&s) != 1){draw(&s);cout << "what fuck?" << endl;} char x; cin >> x;
return 0;
}

这样就大工告成了。

 

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像