
Dim j As Integer
Dim k As Integer
Dim X As String
Dim Y As String
Dim m As Integer
Dim n As Integer
Private Sub Command1_Click()
Label1.Caption = "该黑棋" &gamer1 &"走"
blackwhite = True
heibaiqi = True
Picture1.Cls
For i = 5 To -5 Step -1
Picture1.Line (-4.5, i - 0.5)-(4.5, i - 0.5)
QBColor (0)
Picture1.Line (i - 0.5, -4.5)-(i - 0.5, 4.5)
QBColor (0)
Next
For j = -4 To 4 Step -1
For k = -4 To 4 Step -1
a(j, k) = 0
Next
Next
a(j, k) = 0
Picture1.FillStyle = 0
Picture1.FillColor = QBColor(0)
Picture1.Circle (0, 0), 0.3, QBColor(0)
Picture1.Circle (1, 1), 0.3, QBColor(0)
Picture1.FillColor = QBColor(15)
Picture1.Circle (0, 1), 0.3, QBColor(15)
Picture1.Circle (1, 0), 0.3, QBColor(15)
End Sub
Private Sub Form_Load()
Form2.Picture1.Scale (-5, 5)-(5, -5)
Text1.Text = ""
End Sub
Private Sub kaishi_Click()
Label1.Caption = "该黑棋" + gamer1 + "走"
blackwhite = True
heibaiqi = True
Picture1.Cls
For i = 5 To -5 Step -1
Picture1.Line (-4.5, i - 0.5)-(4.5, i - 0.5)
QBColor (0)
Picture1.Line (i - 0.5, -4.5)-(i - 0.5, 4.5)
QBColor (0)
Next
For j = -4 To 4 Step -1
For k = -4 To 4 Step -1
a(j, k) = 0
Next
Next
a(j, k) = 0
Picture1.FillStyle = 0
Picture1.FillColor = QBColor(0)
Picture1.Circle (0, 0), 0.3, QBColor(0)
Picture1.Circle (1, 1), 0.3, QBColor(0)
Picture1.FillColor = QBColor(15)
Picture1.Circle (0, 1), 0.3, QBColor(15)
Picture1.Circle (1, 0), 0.3, QBColor(15)
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If CInt(X) >= -4 And CInt(Y) >= -4 And heibaiqi = True Then
m = CInt(X)
n = CInt(Y)
Picture1.FillStyle = 0
If blackwhite = True And a(CInt(X), CInt(Y)) = 0 Then
Picture1.FillColor = QBColor(0)
Picture1.Circle (CInt(X), CInt(Y)), 0.3, QBColor(0)
a(CInt(X), CInt(Y)) = 1
Label1.Caption = "该白棋" &gamer2 &"走"
blackwhite = Not blackwhite
End If
If blackwhite = False And a(CInt(X), CInt(Y)) = 0 Then
Picture1.FillColor = QBColor(15)
Picture1.Circle (CInt(X), CInt(Y)), 0.3, QBColor(15)
a(CInt(X), CInt(Y)) = 2
Label1.Caption = "该黑棋" &gamer1 &"走"
blackwhite = Not blackwhite
End If
End If
'反转棋子
For i = 1 To 7
For j = 0 To i - 1
If a(CInt(X), CInt(Y)) = 1 And a(CInt(X) - i, CInt(Y)) = 1 And a(CInt(X) - i + j, CInt(Y)) = 2 Then
a(CInt(X) - i + j, CInt(Y)) = 1
End If
If a(CInt(X), CInt(Y)) = 1 And a(CInt(X), CInt(Y) - i) = 1 And a(CInt(X), CInt(Y) - i + j) = 2 Then
a(CInt(X), CInt(Y) - i + j) = 1
End If
If a(CInt(X), CInt(Y)) = 2 And a(CInt(X) - i, CInt(Y)) = 2 And a(CInt(X) - i + j, CInt(Y)) = 1 Then
a(CInt(X) - i + j, CInt(Y)) = 2
End If
If a(CInt(X), CInt(Y)) = 2 And a(CInt(X), CInt(Y) - i) = 2 And a(CInt(X), CInt(Y) - i + j) = 1 Then
a(CInt(X), CInt(Y) - i + j) = 2
End If
Next
Next
这个问题太深奥了、只能百度之这里将要叙述三种不同的估值函数范例。大多数的黑白棋程序都可以归结于此。
棋格表
这种算法的意思是,不同的棋格有不同的值,角的值大而角旁边的格子值要小。忽视对称的话,棋盘上有10个不同的位置,每个格子根据三种可能性赋值:黑棋、白棋和空。更有经验的逼近是在游戏的不同阶段对格子赋予不同的值。例如,角在开局阶段和中局开始阶段比终局阶段更重要。
一般认为,采用这种算法的程序总是很弱,但另一方面,它很轻易实现,于是许多程序开始采用这种逼近。并且,对于许多程序设计者来说,它有能力使程序强到击败它的创造者...
基于行动力的估值
这种更久远的接近有很强的全局观,而不像棋格表那样局部化。观察表明,许多人类玩者努力获得最大的行动力(可下棋的数目)和潜在行动力(临近对手棋子的空格,见技巧篇)。假如代码有效率的话,可以很快发现,它们提高棋力很多。和另一种人类的策略一样,许多基于行动力估值的程序同时还有一些边角配置的知识,试图在中盘早期使棋子最少。
基于模版的估值
正如上面提及的,许多中等力量的程序经常合并一些边角判定的知识,最大行动力和潜在行动力是全局特性,但是他们可以被切割成局部配置,再加在一起。棋子最少化也是如此。 这导致了以下的概括:在估值函数中仅用局部配置(模版),通常单独计算每一行、一列、斜边和角落的模板,再线性叠加在一起来实现。并且,配置情况的值非常依靠于游戏的不同阶段。比如,一条边有3321种配置情况((3^8-3^4)/2+3^4),每种情况的分值好坏在游戏的不同阶段都不相同。分值基于强力玩者和程序的游戏结果统计,他们存于数据库中,游戏启动时自动调入。
常见的有这样一些模板:
名称 类似区域 配置数 去掉对称后的配置数
corner5x2 a1:e2 3^10=59049 (3^10-3^5)/2+3^5 = 29646
diag5 a5:e1 3^5 =243 (3^5 -3^3)/2+3^3 = 135
diag6 a6:f1 3^6 =729 (3^6 -3^3)/2+3^3 = 378
diag7 a7:g1 3^7 =2187 (3^7 -3^4)/2+3^4 = 1134
diag8 a8:h1 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321
edge2x a1:h1 + b2 + g2 3^10=59049 (3^10-3^5)/2+3^5 = 29646
hor2 a2:h2 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321
hor3 a3:h3 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321
hor4 a4:h4 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321
triangle a1:a4:d1 3^10=59049 (3^10-3^5)/2+3^5 = 29646
估值合并
一般程序的估值基于许多的参数,如行动力、潜在行动力、余裕手、边角判定、稳定子(见技巧篇)。但是怎么样将他们合并起来得到一个估值呢?为了提高速度,一般的程序采用线性合并。设a1,a2,a3,a4为参数,则估值s:=n1*a1+n2*a2+n3*a3+n4*a4。其中n1,n2,n3,n4为常数,术语叫“权重”(weight),它决定了参数的重要性,来自于统计值。
黑白棋#include "graphics.h" /*图形系统头文件*/
#define LEFT 0x4b00 /*光标左键值*/
#define RIGHT 0x4d00 /*光标右键值*/
#define DOWN 0x5000 /*光标下键值*/
#define UP 0x4800 /*光标上键值*/
#define ESC 0x011b /* ESC键值*/
#define ENTER 0x1c0d /* 回车键值*/
int a[8][8]={0},key,score1,score2/*具体分数以及按键与存放棋子的变量*/
char playone[3],playtwo[3]/*两个人的得分转换成字符串输出*/
void playtoplay(void)/*人人对战函数*/
void DrawQp(void)/*画棋盘函数*/
void SetPlayColor(int x)/*设置棋子第一次的颜色*/
void MoveColor(int x,int y)/*恢复原来棋盘状态*/
int QpChange(int x,int y,int z)/*判断棋盘的变化*/
void DoScore(void)/*处理分数*/
void PrintScore(int n)/*输出成绩*/
void playWin(void)/*输出胜利者信息*/
/******主函数*********/
void main(void)
{
int gd=DETECT,gr
initgraph(&gd,&gr,"c:\\tc")/*初始化图形系统*/
DrawQp()/*画棋盘*/
playtoplay()/*人人对战*/
getch()
closegraph()/*关闭图形系统*/
}
void DrawQp()/*画棋盘*/
{
int i,j
score1=score2=0/*棋手一开始得分都为0*/
setbkcolor(BLUE)
for(i=100i<=420i+=40)
{
line(100,i,420,i)/*画水平线*/
line(i,100,i,420)/*画垂直线*/
}
setcolor(0)/*取消圆周围的一圈东西*/
setfillstyle(SOLID_FILL,15)/*白色实体填充模式*/
fillellipse(500,200,15,15)/*在显示得分的位置画棋*/
setfillstyle(SOLID_FILL,8)/*黑色实体填充模式*/
fillellipse(500,300,15,15)
a[3][3]=a[4][4]=1/*初始两个黑棋*/
a[3][4]=a[4][3]=2/*初始两个白棋*/
setfillstyle(SOLID_FILL,WHITE)
fillellipse(120+3*40,120+3*40,15,15)
fillellipse(120+4*40,120+4*40,15,15)
setfillstyle(SOLID_FILL,8)
fillellipse(120+3*40,120+4*40,15,15)
fillellipse(120+4*40,120+3*40,15,15)
score1=score2=2/*有棋后改变分数*/
DoScore()/*输出开始分数*/
}
void playtoplay()/*人人对战*/
{
int x,y,t=1,i,j,cc=0
while(1)/*换棋手走棋*/
{
x=120,y=80/*每次棋子一开始出来的坐标,x为行坐标,y为列坐标*/
while(1) /*具体一个棋手走棋的过程*/
{
PrintScore(1)/*输出棋手1的成绩*/
PrintScore(2)/*输出棋手2的成绩*/
SetPlayColor(t)/*t变量是用来判断棋手所执棋子的颜色*/
fillellipse(x,y,15,15)
key=bioskey(0)/*接收按键*/
if(key==ESC)/*跳出游戏*/
break
else
if(key==ENTER)/*如果按键确定就可以跳出循环*/
{
if(y!=80&&a[(x-120)/40][(y-120)/40]!=1
&&a[(x-120)/40][(y-120)/40]!=2)/*如果落子位置没有棋子*/
{
if(t%2==1)/*如果是棋手1移动*/
a[(x-120)/40][(y-120)/40]=1
else/*否则棋手2移动*/
a[(x-120)/40][(y-120)/40]=2
if(!QpChange(x,y,t))/*落子后判断棋盘的变化*/
{
a[(x-120)/40][(y-120)/40]=0/*恢复空格状态*/
cc++/*开始统计尝试次数*/
if(cc>=64-score1-score2) /*如果尝试超过空格数则停步*/
{
MoveColor(x,y)
fillellipse(x,y,15,15)
break
}
else
continue/*如果按键无效*/
}
DoScore()/*分数的改变*/
break/*棋盘变化了,则轮对方走棋*/
}
else/*已经有棋子就继续按键*/
continue
}
else /*四个方向按键的判断*/
if(key==LEFT&&x>120)/*左方向键*/
{
MoveColor(x,y)
fillellipse(x,y,15,15)
SetPlayColor(t)
x-=40
fillellipse(x,y,15,15)
}
else
if(key==RIGHT&&x<400&&y>80)/*右方向键*/
{
MoveColor(x,y)
fillellipse(x,y,15,15)
SetPlayColor(t)
x+=40
fillellipse(x,y,15,15)
}
else
if(key==UP&&y>120)/*上方向键*/
{
MoveColor(x,y)
fillellipse(x,y,15,15)
SetPlayColor(t)
y-=40
fillellipse(x,y,15,15)
}
else
if(key==DOWN&&y<400)/*下方向键*/
{
MoveColor(x,y)
fillellipse(x,y,15,15)
SetPlayColor(t)
y+=40
fillellipse(x,y,15,15)
}
}
if(key==ESC)/*结束游戏*/
break
if((score1+score2)==64||score1==0||score2==0)/*格子已经占满或一方棋子为0判断胜负*/
{
playWin()/*输出最后结果*/
break
}
t=t%2+1/*一方走后,改变棋子颜色即轮对方走*/
cc=0 /*计数值恢复为0*/
} /*endwhile*/
}
void SetPlayColor(int t)/*设置棋子颜色*/
{
if(t%2==1)
setfillstyle(SOLID_FILL,15)/*白色*/
else
setfillstyle(SOLID_FILL,8)/*灰色*/
}
void MoveColor(int x,int y)/*走了一步后恢复原来格子的状态*/
{
if(y<100)/*如果是从起点出发就恢复蓝色*/
setfillstyle(SOLID_FILL,BLUE)
else/*其他情况如果是1就恢复白色棋子,2恢复黑色棋子,或恢复蓝色棋盘*/
switch(a[(x-120)/40][(y-120)/40])
{
case 1:
setfillstyle(SOLID_FILL,15)break/*白色*/
case 2:
setfillstyle(SOLID_FILL,8)break/*黑色*/
default:
setfillstyle(SOLID_FILL,BLUE)/*蓝色*/
}
}
int QpChange(int x,int y,int t)/*判断棋盘的变化*/
{
int i,j,k,kk,ii,jj,yes
yes=0
i=(x-120)/40/*计算数组元素的行下标*/
j=(y-120)/40/*计算数组元素的列下标*/
SetPlayColor(t)/*设置棋子变化的颜色*/
/*开始往8个方向判断变化*/
if(j<6)/*往右边*/
{
for(k=j+1k<8k++)
if(a[i][k]==a[i][j]||a[i][k]==0)/*遇到自己的棋子或空格结束*/
break
if(a[i][k]!=0&&k<8)
{
for(kk=j+1kk<k&&k<8kk++)/*判断右边*/
{
a[i][kk]=a[i][j]/*改变棋子颜色*/
fillellipse(120+i*40,120+kk*40,15,15)
}
if(kk!=j+1) /*条件成立则有棋子改变过颜色*/
yes=1
}
}
if(j>1)/*判断左边*/
{
for(k=j-1k>=0k--)
if(a[i][k]==a[i][j]||!a[i][k])
break
if(a[i][k]!=0&&k>=0)
{
for(kk=j-1kk>k&&k>=0kk--)
{
a[i][kk]=a[i][j]
fillellipse(120+i*40,120+kk*40,15,15)
}
if(kk!=j-1)
yes=1
}
}
if(i<6)/*判断下边*/
{
for(k=i+1k<8k++)
if(a[k][j]==a[i][j]||!a[k][j])
break
if(a[k][j]!=0&&k<8)
{
for(kk=i+1kk<k&&k<8kk++)
{
a[kk][j]=a[i][j]
fillellipse(120+kk*40,120+j*40,15,15)
}
if(kk!=i+1)
yes=1
}
}
if(i>1)/*判断上边*/
{
for(k=i-1k>=0k--)
if(a[k][j]==a[i][j]||!a[k][j])
break
if(a[k][j]!=0&&k>=0)
{
for(kk=i-1kk>k&&k>=0kk--)
{
a[kk][j]=a[i][j]
fillellipse(120+kk*40,120+j*40,15,15)
}
if(kk!=i-1)
yes=1
}
}
if(i>1&&j<6)/*右上*/
{
for(k=i-1,kk=j+1k>=0&&kk<8k--,kk++)
if(a[k][kk]==a[i][j]||!a[k][kk])
break
if(a[k][kk]&&k>=0&&kk<8)
{
for(ii=i-1,jj=j+1ii>k&&k>=0ii--,jj++)
{
a[ii][jj]=a[i][j]
fillellipse(120+ii*40,120+jj*40,15,15)
}
if(ii!=i-1)
yes=1
}
}
if(i<6&&j>1)/*左下*/
{
for(k=i+1,kk=j-1k<8&&kk>=0k++,kk--)
if(a[k][kk]==a[i][j]||!a[k][kk])
break
if(a[k][kk]!=0&&k<8&&kk>=0)
{
for(ii=i+1,jj=j-1ii<k&&k<8ii++,jj--)
{
a[ii][jj]=a[i][j]
fillellipse(120+ii*40,120+jj*40,15,15)
}
if(ii!=i+1)
yes=1
}
}
if(i>1&&j>1)/*左上*/
{
for(k=i-1,kk=j-1k>=0&&kk>=0k--,kk--)
if(a[k][kk]==a[i][j]||!a[k][kk])
break
if(a[k][kk]!=0&&k>=0&&kk>=0)
{
for(ii=i-1,jj=j-1ii>k&&k>=0ii--,jj--)
{
a[ii][jj]=a[i][j]
fillellipse(120+ii*40,120+jj*40,15,15)
}
if(ii!=i-1)
yes=1
}
}
if(i<6&&j<6)/* 右下*/
{
for(k=i+1,kk=j+1kk<8&&kk<8k++,kk++)
if(a[k][kk]==a[i][j]||!a[k][kk])
break
if(a[k][kk]!=0&&kk<8&&k<8)
{
for(ii=i+1,jj=j+1ii<k&&k<8ii++,jj++)
{
a[ii][jj]=a[i][j]
fillellipse(120+ii*40,120+jj*40,15,15)
}
if(ii!=i+1)
yes=1
}
}
return yes/*返回是否改变过棋子颜色的标记*/
}
void DoScore()/*处理分数*/
{
int i,j
score1=score2=0/*重新开始计分数*/
for(i=0i<8i++)
for(j=0j<8j++)
if(a[i][j]==1)/*分别统计两个人的分数*/
score1++
else
if(a[i][j]==2)
score2++
}
void PrintScore(int playnum)/*输出成绩*/
{
if(playnum==1)/*清除以前的成绩*/
{
setfillstyle(SOLID_FILL,BLUE)
bar(550,100,640,400)
}
setcolor(RED)
settextstyle(0,0,4)/*设置文本输出样式*/
if(playnum==1)/*判断输出哪个棋手的分,在不同的位置输出*/
{
sprintf(playone,"%d",score1)
outtextxy(550,200,playone)
}
else
{
sprintf(playtwo,"%d",score2)
outtextxy(550,300,playtwo)
}
setcolor(0)
}
void playWin()/*输出最后的胜利者结果*/
{
settextstyle(0,0,4)
setcolor(12)
if(score2>score1)/*开始判断最后的结果*/
outtextxy(100,50,"black win!")
else
if(score2<score1)
outtextxy(100,50,"white win!")
else
outtextxy(60,50,"you all win!")
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)