一、easyx库的安装
二、该代码所使用的头文件
#include <iostream>
#include <string.h>
#include <vector>//容器头文件
#include <Windows.h>
#include<graphics.h>//图形头文件
三、需要使用的数据类型
int board[18][18] = { 0 };//棋盘数组
int flag = 0;//计数器,判断黑棋执步或白棋执步
vector <int> a_v;
vector <int> b_v;//利用容器记录悔棋位置,a,b分别为x,y坐标
三、棋盘绘制(利用easyx绘制棋盘)
//初始化游戏界面
void InitGame()
{
//绘图
initgraph(700, 600);//把图界面输出
setbkcolor(BROWN);//棕色
cleardevice();//刷新
//画线 绘制棋盘
setlinecolor(BLACK);//把线设置成黑色
for (int i = 70; i <= 500; i += 25)
{
line(5, i, 430, i);//画横着的线
line(i - 65, 70, i - 65, 495);//画垂直的线
}
line(431, 70, 431, 495);//加粗
line(5, 69, 430, 69);
//输出玩家信息
outtextxy(480, 80, "玩家1 白棋");
outtextxy(480, 180, "玩家2 黑棋");
outtextxy(580, 180, "点击悔棋");
}
绘制成功后即可得到棋盘初始界面
四、基本操作下棋的实现
对于下棋过程,我们可以将棋盘视为二维数组(包括x轴与y轴)int board[18][18] = { 0 };//棋盘数组 (本想用bool类型来记录下棋情况,但由于单个单位会有三种情况黑棋、白棋、无棋,所以使用int类型记录)下棋过程中我们还需要让计算机知道黑棋执步还是白棋执步,因此我加入了int flag = 0;//计数器,判断黑棋执步或白棋执步来记录flag为偶数则黑棋执步,奇数为白棋执步,由于数据只有两种情况,我们可以使用bool类型记录,但是不能记录步数用于悔棋所以废除使用;鉴于五子棋规则,我们需要在下棋后就进行输赢判断(该函数下一段讲述);同时要完成悔棋操作,我们需要记住每步棋子的落位方便悔棋。
//下棋
void playChess()
{
int a, b;//棋盘上的坐标
MOUSEMSG m;//鼠标类型的数据
HWND hwnd;//输出窗口
hwnd = GetHWnd();
//鼠标左键点击下棋
while (1)
{
m = GetMouseMsg();//获取鼠标消息
if (m.uMsg == WM_LBUTTONDOWN)//如果左键按下
{
a = (m.x + 13) / 25;
b = (m.y - 70 + 13) / 25;
if (m.x >= 580 && m.x <= 660 && m.y >= 180 && m.y <= 200)//悔棋
{
huiqi(a_v.back(), b_v.back());
a_v.pop_back(); b_v.pop_back();//利用vector容器进行悔棋
continue;
}
if (a > 17 || a < 0 || b>17 || b < 0)
{
MessageBox(hwnd, "鼠标点击越界", "提示", MB_OK);
continue;
}
if (board[a][b] != 0)
{
MessageBox(hwnd, "这里已经有棋子了", "提示", MB_OK);
continue;
}
if (flag % 2 == 0)//是偶数
{
//显示为黑棋
setfillcolor(BLACK);
board[a][b] = 1;
}
if (flag % 2 != 0)//为奇数
{
//显示为白棋
setfillcolor(WHITE);
board[a][b] = 2;
}
//落棋
solidcircle(a * 25 + 5, b * 25 + 70, 10);//画一个圆
flag++;
a_v.push_back(a); b_v.push_back(b);
//判断输赢
if (judge(a, b))
{
if (flag % 2 == 1)
{
MessageBox(hwnd, "玩家2胜利", "提示", MB_OK);
exit(0);
}
else
{
MessageBox(hwnd, "玩家1胜利", "提示", MB_OK);
exit(0);
}
}}
}
}
在下棋操作中,我们包括了判断哪方执步,记录并绘出棋子位置,悔棋三种操作,数据由鼠标点击位置获取
MOUSEMSG m;//鼠标类型的数据
HWND hwnd;//输出窗口
hwnd = GetHWnd();
//鼠标左键点击下棋
五、判断输赢操作实现
对于判断输赢的过程,众所周知五个棋子连在一起即可胜利,在实际游戏中,我们通过最后一个落子与周围的同色棋子是否连着存在五个来判断输赢,这也是我判断输赢的方法,由于实际操作要转换为计算机操作,我们必须在每次下棋后就就执行一次判断(横向判、纵向判断、竖向判断)。
//判断输赢
int judge(int a, int b)
{
//左右
for (int i = a - 4, num = 1; i <= a + 4; i++)
{
if (i > 17 || i < 0) continue;//排除越界
if (board[a][b] == board[i][b] && a != i)//一旦相同就加1
num++;
else
{
if (a != i)//排除循环中自己的比较
num = 1;
}
if (num == 5)
return 1;
}
//上下
for (int i = b - 4, num = 1; i <= b + 4; i++)
{
if (i > 17 || i < 0) continue;//排除越界
if (board[a][b] == board[a][i] && b != i)//一旦相同就加1
num++;
else
{
if (b != i)//排除循环中自己的比较
num = 1;
}
if (num == 5)
return 1;
}
//斜右
for (int i = a - 4, j = b + 4, num = 1; i <= a + 4 && j >= b - 4; i++, j--)
{
if (i > 17 || i < 0 || j>17 || j < 0) continue;//排除越界
if (board[a][b] == board[i][j] && a != i && b != j)//一旦相同就加1
num++;
else
{
if (a != i && b != j)//排除循环中自己的比较
num = 1;
}
if (num == 5)
return 1;
}
//斜左
for (int i = a - 4, j = b - 4, num = 1; i <= a + 4 && j <= b + 4; i++, j++)
{
if (i > 17 || i < 0 || j>17 || j < 0) continue;//排除越界
if (board[a][b] == board[i][j] && a != i && b != j)//一旦相同就加1
num++;
else
{
if (a != i && b != j)//排除循环中自己的比较
num = 1;
}
if (num == 5)
return 1;
}
return 0;
}
该函数主要通过存储在数组中的棋子数据来进行判断;如先前所说,在下棋过程中同时进行比较由于输入数据位与二维数组中,通过二维数组来对棋子是否连成五个或五个以上的结果进行判断,结果只返回是否出现赢家,黑棋或白棋胜利有计数器flag记录判断;
六、悔棋操作实现
对于悔棋的过程,我们只需要记录每次下棋的坐标(通过vector容器)vector <int> a_v; vector <int> b_v;//利用容器记录悔棋位置,a,b分别为x,y坐标
//不使用stack栈结构,因为stl中栈的存储大小有限,容易越界导致bug,不使用队列是因为队列的先进先出的操作不适用与悔棋以及是什么棋子执步即可,但由于需要将操作结果面向用户展示,我需要在图像上进行改变,最简单的方法即直接覆盖棋子同时对flag计数器减一,然后将容器尾部数据删除。
//悔棋
void huiqi(int a,int b){
clearcircle(a * 25 + 5, b * 25 + 70, 10);//清除区域
line(a * 25-5 , b * 25 + 70, a * 25+15, b * 25 + 70);//画横着的线
line(a * 25 +5, b * 25 + 70-10,a * 25 + 5, b * 25 + 70+ 10);//画垂直的线
board[a][b] = 0;
flag--;
}
该函数主要是对已知位置(x轴,y轴)执行图像上的清除(准确说是覆盖),主要部分(数据存储)还在下棋函数中
在函数设计时,实际函数中只进行了覆盖的操作,即在图上画一个棕色的椭圆以及横竖线,来“伪造”悔棋的操作。
七、主函数
int main()//主函数 有且仅有一个
{
InitGame();//初始画图形
playChess();//调用下棋
return 0;
}
由于操作主要进行在下棋函数中,所以主函数中只需要使用绘制棋盘函数以及主函数即可