C语言五子棋的项目背景,五子棋项目源码!

原标题:五子棋项目源码!

662f79b560169d6d76f15a720d30d699.png

五子棋项目源码!

/*--------------------------------------

Gobang.c

五子棋函数的实现文件

对各种输入进行处理

--------------------------------------*/

#ifndef _WINDOWS_

#include

#endif

#include

#ifndef _INC_STDLIB

#include

#endif

#ifndef _GOBANG_H_

#include "Gobang.h"

#endif

//定义五子棋谱的线数

#ifndef LINECOUNT

#define LINECOUNT 15

#endif

/*

显示五子棋游戏背景

输入参数为设备环境句柄指针pdc,当前窗口大小r以及高度方向上的偏移offset

*/

BOOL DisplayInitBackground(HDC* pdc, RECT r, unsigned offset)

{

//五子棋盘每行、列宽、高度

unsigned width = (r.right - r.left) / (LINECOUNT + 1);

//边缘多出的像素值,即上一步求整余下的值

unsigned edge = r.right - r.left - width*(LINECOUNT + 1);

//计算棋谱位于窗口坐标系中的左上角点坐标

unsigned left = edge / 2 + width;

unsigned top = offset + edge / 2 + width;

int i = 0;

HPEN hPen;//将要使用的画笔

HPEN hPenOld;//当前画笔

//定义画笔

hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));

if (hPen == NULL) return FALSE;

//选中画笔

hPenOld = (HPEN)SelectObject(*pdc, hPen);

if (hPenOld == NULL) return FALSE;

//绘制五子棋谱

//绘制横线

for (i = 0; i < LINECOUNT; ++i)

{

MoveToEx(*pdc, left, top + i*width, NULL);

LineTo(*pdc, left + (LINECOUNT - 1)*width, top + i*width);

}

//绘制纵线

for (i = 0; i < LINECOUNT; ++i)

{

MoveToEx(*pdc, left + i*width, top, NULL);

LineTo(*pdc, left + i*width, top + (LINECOUNT - 1)*width);

}

if (SelectObject(*pdc, hPenOld) == NULL)

return FALSE;

return TRUE;

}

/*

判断点击的坐标是否在棋盘线的交点上,是否可以放置棋子

输入客户去坐标系中的横纵坐标、当前窗口在客户坐标系中的位置、高度偏差以及

单击的允许偏差

*/

BOOL IsIntersection(int x, int y, RECT r, int offset, int shift)

{

//五子棋盘每行、列宽、高度

int width = (r.right - r.left) / (LINECOUNT + 1);

//边缘多出的像素值,即上一步求整余下的值

int edge = r.right - r.left - width*(LINECOUNT + 1);

//计算棋谱位于窗口坐标系中的左上角点坐标

int left = edge / 2 + width;

int top = offset + edge / 2 + width;

//在棋盘范围内

if ((x - left) >= -shift && (x - left) <= ((LINECOUNT - 1)*width + shift)

&& (y - top) >= -shift && (y - top) <= ((LINECOUNT - 1)*width + shift)

//在棋盘线交点误差范围内

&& ((x - left) % width <= shift || (x - left) % width >= width - shift)

&& ((y - top) % width <= shift || (y - top) % width >= width - shift))

{

return TRUE;

}

else

{

return FALSE;

}

}

/*

找到单击的合法坐标对应的棋盘线交点的位置

输入单击的横纵坐标,窗口客户区位置、高度偏移和允许的单击偏差

*/

POINT FindPosition(int x, int y, RECT r, int offset, int shift)

{

//五子棋盘每行、列宽、高度

int width = (r.right - r.left) / (LINECOUNT + 1);

//边缘多出的像素值,即上一步求整余下的值

int edge = r.right - r.left - width*(LINECOUNT + 1);

//计算棋谱位于窗口坐标系中的左上角点坐标

int left = edge / 2 + width;

int top = offset + edge / 2 + width;

//棋盘线交叉点

POINT pt;

//寻找横坐标

//超过交点

if (abs((x - left) % width) <= shift)

{

pt.x = x - (x - left) % width;

}

//不到交点

else if ((x - left) % width >= width - shift)

{

pt.x = x - (x - left) % width + width;

}

//寻找纵坐标

//超过交点

if (abs((y - top) % width) <= shift)

{

pt.y = y - (y - top) % width;

}

//不到交点

else if ((y - top) % width >= width - shift)

{

pt.y = y - (y - top) % width + width;

}

return pt;

}

/*

在指定的棋盘交叉点显示黑棋

输入参数为设备坐标句柄指针,棋盘交叉点位置与棋子半径

*/

BOOL DisplayBlackChess(HDC* pdc, POINT pos, int radius)

