关键词不能为空

当前您在: 首页 > 育儿 >

基于C#的五子棋游戏的设计与实现.

作者:陕西保健网
来源:http://www.xapfxb.com/yuer
更新日期:2021-01-27 06:00

韩国男子组合有哪些-

2021年1月27日发(作者:皮高品)


























基于
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
”< br>,英文称之为“
Gobang

或“
FIR

Five in a Row
的缩写)
,亦有“连五子”

“五子连”< br>、
“串珠”

“五目”

“五目碰”

“五 格”等多种称谓。

五子棋不仅能增强思维能力,提高智力,而且富含哲理,有
助于修 身养性。五子棋既有现代休闲的明显特征“短、平、快”

又有古典哲学的高深学问“阴阳易理 ”
;它既有简单易学的特性,
为人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既有
“场”的概念,亦有“点”的连接。 它是中西文化的交流点,是
古今哲理的结晶。

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 = < br>global
::
五子

.Properties.
Reso urces
.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[tempSt ackElement
.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[tempStackElement.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/429892.html

基于C#的五子棋游戏的设计与实现.的相关文章