狐臭用什么药好-
郑
州
科
技
学
院
课
程
设
计
论
文
基于
C#
的五子棋游戏的设计与实现
学生姓名:王新年
学
号:
201015066
年级专业:
10
级计科二班
指导老师:
王玉萍
学
院:
信息工程学院
1
引言
................... .................................................. ..........................................
1
1.1
五子棋介绍
.
......... .................................................. ...................................
1
2
软件架构
.
...................... .................................................. ..............................
1
3
五子棋设计说明
.
......................... .................................................. ...............
2
3.1
主要成员变量说明
.
......................................... .........................................
2
3.2
回溯栈元素类
——
StackElement
.
......................................... ...................
3
3.3
棋子点属性类
——
qzdianshuxing ................ ...........................................
3
3.4
主要成员函数说明
.
...... .................................................. ..........................
3
3.5
实现人机对弈的主要函数
.
..................... .................................................
7
3.6
实现菜单功能的函数
.
..... .................................................. .....................
2
6
3.6
程序运行界面
.
.......................... .................................................. ............
3
0
4
心得体会
................................................. ..................................................
31
1
1
引言
1.1
五子棋介绍
五子 棋是起源于中国古代的传统黑白棋种之一。现代五子棋
日文称之为“連珠”
,英译为“
Renju
”
,英文称之为“
Gobang
”
或“
FIR< br>”
(
Five in a Row
的缩写)
,亦有“连五子”
、
“五子连”
、
“串珠”
、
“五目”
、
“五目碰”
、
“五格”等多种称谓。
五子棋不仅能增强思维能力,提高智力,而且富含 哲理,有
助于修身养性。五子棋既有现代休闲的明显特征“短、平、快”
,
又有古典哲 学的高深学问“阴阳易理”
;它既有简单易学的特性,
为人民群众所喜闻乐见,又有深奥的技巧 和高水平的国际性比
赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既有
“场”的概 念,亦有“点”的连接。它是中西文化的交流点,是
古今哲理的结晶。
2
软件架构
软件的总体架构如图
2.1
:
重
新
开
始
悔
棋
声
音
控
制
退
出
游戏控制
主界面
游戏模式
开
始
人
人
对
战
人
机
对
战
1
图
2.1
软件架构
3
五子棋设计说明
3.1
主要成员变量说明
1
)
选择游戏模式标志——
m_renren
用来表示当前玩家选择游戏的情况,
当
m_renren
为
false
时,
表示人机对战;为
true
时,表示人人对弈。
2
)
游戏开始标志——
begin
用来判断当前游戏是否开始
3
)
音效标志——
sound
在下棋过程中,判断是否 需要声音,当
sound
为
true
时,表
示玩家需要声音,否则的 话,玩家不需要声音。
4
)
谁先下的标志——
first
这个标志只对人机对弈时有效。当
first
为
true
时,表示人
先下,否则,电脑先下。
5
)
棋盘数据——
points
points
为棋盘情况数组,是用一个
15*15
的二维数组来表示
的。
points[ i,j]=2
表示此处无子,
points[i,j]=1
表示此处
为黑子< br> points[i,j]=0
表示此处为白子。
6
)
棋子颜色标志——
qzcolor
用来表示当前棋 子的颜色,
qzcolor=1
时表示黑棋,
qzcolor=0
时表示百棋 。
7
)
棋子数据——
qz
表示棋子所放的位 子,是用一个
15*15
的
PictureBox
类型的
二维数组来 表示。它还可以用来显示当前棋子的图片。
8
)
oldMovePoint
用来记录鼠标经过后点的位置。
9
)
backStack
用于悔棋的栈。
10
)
backTrackStack
2
用于回溯的栈
11
)结局——
result
用枚举类型来表示结局。如:
public
enum
result
:
int
//
结局
{
lose = -1,
equal,
win
}
3.2
回溯栈元素类
——
StackElement
成员变量:
1
)
qzColor
棋子的颜色
2
)
bestFivePoints
最好点的位置
3
)
pointsCount
计算最好点的数目
4
)
pointNumber
点的数目
5
)
Theresult
结局
6
)
stepNumber
预测的步数
3.3
棋子点属性类
——
qzdianshuxing
成员变量:
1
)
blackConnect
黑棋子
i
个(包括活棋)的连接条数
2
)
blackActive
黑活棋
i
个的连接条数
3
)
whiteConnect
白棋子
i
个(包括活棋)的连接条数
4
)
whiteActive
白活棋
i
个的连接条数
5
)
tempActive3
活棋数为
3
的连接条数
3.4
主要成员函数说明
1
)
初始化棋盘——
Initializeqp
初始化操作包括以下几个步骤:
?
设置棋子所在的位置
?
设置棋子的大小
?
初始化棋子的背景颜色
?
将棋子的
sizemode
设置为
CenterImage
?
将棋子的可见性设置为
false
?
将棋子添加到
form
上。
2
)
绘制棋盘——
Form1_Paint
3
其主要是画出以
40*40
的大小为每一小格,代码如下:
for
(i = 0; i < 15; i++)
{
ne(myPen, 30 + i * 40, 50, 30 +
i * 40, 610);
ne(myPen, 30, 50 + i * 40, 590,
50 + i * 40);
}
3
)
绘制光标——
Form1_MouseMove
当鼠标在棋盘上移动时,当前的显示画红方框,过去的显示
和背景一样颜色的方框。
当前的红方框代码如下:
if
(10 < e.X && 10< e.Y &&e.X <
&& e.Y <)
{
x = ((e.X - 10) / 40) * 40 + 30;
y = ((e.Y - 10) / 40) * 40 + 50;
ne(newpen, x - 15, y - 15, x - 15,
y - 5);
ne(newpen, x - 15, y - 15, x - 5,
y - 15);
ne(newpen, x + 15, y - 15, x + 5,
y - 15);
ne(newpen, x + 15, y - 15, x + 15,
y -5);
ne(newpen, x - 15, y + 15, x - 15,
y + 5);
ne(newpen, x - 15, y + 15, x - 5,
y + 15);
ne(newpen, x + 15, y + 15, x + 15,
y + 5);
ne(newpen, x + 15, y + 15, x + 5,
y + 15);
oldMovePoint.X = x;
oldMovePoint.Y = y;
}
过去的方框代码如下:
4
if
(oldMovePoint.X != -1)
{
ne(oldpen, oldMovePoint.X - 15,
oldMovePoint.Y - 15, oldMovePoint.X - 15, oldMovePoint.Y
- 5);
ne(oldpen, oldMovePoint.X - 15,
oldMovePoint.Y - 15, oldMovePoint.X - 5, oldMovePoint.Y
- 15);
ne(oldpen, oldMovePoint.X + 15,
oldMovePoint.Y - 15, oldMovePoint.X + 5, oldMovePoint.Y
- 15);
ne(oldpen, oldMovePoint.X + 15,
oldMovePoint.Y - 15, oldMovePoint.X + 15, oldMovePoint.Y
- 5);
ne(oldpen, oldMovePoint.X - 15,
oldMovePoint.Y + 15, oldMovePoint.X - 15, oldMovePoint.Y
+ 5);
ne(oldpen, oldMovePoint.X - 15,
oldMovePoint.Y + 15, oldMovePoint.X - 5, oldMovePoint.Y
+ 15);
ne(oldpen, oldMovePoint.X + 15,
oldMovePoint.Y + 15, oldMovePoint.X + 15, oldMovePoint.Y
+ 5);
ne(oldpen, oldMovePoint.X + 15,
oldMovePoint.Y + 15, oldMovePoint.X + 5, oldMovePoint.Y
+ 15);
}
4
)
下棋子——
putqz
下棋子有两种可能性,一
是知道一个点的横纵坐标;二
是
知道一个点。
下面我就说一说知道
x
,
y坐标的情况,第二种情况只要调用
第一种情况就行了。
假如下的是一个黑棋子, 将
qz
的背景图设置为
blackstone
,
并将此处标记为已下 黑棋,并将此棋子标记为最后落子指示。
如果悔棋的栈不为空,将其弹出栈,并将
qz
的图像设置为什
么都没有,再将其压入栈。同理,白旗也跟这一样做。代码
5
如下:
if
(qzcolor==1)
{
qz[x, y].BackgroundImage =
global
::
五子
棋.Properties.
Resources
.blackstone;
points[x, y] = 1;
qz[x, y].Image =
global
::
五子
棋
.Propert ies.
Resources
.lastblackstone;
if
( > 0)
{
temp = (
Point
)();
qz[temp.X, temp.Y].Image =
global
::
五子棋
.Properties.
Resources
.nullll;
(temp);
}
}
else
{
qz[x, y].BackgroundImage =
global
::
五子< br>棋
.Properties.
Resources
.whitestone;
points[x, y] = 0;
qz[x, y].Image =
global
::
五子
棋
.P roperties.
Resources
.lastwhitestone;
if
( > 0)
{
temp = (
Point
)();
qz[temp.X, temp.Y].Image =
global
::
五子棋
.Properties.
Resources
.nullll;
(temp);
}
}
最后将其可见性设置为
true
。
5
)
开始函数——
start
当棋局开始时,就应将棋盘初始化,使棋盘上没有棋子。如
果有悔棋,就要将悔棋栈清空。代码如下
:
if
(!begin)
{
6
begin =
true
;
for
(x = 0; x < 15; x++)
for
(y = 0; y < 15; y++)
{
qz[x, y].Visible =
false
;
points[x, y] = 2;
}
while
( > 0)
();
}
3.5
实现人机对弈的主要函数
6
)
察看两点之间的棋子数函数——
ConnectqpCount
这个函数主要求两点 之间可能形成五连子的
qzcolor
色棋的
连子数
(
包括活期)
。首先,求出两点之间总共的棋子数,并
判断棋子所在哪个方向。沿着这个方向每个点的 坐标,并察
看这几个点中有没有反色的棋子。如果有,棋子数设为
0
,否
则的 话,棋子数自加
1
。代码如下:
int
x, y, i, j,
length, xPlus =
0, yPlus = 0, sum, maxSum
= 0;
length =
Math
.Max(
Math
.Abs(point1.X - point2.X),
Math
.Abs(point1.Y - point2.Y)) + 1;
if
(point1.X != point2.X) xPlus = 1;
if
(point1.Y != point2.Y) yPlus = (point2.Y -
point1.Y)/
Math
.Abs(po
int2.Y - point1.Y);
for
(i = 0; i < length - 4; i++)
{
x = point1.X + i * xPlus;
y = point1.Y + i * yPlus;
sum = 0;
for
(j = 0; j < 5; j++)
{
//
察看两点之间当中有没有反色
if
(points[x
+
j
*
xPlus,
y
+
j
*
yPlus]
== qzcolor)
sum++;
else
if
(points[x + j * xPlus, y + j
7
* yPlus] == -qzcolor+1)
{
sum = 0;
break
;
}
}
if
(maxSum < sum)
maxSum = sum;
}
return
maxSum;
7
)
察看两点之间是否存在活棋的函数——
ActiveConnectqp
这个函数主要求两点之间
qzcolor
色棋是否存在活棋。
temp1
变量表示在一直线上,比如,
一条向下的直线,则表示点
point1< br>上方可下的个数;而
temp2
表示点
point2
下方可下的个数。代码表示为:
temp1 =
Math
.Min(
Math
.Min(
Math
.Min(5 - count,
point1.X), point1.Y), 14 - point1.Y);
temp2 =
Math
.Min(
Math
.Min(
Math
.Min(5 - count, 14 -
point2.X), 14 - point2.Y), point2.Y);
则长度表示为:
length
=
Math
.Max(
Math
.Abs(point1.X
-
point2.X),
Math
.Abs(point1.Y - point2.Y)) + 1 + temp1 + temp2;
先
求
两
点
之
间
qzcolor
色
棋
的
棋
子个
数
,
做
法
和
函
数
Connectq pCount
一样。再判断它是否是活棋。当参数
count
和所得两点之间
qzcolor
色棋的棋子个数相等,并且两头都
没下棋子时,它为活棋。否则,反之。代码如 下:
if
(point1.X != point2.X) xPlus = 1;
if
(point1.Y
!=
point2.Y)
yPlus
=
(point2.Y
-
point1.Y)
/
Math
.Abs(point2.Y - point1.Y);
for
(i = 0; i < length - 4; i++)
{
x = point1.X - temp1 * xPlus + i * xPlus;
y = point1.Y - temp1 * yPlus + i * yPlus;
if
(x + 4 * xPlus > 14 || y + 4 * yPlus >
14)
break
;
sum = 0;
8
for
(j = 0; j < 4; j++)
{
if
(points[x
+
j
*
xPlus,
y
+
j
*
yPlus]
== qzcolor)
sum++;
else
if
(points[x + j * xPlus, y + j
* yPlus] == -qzcolor+1)
{
sum = 0;
break
;
}
}
if
(0 < x && 0 <= y - yPlus && y - yPlus
<= 14)
{
if
(sum == count && points[x - xPlus, y -
yPlus] == 2 && points[x + 4 * xPlus, y + 4 * yPlus]
== 2)
return
true
;
}
}
8
)
查看是否被破坏活期——
BreakActiveConnectqp
在
( x,y)
处放
qzcolor
色棋后形成活
count,
且放一反色 棋后破坏
棋形成活
count
。代码如下:
if
(!ActiveConnectqp(qzcolor, count, point1, point2))
return
false
;
if
(count == 5)
return
false
;
else
if
(count == 4)
return
true
;
else
{
bool
blnFlag;
points[x, y] = -qzcolor+1;
blnFlag
=
!ActiveConnectqp(qzcolor,
count
- 1, point1, point2);
points[x, y] = qzcolor;
return
blnFlag;
}
9
9
)
查看是否是最好的点——
FindBestPoint
首先,查看有没有最佳点,并 形成栈元素。如果没有,返回
false
;否则,将这栈元素压入回溯栈中。当栈非空时,将栈
元素弹出,如果栈中的
pointNumber
小于
pointCount< br>时,在
棋盘上下一棋。如果赢棋,不再继续探测,并在棋盘上退一
棋。如果和棋的话,也 不再继续探测,并在棋盘上退一棋。
否则,继续下棋并探测。如果栈顶元素无点,弹出后栈必非
空,并在棋盘上退一棋。如果栈顶元素中点均已试过,则寻
找栈顶元素中点的最好结局,并寻找最佳步数 。实现的代码
如下:
result
totalresult =
result
.lose;
int
i, bestStepNumber = 0;
StackElement
tempStackElement =
new
StackElement
();
if
(first)
{
qzcolor = 0;
if
(! FindBestFivePointsAndFormAStackElement(qzcolor,
ref
tempStackElement))
return
false
;
}
else
{
qzcolor = 1;
if
(! FindBestFivePointsAndFormAStackElement(qzcolor,
ref
tempStackElement))
return
false
;
}
(tempStackElement);
while
( > 0)
//
栈非空
{
tempStackElement =
(
StackElement
)();
if
(umber <
Count)
10
{
//
在棋盘上下一棋
points[vePoints[tempStackElement
.pointNumber]. X,
vePoints[
umber].Y] = r;
if
(Win(r,
vePoints[
umber]))
{
//
赢棋,不在继续探测
ult[umber]
=
result
.win;
mber[umbe
r] = + 1;
//
在棋盘上退一棋
points[vePoints[tempStackElement
.pointNumb er].X,
vePoints[
umber].Y] = 2;
umber++;
(tempStackElement);
}
else
if
( == M -
1)
{
//
将此元素压入栈后栈满,不在继续探
测
ult[umber]
=
result
.equal;
mber[umbe
r] = M;
11
//
在棋盘上退一棋
points[vePoints[tempStackElement
.pointNumb er].X,
vePoints[
umber].Y] = 2;
umber++;
(tempStackElement);
}
else
{
//
另一方继续下棋向下探测
umber++;
(tempStackElement);
FindBestFivePointsAndFormAStackElement(-tempSt ackElemen
r+1,
ref
tempStackElement);
(tempStackElement);
}
}
//end if
else
//
栈顶元素无点或点均已试过
{
if
(Count ==
0)
//
栈顶元素无点,且弹出后栈必非空
{
tempStackElement =
(
StackElement
)();
ult[umber
- 1] =
result
.win;
mber[umbe
r - 1] = + 1;
//
在棋盘上退一棋
12
points[vePoints[tempStackElem ent
.pointNumber - 1].X,
vePoints[
umber - 1].Y] = 2;
(tempStackElement);
}
else
//
栈顶元素中点均已试过
{
//
寻找栈顶元素中点的最好结局
totalresult =
ult[0];
for
(i = 0; i <
Count; i++)
if
(totalresult <
ult[i])
totalresult =
ult[i];
//
寻找最佳步数
if
(totalresult ==
result
.win)
{
bestStepNumber = M + 2;
for
(i = 0; i <
Count; i++)
if
(totalresult ==
ult[i] && bestStepNumber >
mber[i])
bestStepNumber =
mber[i];
}
else
//totalresult==
或
lose
{
bestStepNumber = 0;
for
(i = 0; i <
Count; i++)
if
(totalresult ==
13
ult[i] && bestStepNumber <
mber[i])
bestStepNumber =
mber[i];
}
if
( > 0)
//
栈非空
{
tempStackElement =
(
StackElement
)();
ult[umber
- 1] = (
result
)(0 - totalresult);
mber[umbe
r - 1] = bestStepNumber;
//
在棋盘上退一棋
points[vePoints[tempStackElement
.pointNumb er - 1].X,
vePoints[
umber - 1].Y] = 2;
(tempStackElement);
}
}
}
}
for
(i = 0; i < Count;
i++)
if
(totalresult ==
ult[i] && bestStepNumber ==
mber[i])
break
;
bestPoint =
vePoints[i];
return
true
;
14
狐臭用什么药好-
狐臭用什么药好-
狐臭用什么药好-
狐臭用什么药好-
狐臭用什么药好-
狐臭用什么药好-
狐臭用什么药好-
狐臭用什么药好-
本文更新与2021-01-27 06:00,由作者提供,不代表本网站立场,转载请注明出处:http://www.xapfxb.com/yuer/429891.html
-
上一篇:五子棋游戏设计报告
下一篇:基于C#的五子棋游戏的设计与实现.