{

HBRUSH hBrush;//将要使用的画刷

HBRUSH hBrushOld;//当前画刷

HRGN rgn;//棋子的区域

//产生画刷

hBrush = CreateSolidBrush(RGB(0, 0, 0));

//选中画刷

hBrushOld = (HBRUSH)SelectObject(*pdc, hBrush);

//产生棋子区域

rgn = CreateEllipticRgn(pos.x - radius, pos.y - radius,

pos.x + radius, pos.y + radius);

//绘制区域

PaintRgn(*pdc, rgn);

//删除区域与对象

DeleteObject(rgn);

if (SelectObject(*pdc, hBrushOld) == NULL)

return FALSE;

return TRUE;

}

/*

在指定的棋盘交叉点显示白棋

输入参数为设备坐标句柄指针,棋盘交叉点位置与棋子半径

*/

BOOL DisplayWhiteChess(HDC* pdc, POINT pos, int radius)

{

HBRUSH hBrush;//将要使用的画刷

HBRUSH hBrushOld;//当前画刷

HRGN rgn;//棋子的区域

//产生画刷

hBrush = CreateSolidBrush(RGB(255, 255, 255));

//选中画刷

hBrushOld = (HBRUSH)SelectObject(*pdc, hBrush);

//产生棋子区域

rgn = CreateEllipticRgn(pos.x - radius, pos.y - radius,

pos.x + radius, pos.y + radius);

//绘制区域

PaintRgn(*pdc, rgn);

//删除区域与对象

DeleteObject(rgn);

if (SelectObject(*pdc, hBrushOld) == NULL)

return FALSE;

return TRUE;

}

/*

检查单击的棋盘线交叉点是否已有棋子

输入参数为已下棋子的坐标数组头指针,已下的棋子个数与待判断的棋子坐标

*/

BOOL IsChessExisted(POINT* existedPoint, int count, POINT pt)

{

int i = 0;

for (i = 0; i < count; ++i)

{

if (pt.x == existedPoint[i].x && pt.y == existedPoint[i].y)

return TRUE;

}

return FALSE;

}

/*

通过棋子的客户区坐标计算棋子对应的坐标索引

输入棋子的客户区坐标,客户区大小与高度偏移

*/

POINT FindIndex(POINT pt, RECT r, int offset)

{

//五子棋盘每行、列宽、高度

int width = (r.right - r.left) / (LINECOUNT + 1);

//边缘多出的像素值,即上一步求整余下的值

int edge = r.right - r.left - width*(LINECOUNT + 1);

//计算棋谱位于窗口坐标系中的左上角点坐标

int left = edge / 2 + width;

int top = offset + edge / 2 + width;

//棋盘线交叉点坐标索引

POINT ptIndex;

//将坐标转化为索引

ptIndex.x = (pt.x - left) / width;

ptIndex.y = (pt.y - top) / width;

return ptIndex;

}

/*

根据坐标索引(重绘)显示棋子

输入参数为设备坐标句柄指针,棋盘交叉点位置索引数组头指针,

已下的棋子个数和客户区大小,高度偏移与棋子半径

*/

BOOL DisplayChess(HDC* pdc, POINT* existedPoint,

int count, RECT r, int offset, int radius)

{

//五子棋盘每行、列宽、高度

int width = (r.right - r.left) / (LINECOUNT + 1);

//边缘多出的像素值,即上一步求整余下的值

int edge = r.right - r.left - width*(LINECOUNT + 1);

//计算棋谱位于窗口坐标系中的左上角点坐标

int left = edge / 2 + width;

int top = offset + edge / 2 + width;

//棋盘线交叉点客户区坐标

POINT pt;

int i = 0;

//重绘、显示棋子

for (i = 0; i < count; i++)

{

//坐标索引转化为客户区坐标

pt.x = existedPoint[i].x*width + left;

pt.y = existedPoint[i].y*width + top;

//绘制棋子

//i为奇数,白棋

if (i % 2)

{

if (!DisplayWhiteChess(pdc, pt, radius))

return FALSE;

}

//偶数,黑棋

else

{

if (!DisplayBlackChess(pdc, pt, radius))

return FALSE;

}

}

return TRUE;

}

/*

检查是否赢得了此局

输入刚下的棋子坐标索引与已下的棋子坐标索引

*/

BOOL IsWin(POINT ptIndex, int chessIndex[15][15])

{

int i = 1;

int count = 1;//记录连续的棋子个数

//检查水平方向

//向左检查

while (chessIndex[ptIndex.x - i][ptIndex.y])

{

count++;

i++;

}

//向右检查

i = 1;

while (chessIndex[ptIndex.x + i][ptIndex.y])

{

count++;

i++;

}

//判断

if (count >= 5)

return TRUE;

//检查竖直方向

//向上检查

i = 1;

count = 1;

while (chessIndex[ptIndex.x][ptIndex.y - i])

{

count++;

i++;

}

//向右检查

i = 1;

while (chessIndex[ptIndex.x][ptIndex.y + i])

{

count++;

i++;

}

//判断

if (count >= 5)

return TRUE;

//检查主对角线方向

//向左上检查

i = 1;

count = 1;

while (chessIndex[ptIndex.x - i][ptIndex.y - i])

{

count++;

i++;

}

//向右下检查

i = 1;

while (chessIndex[ptIndex.x + i][ptIndex.y + i])

{

count++;

i++;

}

//判断

if (count >= 5)

return TRUE;

//检查副对角线方向

//向右上检查

i = 1;

count = 1;

while (chessIndex[ptIndex.x + i][ptIndex.y - i])

{

count++;

i++;

}

//向左下检查

i = 1;

while (chessIndex[ptIndex.x - i][ptIndex.y + i])

{

count++;

i++;

}

//判断

if (count >= 5)

return TRUE;

return FALSE;

}

//显示比赛的状态,即当前的黑白棋颜色

//输入设备环境句柄指针,已下点数,窗口大小以及高度偏移量

void ShowGameStatus(HDC* pdc, int count, RECT r, int offset)

{

HPEN hPen;

HPEN hOldPen;

HFONT hFont;

HFONT hOldFont;

hPen = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));

hOldPen = SelectObject(*pdc, hPen);

hFont = CreateFont(offset, (int)(offset / 1.5),

0, 0, FW_THIN, FALSE, FALSE, FALSE,

DEFAULT_CHARSET, OUT_CHARACTER_PRECIS,

CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,

FF_MODERN, TEXT("宋体"));

hOldFont = SelectObject(*pdc, hFont);

SetBkColor(*pdc, RGB(255, 250, 00));

if (count % 2)

{

TextOut(*pdc, 2, 2, TEXT("现在白棋"), 4);

}

else

{

TextOut(*pdc, 2, 2, TEXT("现在黑棋"), 4);

}

SelectObject(*pdc, hOldPen);

DeleteObject(hPen);

SelectObject(*pdc, hOldFont);

DeleteObject(hFont);

}

------------华丽的分割线--------------

经过长时间精心备课,杨老师的C语言系统已经上线,本期共包含22节课,课程是标准C语言

课程包含内容:

数据类型、进制转换、运算符、循环语句、开关分支语句、函数、数组、字符串、指针、结构体、内存管理、文件操作函数指针、指针函数、多维数组、高级指针、

每天晚上一节课

每节课是一个小时共:22节课

前20名支付是20元,优惠名额过了后面报名的学员是50元。

满30人开班,早点报名早点学习!

点击原文链接详细了解

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
开发步骤和思路 1、 编写主框架类JFiveFrame, 设置大小,标题,关闭窗口的行为, 在main中创建并显示。 2、 编写DrawPanel extends JPanel,定义构造函数,来设置背景颜色。 然后在主框架类中创建DrawPanel对象,并添加到主框架中。 3、 DrawPanel中覆盖paintComponent方法来进行绘制。 绘制15*15网格的棋盘, 绘制前先定义边距、行数、列数、网格宽度等常量 4、 定义Chess类,包括x,y索引, 颜色。 定义构造函数和相应的get方法。 5、 在DrawPanel中创建Chess[], 然后在paintComponent方法中绘制棋子数组(注意将索引转换成坐标)。 6、 为DrawPanel实现监听器MouseListener, 覆盖相应抽象方法。在构造方法中增加监听器(addMouseListener...)。 7、 编写mousePressed方法的内容,预先定义isBlack表示下的是黑棋还是白棋, chessCount表示当前棋子的个数 8、 在mousePressed中获得下的坐标,转换成索引, 再创建Chess对象,添加到chessList中。再重新绘制。 9、 添加相应的判断: 不能画到棋盘外, 下过的地方不能再下(需要辅助方法findChess...) 10、 再添加胜利的判断isWin, 添加标记变量gameOver. 在mousePressed方法的最前面调用加入gameOver的判断, 在mousePressed方法的最后调用isWin, 返回true则给出消息提示,gameOver设置为true。 11、isWin方法具体的编写。在当前下棋的横向,纵向,两个斜向上分别判断是否有连续的同色五子。 继续改进: 加入菜单:重新开始; 退出; 悔棋; 加入工具栏,三个按纽。 为最后下的棋子做出标记(画红色的矩形边界)。 改变鼠标形状, 在可以下的地方变手形;

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值