论坛的首页
勇芳的软件
教程和帮助
VisualFreeBasic编程文档
勇芳系列软件帮助说明教程
留言或交流
登录
搜索
登录
搜索
勇芳
累计撰写
330
篇文章
累计收到
0
条评论
首页
栏目
论坛的首页
勇芳的软件
教程和帮助
VisualFreeBasic编程文档
勇芳系列软件帮助说明教程
留言或交流
登录
作者 【1】 的文章
2026-1-22
VisualFreeBasic游戏趣味编程_7.3_小蛇向右移动
实现小蛇的移动功能是“贪吃蛇”游戏的开发难点,图7-4列出了小蛇向右移动前后二维数组的元素值,虚线框内为对应代码的实现步骤: 假设小蛇初始元素值为54321,其中1为蛇头、5432为蛇身、最大值5为蛇尾。首先将二维数组中所有大于0的元素加1,得到65432;然后将最大值6变为0,即去除了原来的蛇尾;最后将2右边的元素由0变成1,即实现了小蛇向右移动。 定义函数moveSnake( )处理小蛇移动的相关操作: Sub moveSnake() ' 移动小蛇及相关处理函数 Dim i As Long, j As Long For i = 0 To BLOCK_HEIGHT -1 '对行遍历 For j = 0 To BLOCK_WIDTH -1 '对列遍历 If Blocks(i, j) > 0 Then '大于0的为小蛇元素 Blocks(i, j) += 1 '让其+1 End If Next Next Dim As Long oldTail_i, oldTail_j, oldHead_i, oldHead_j '定义变量,存储旧蛇尾、旧蛇头坐标 Dim mm As Long '用于记录最大值 For i = 0 To BLOCK_HEIGHT -1 '对行遍历 For j = 0 To BLOCK_WIDTH -1 '对列遍历 If mm < Blocks(i, j) Then '如果当前元素值比max大 mm = Blocks(i, j) '更新max的值 oldTail_i = i ' 记录最大值的坐标,就是旧蛇尾的位置 oldTail_j = j End If If Blocks(i, j) = 2 Then '找到数值为2 oldHead_i = i ' 数值为2恰好是旧蛇头的位置 oldHead_j = j ' End If Next Next Dim newHead_i As Long = oldHead_i ' 设定变量存储新蛇头的位置 Dim newHead_j As Long = oldHead_j newHead_j = oldHead_j + 1 ' 向右移动,更新蛇头坐标 If newHead_j = BLOCK_WIDTH Then newHead_j = 0 Blocks(newHead_i, newHead_j) = 1 ' 新蛇头位置数值为1 Blocks(oldTail_i, oldTail_j) = 0 ' 旧蛇尾位置变成空白 End Sub 在updateWithoutInput( )函数中调用moveSnake( ): Sub updateWithoutInput() '与输入无关的更新 moveSnake() '调用小蛇移动函数 End Sub 通过以上操作则实现了小蛇自动向右移动,效果如图7-5所示。
2026年-1月-22日
61 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_7.2_基于二维数组的游戏地图
为了实现图7-1中网格状的游戏地图效果,这一节介绍二维数组的概念。首先输入并运行以下代码: Sub 游戏执行过程(hWndForm As hWnd) Dim a(2, 4) As Long Dim i As Long, j As Long For i = 0 To 2 For j = 0 To 4 a(i, j) = i * 10 + j Next Next For i = 0 To 2 For j = 0 To 4 Print a(i, j) Next Next End Sub 其中,Dim a(2, 4) As Long定义了二维数组a,有3行5列15个元素。通过 a(i, j)的形式可以访问二维数组的元素,下标i范围为0~2,下标j范围为0~4。 练习题7-1:生成一个4行4列的二维数组,元素取值为1~5的随机数,输出二维数组。如果二维数组中的元素为5,则将其元素值变为0,输出更新后的二维数组。样例输出如下所示。 二维数组也可以在定义时直接初始化,例如: Dim a(2, 3) As Long = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} 其中,{1,2,3,4}赋给第0行,{5,6,7,8}赋给第1行,{9,10,11,12}赋给第2行: 首先利用宏定义设定游戏画面高度上的格子数目HEIGHT、宽度上的格子数目WIDTH、每个小格子的大小BLOCK_SIZE: #define BLOCK_HEIGHT 30 ' 高度上一共30个小格子 #define BLOCK_WIDTH 40 ' 宽度上一共40个小格子 #define BLOCK_SIZE 20 ' 每个小格子的长宽大小 利用二维数组存储所有格子的信息: Dim Blocks(BLOCK_HEIGHT,BLOCK_WIDTH) As Long ' 二维数组,用于记录所有的游戏数据 利用两重for循环,可以设定元素Blocks(i,j)的值为随机整数: Dim i As Long, j As Long For i = 0 To BLOCK_HEIGHT -1 For j = 0 To BLOCK_WIDTH -1 Blocks(i, j) = Int(Rnd * 30) ' 赋值为随机数 Next Next 然后可以根据元素数值设定填充颜色,在对应位置绘制小方格: gg.Pen 1, BGR(255,255,255) For i = 0 To BLOCK_HEIGHT -1 For j = 0 To BLOCK_WIDTH -1 gg.Brush HSBtoRGB_Gdi(HSB(Blocks(i, j)*10, 90, 100, 255)) '根据元素值设定填充颜色 gg.DrawFrame j*BLOCK_SIZE,i*BLOCK_SIZE,BLOCK_SIZE,BLOCK_SIZE Next Next 全部源码 #define BLOCK_HEIGHT 17 ' 高度上一共30个小格子 #define BLOCK_WIDTH 27 ' 宽度上一共40个小格子 #define BLOCK_SIZE 15 ' 每个小格子的长宽大小 Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim Blocks(BLOCK_HEIGHT -1, BLOCK_WIDTH -1) As Long ' 二维数组,用于记录所有的游戏数据 Dim i As Long, j As Long For i = 0 To BLOCK_HEIGHT -1 For j = 0 To BLOCK_WIDTH -1 Blocks(i, j) = Int(Rnd * 30) ' 赋值为随机数 Next Next gg.Pen 1, BGR(255,255,255) For i = 0 To BLOCK_HEIGHT -1 For j = 0 To BLOCK_WIDTH -1 gg.Brush HSBtoRGB_Gdi(HSB(Blocks(i, j)*10, 90, 100, 255)) '根据元素值设定填充颜色 gg.DrawFrame j*BLOCK_SIZE,i*BLOCK_SIZE,BLOCK_SIZE,BLOCK_SIZE Next Next End Sub 二维数组Blocks(HEIGHT,WIDTH)中也可以记录蛇的信息。设定元素值为0表示空,画出灰色的方格;元素值为1表示蛇头,蛇头后的蛇身依次为2、3、4、5等正整数,画出彩色的方格,如图7-3所示。 #define BLOCK_HEIGHT 17 ' 高度上一共30个小格子 #define BLOCK_WIDTH 27 ' 宽度上一共40个小格子 #define BLOCK_SIZE 15 ' 每个小格子的长宽大小 Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim Blocks(BLOCK_HEIGHT -1, BLOCK_WIDTH -1) As Long ' 二维数组,用于记录所有的游戏数据 Dim i As Long, j As Long Blocks(BLOCK_HEIGHT / 2, Int(BLOCK_WIDTH / 2)) = 1 '画面中间画蛇头,数字为1 For i = 1 To 4 Blocks(BLOCK_HEIGHT / 2, Int(BLOCK_WIDTH / 2) - i) = i + 1 '向左依次4个蛇身,数值依次为2、3、4、5 Next gg.Pen 1, BGR(255, 255, 255) '对二维数组所有元素遍历 For i = 0 To BLOCK_HEIGHT -1 For j = 0 To BLOCK_WIDTH -1 If Blocks(i, j) > 0 Then gg.Brush HSBtoRGB_Gdi(HSB(Blocks(i, j) * 10, 90, 100, 255)) '根据元素值设定填充颜色 Else gg.Brush BGR(165, 165, 165) 'GDI的颜色值。 End If gg.DrawFrame j *BLOCK_SIZE, i *BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE Next Next End Sub 最后,我们用7.1节的游戏框架重构,将Blocks设为全局变量,初始化代码放到startup()中,绘制功能放到show()中: #define BLOCK_HEIGHT 17 ' 高度上一共30个小格子 #define BLOCK_WIDTH 27 ' 宽度上一共40个小格子 #define BLOCK_SIZE 15 ' 每个小格子的长宽大小 '全局变量定义 Dim Shared Blocks(BLOCK_HEIGHT -1, BLOCK_WIDTH -1) As Long ' 二维数组,用于记录所有的游戏数据 Sub startup(gg As yGDI) '初始化函数 Dim i As Long, j As Long Blocks(BLOCK_HEIGHT / 2, Int(BLOCK_WIDTH / 2)) = 1 '画面中间画蛇头,数字为1 For i = 1 To 4 Blocks(BLOCK_HEIGHT / 2, Int(BLOCK_WIDTH / 2) - i) = i + 1 '向左依次4个蛇身,数值依次为2、3、4、5 Next gg.Pen 1, BGR(255, 255, 255) End Sub Sub show(gg As yGDI) '绘制函数 gg.Cls Dim i As Long, j As Long '对二维数组所有元素遍历 For i = 0 To BLOCK_HEIGHT -1 For j = 0 To BLOCK_WIDTH -1 If Blocks(i, j) > 0 Then gg.Brush HSBtoRGB_Gdi(HSB(Blocks(i, j) * 10, 90, 100, 255)) '根据元素值设定填充颜色 Else gg.Brush BGR(165, 165, 165) 'GDI的颜色值。 End If gg.DrawFrame j *BLOCK_SIZE, i *BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE Next Next gg.Redraw End Sub Sub updateWithoutInput() '与输入无关的更新 End Sub Sub updateWithInput() ' 和输入有关的更新 End Sub Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm startup(gg) '初始化函数,仅执行一次 Do show(gg) ' 进行绘制 updateWithoutInput() ' 和输入无关的更新 updateWithInput() ' 和输入有关的更新 sleep 10 Loop End Sub
2026年-1月-22日
57 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_7.1_变量作用域与游戏框架
在程序中变量起作用的范围,称为变量的作用域。根据作用域的不同,FB语言中的变量可分为局部变量和全局变量。 在函数内部定义的变量称为局部变量,其作用域从变量定义处开始,到}处结束。 Sub fun() Dim a As Long '局部变量,仅能在fun函数内部使用 a=10 End Sub Sub 游戏执行过程(hWndForm As hWnd) Dim x As Long '局部变量,仅能在[游戏执行过程]函数内部使用 x = 1 End Sub 在以上代码中,变量a的作用域在函数fun()内部,如果在其他区域使用变量a,程序报错;变量x的作用域在函数【游戏执行过程()】内部,如果在其他区域使用变量x,程序报错。 在所有函数之外定义的变量称为全局变量,其作用域从变量定义处开始,到整个程序最后结束。 Dim Shared m As Long '全局变量,整个程序都可以访问 Sub fun() m=3 End Sub Sub 游戏执行过程(hWndForm As hWnd) Print mm = 2 Print m fun() Print m End Sub 在上面代码中,变量m在函数外定义,为全局变量,因此在函数外、函数fun()与main()内都可以访问。程序运行后输出: 1 2 3 提示 如果全局变量与局部变量同名,则在局部变量的作用域内访问的是局部变量,全局变量将被“屏蔽” 利用函数和变量作用域的知识,我们设定了一个简化的游戏开发框架: '全局变量定义 Sub startup() '初始化函数 End Sub Sub show() '绘制函数 End Sub Sub updateWithoutInput() '与输入无关的更新 End Sub Sub updateWithInput() ' 和输入有关的更新 End Sub Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm startup() ' 初始化函数,仅执行一次 Do gg.Cls show() ' 进行绘制 updateWithoutInput() '和输入无关的更新 updateWithInput() ' 和输入有关的更新 gg.Redraw Sleep 100 Loop End Sub 首先在函数外定义一些游戏数据变量,这些全局变量在整个程序中均可以访问。具体的游戏功能在startup()、show()、updateWithoutInput()、updateWithInput()这4个函数中实现。 程序从主函数开始,首先运行一次startup(),进行游戏的初始化。然后开始循环执行3个函数:show()进行绘制、updateWithoutInput()执行和输入无关的更新、updateWithInput()执行和输入有关的更新。
2026年-1月-22日
53 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_第7章_“贪吃蛇”游戏
在本章我们将探讨如何编写“贪吃蛇”游戏,效果如图7-1所示。键盘控制小蛇上、下、左、右移动,吃到食物后长度加1;蛇头碰到自身或窗口边缘,游戏失败。 本章首先探讨了如何利用全局变量和函数的知识,设计一个游戏开发框架;然后介绍了二维数组的知识,构造地图和小蛇的方法,解析了如何实现小蛇向4个方向移动;接着讲解了静态变量的概念,以及如何进行时间控制的改进;最后讲解了如何实现失败判断与显示、吃食物增加长度的功能。
2026年-1月-22日
59 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_6.7_按键互动
当按下空格键后,将circleNum设为0,相当于清除所有已有的圆;将drawMode加1,从而切换为下一种绘图模式: Do If IsKeyPress(VK_SPACE) Then '按下空格键 drawMode += 1 If drawMode > 4 Then drawMode = 1 Exit Do End If Sleep 100 Loop 全部代码 Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim 圆心x(99) As Long '数组存储所有圆心的x坐标 Dim 圆心y(99) As Long '数组存储所有圆心的y坐标 Dim 半径(99) As Long '数组存储所有圆的半径 Dim 圆的个数 As Long = 0 Dim 游戏W As Long = DpiunScaleI(Form1.ScaleWidth) '游戏区的尺寸 Dim 游戏H As Long = DpiunScaleI(Form1.ScaleHeight) Dim 圆的最小半径 As Long = 5 Dim 圆的最大半径 As Long = 40 Dim circleNum As Long ' 生成的圆的个数 Dim As Long x, y, r ' 新增圆的圆心坐标、半径 Dim isNewCircleOK As Long '用于判断新生成的圆是否OK '生成圆,把数据保存在数组中 Dim i As Long Dim drawMode As Long = 1 Do While 圆的个数 < 100 '当圆的个数小于100时,循环运行 isNewCircleOK = 0 ' 假设开始不OK While isNewCircleOK = 0 ' 当新生成的圆不OK时,重复生成新圆进行比较 Randomize x = Int(Rnd *游戏W) '新圆的圆心x坐标 Randomize y = Int(Rnd *游戏H) '新圆的圆心y坐标 ' r = 圆的最小半径 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i), 圆心y(i), 半径(i), x, y, r) Then Exit For ' 如果已有圆和新圆相交跳出循环,此时i<圆的个数 Next If (i = 圆的个数) Then ' 如果上面for语句都不跳出,说明i等于circleNum isNewCircleOK = 1 ' 这个新生成的圆和已有圆都不相交 End If Wend isNewCircleOK = 0 ' 继续设为不OK,下面要让这个新圆的半径最大 While isNewCircleOK = 0 And r < 圆的最大半径 ' 当不OK,并且新圆的半径小于最大半径时 r += 1 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i), 圆心y(i), 半径(i), x, y, r) Then isNewCircleOK = 1 ' 一旦和一个旧圆相交,这时新圆OK Exit For ' 因为新圆半径已经达到最大的情况,这时跳出循环 End If Next Wend 圆心x(圆的个数) = x '把新圆的圆心坐标添加到数组中 圆心y(圆的个数) = y 半径(圆的个数) = r '把新圆的半径添加到数组中 圆的个数 += 1 '圆的个数+1 Wend gg.Cls For i = 0 To 圆的个数 -1 'Dim drawMode As Long = randBetweenMinMax(1, 4) ' 随机生成一种绘制模式 ' 根据不同绘图模式进行绘制 If (drawMode = 1) Then DrawCircles1(gg, 圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 2) Then DrawCircles2(gg, 圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 3) Then DrawCircles3(gg, 圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 4) Then DrawCircles4(gg, 圆心x(i), 圆心y(i), 半径(i)) End If Next gg.Redraw Sleep 500 Do If IsKeyPress(VK_SPACE) Then '按下空格键 圆的个数 =0 drawMode += 1 If drawMode > 4 Then drawMode = 1 Exit Do End If Sleep 100 Loop Loop End Sub
2026年-1月-22日
49 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_6.6_函数封装多种绘制效果
对于圆心坐标(x,y)、半径r的圆,定义4个函数,可以实现不同的绘制效果: '填充黄色圆绘制 Sub DrawCircles1(gg As yGDI, x As Long, y As Long, r As Long) gg.Pen 1, BGR(105, 105, 105) 'GDI的颜色值。 gg.Brush BGR(204, 204, 0) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 End Sub '填充随机颜色圆绘制 Sub DrawCircles2(gg As yGDI, x As Long, y As Long, r As Long) gg.Pen 1, BGR(255, 255, 255) 'GDI的颜色值。 Randomize Dim h As Long = Rnd *360 gg.Brush HSBtoRGB_Gdi(HSB(h,60,80,255) ) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 End Sub '填充随机颜色同心圆绘制 Sub DrawCircles3(gg As yGDI, x As Long, y As Long, r As Long) gg.Pen 1, BGR(255, 255, 255) 'GDI的颜色值。 While r > 0 Randomize Dim h As Long = Rnd * 360 gg.Brush HSBtoRGB_Gdi(HSB(h, 60, 80, 255)) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 r -= 5 Wend End Sub '随机颜色同心圆线条绘制 Sub DrawCircles4(gg As yGDI, x As Long, y As Long, r As Long) gg.Brush While r > 0 Randomize Dim h As Long = Rnd * 360 gg.Pen 1, HSBtoRGB_Gdi(HSB(h, 90, 80, 255)) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 r -= 5 Wend End Sub 在主函数中首先生成[1,4]之间的随机数drawMode,然后根据drawMode的值分别调用不同的绘制函数,即可生成对应的绘制效果。 For i = 0 To 圆的个数 -1 Dim drawMode As Long = randBetweenMinMax(1, 4) ' 随机生成一种绘制模式 ' 根据不同绘图模式进行绘制 If (drawMode = 1) Then DrawCircles1(gg,圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 2) Then DrawCircles2(gg,圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 3) Then DrawCircles3(gg,圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 4) Then DrawCircles4(gg,圆心x(i), 圆心y(i), 半径(i)) End If Next 绘制效果如图6-8所示。 完整代码 ' 判断两个圆是否相交 Function isTwoCirclesIntersect(x1 As Long, y1 As Long,r1 As Long , x2 As Long, y2 As Long, r2 As Long ) As Long If (Dist2Points(x1, y1, x2, y2) < r1 + r2) Then Return 1 Else Return 0 End Function ' 求解两个点之间的距离 Function Dist2Points(x1 As Long, y1 As Long, x2 As Long, y2 As Long) As Long Dim result As Long result = Sqr((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) Return result End Function '生成[min,max]之间的随机整数 Function randBetweenMinMax(小 As Long, 大 As Long) As Long Randomize Dim r As Long = int(Rnd * (大 - 小 + 1)) + 小 Return r End Function '填充黄色圆绘制 Sub DrawCircles1(gg As yGDI, x As Long, y As Long, r As Long) gg.Pen 1, BGR(105, 105, 105) 'GDI的颜色值。 gg.Brush BGR(204, 204, 0) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 End Sub '填充随机颜色圆绘制 Sub DrawCircles2(gg As yGDI, x As Long, y As Long, r As Long) gg.Pen 1, BGR(255, 255, 255) 'GDI的颜色值。 Randomize Dim h As Long = Rnd *360 gg.Brush HSBtoRGB_Gdi(HSB(h,60,80,255) ) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 End Sub '填充随机颜色同心圆绘制 Sub DrawCircles3(gg As yGDI, x As Long, y As Long, r As Long) gg.Pen 1, BGR(255, 255, 255) 'GDI的颜色值。 While r > 0 Randomize Dim h As Long = Rnd * 360 gg.Brush HSBtoRGB_Gdi(HSB(h, 60, 80, 255)) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 r -= 5 Wend End Sub '随机颜色同心圆线条绘制 Sub DrawCircles4(gg As yGDI, x As Long, y As Long, r As Long) gg.Brush While r > 0 Randomize Dim h As Long = Rnd * 360 gg.Pen 1, HSBtoRGB_Gdi(HSB(h, 90, 80, 255)) 'GDI的颜色值。 gg.DrawEllipse x - r, y - r, r * 2, r * 2 r -= 5 Wend End Sub Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim 圆心x(99) As Long '数组存储所有圆心的x坐标 Dim 圆心y(99) As Long '数组存储所有圆心的y坐标 Dim 半径(99) As Long '数组存储所有圆的半径 Dim 圆的个数 As Long = 0 Dim 游戏W As Long = DpiunScaleI(Form1.ScaleWidth) '游戏区的尺寸 Dim 游戏H As Long = DpiunScaleI(Form1.ScaleHeight) Dim 圆的最小半径 As Long = 5 Dim 圆的最大半径 As Long = 40 Dim circleNum As Long ' 生成的圆的个数 Dim As Long x, y, r ' 新增圆的圆心坐标、半径 Dim isNewCircleOK As Long '用于判断新生成的圆是否OK '生成圆,把数据保存在数组中 Dim i As Long While 圆的个数 < 100 '当圆的个数小于100时,循环运行 isNewCircleOK = 0 ' 假设开始不OK While isNewCircleOK = 0 ' 当新生成的圆不OK时,重复生成新圆进行比较 x = Int(Rnd *游戏W) '新圆的圆心x坐标 y = Int(Rnd *游戏H) '新圆的圆心y坐标 ' r = 圆的最小半径 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i), 圆心y(i), 半径(i), x, y, r) Then Exit For ' 如果已有圆和新圆相交跳出循环,此时i<圆的个数 Next If (i = 圆的个数) Then ' 如果上面for语句都不跳出,说明i等于circleNum isNewCircleOK = 1 ' 这个新生成的圆和已有圆都不相交 End If Wend isNewCircleOK = 0 ' 继续设为不OK,下面要让这个新圆的半径最大 While isNewCircleOK = 0 And r < 圆的最大半径 ' 当不OK,并且新圆的半径小于最大半径时 r += 1 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i), 圆心y(i), 半径(i), x, y, r) Then isNewCircleOK = 1 ' 一旦和一个旧圆相交,这时新圆OK Exit For ' 因为新圆半径已经达到最大的情况,这时跳出循环 End If Next Wend 圆心x(圆的个数) = x '把新圆的圆心坐标添加到数组中 圆心y(圆的个数) = y 半径(圆的个数) = r '把新圆的半径添加到数组中 圆的个数 += 1 '圆的个数+1 Wend gg.Pen 1, BGR(105, 105, 105) 'GDI的颜色值。 gg.Brush BGR(204, 204, 0) 'GDI的颜色值。 For i = 0 To 圆的个数 -1 Dim drawMode As Long = randBetweenMinMax(1, 4) ' 随机生成一种绘制模式 ' 根据不同绘图模式进行绘制 If (drawMode = 1) Then DrawCircles1(gg,圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 2) Then DrawCircles2(gg,圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 3) Then DrawCircles3(gg,圆心x(i), 圆心y(i), 半径(i)) ElseIf (drawMode = 4) Then DrawCircles4(gg,圆心x(i), 圆心y(i), 半径(i)) End If Next End Sub
2026年-1月-22日
50 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_6.5_新圆半径最大化
为了进一步改进图案效果,在这一节中让生成的新圆半径尽量大。 rmin为圆的最小半径,rmax为圆的最大半径。首先在随机位置(x,y)处生成半径为rmin的圆,如果生成的新圆和之前已生成的圆相交,如图6-6中“1”处所示,则放弃该圆,重新随机生成。 如果生成的新圆和之前已生成的圆都不相交,如图6-6中“2”处所示,则不断增大新圆的半径,直至找到第一个与该圆相切的圆,或者达到rmax为止。 While 圆的个数 < 100 '当圆的个数小于100时,循环运行 isNewCircleOK = 0 ' 假设开始不OK While isNewCircleOK = 0 ' 当新生成的圆不OK时,重复生成新圆进行比较 x = Int(Rnd *游戏W) '新圆的圆心x坐标 y = Int(Rnd *游戏H) '新圆的圆心y坐标 ' r = 圆的最小半径 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i), 圆心y(i), 半径(i), x, y, r) Then Exit For ' 如果已有圆和新圆相交跳出循环,此时i<圆的个数 Next If (i = 圆的个数) Then ' 如果上面for语句都不跳出,说明i等于circleNum isNewCircleOK = 1 ' 这个新生成的圆和已有圆都不相交 End If Wend isNewCircleOK = 0 ' 继续设为不OK,下面要让这个新圆的半径最大 While isNewCircleOK = 0 And r < 圆的最大半径 ' 当不OK,并且新圆的半径小于最大半径时 r += 1 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i), 圆心y(i), 半径(i), x, y, r) Then isNewCircleOK = 1 ' 一旦和一个旧圆相交,这时新圆OK Exit For ' 因为新圆半径已经达到最大的情况,这时跳出循环 End If Next Wend 圆心x(圆的个数) = x '把新圆的圆心坐标添加到数组中 圆心y(圆的个数) = y 半径(圆的个数) = r '把新圆的半径添加到数组中 圆的个数 += 1 '圆的个数+1 Wend 程序运行后输出如图所示。 提示 While 条件 是一个条件循环语句,只要条件为真,那么一直循环,一直到条件为假才退出循环。
2026年-1月-22日
42 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_6.4_函数的定义与应用
FB 程序是由函数组成的,每一个FB程序都包含这样的结构: Sub Form1_Shown(hWndForm As hWnd, UserData As Integer) Threaddetach ThreadCreate(Cast(Any Ptr, @游戏执行过程), hWndForm) End Sub Sub 游戏执行过程(hWndForm As hWnd) End Sub 在之前的章节中,我们已经调用了很多函数,比如,print()函数输出变量的值、fillcircle()函数画圆、abs()函数求绝对值等。我们也可以定义自己的函数并调用执行: Sub 游戏执行过程(hWndForm As hWnd) printStars() End Sub Sub printStars() Print "*****" End Sub 以上代码首先定义了函数Sub printStars()。其中,printStars为函数的名字,后面跟上圆括号,Sub 表示函数没有返回值。 End Sub是函数结束,从开始到结束是函数体,这里输出一行5个星号。 函数定义后,在主函数中printStars()调用函数,即执行了函数内部的所有语句。程序运行后输出: 练习题6-2:调用6-4-1.cpp中定义的函数,输出如下效果: 函数定义的括号内,还可以添加接受的参数,修改的代码如下,让用户设定要输出的星号的个数: Sub 游戏执行过程(hWndForm As hWnd) Dim i As Long For i = 1 To 4 printStars(i) Next End Sub Sub printStars(num As Long ) Print String(num, "*") End Sub Sub printStars(num As Long )表示函数接受整型变量num为参数,函数内部输出一行num个星号。调用函数时,括号内写不同的数字,就可以输出对应数字个数的星号。主函数中利用for语句,可以依次输出1~5个星号。程序运行后输出: * ** *** **** 函数也可以接受多个参数,参数间以逗号间隔。 Sub 游戏执行过程(hWndForm As hWnd) printStars("+",3) printStars("@",5) printStars("0",8) End Sub Sub printStars(ch As String , num As Long ) Print String(num, ch) End Sub 以上函数接受两个参数:ch为对应的字符、num为要输出的字符的个数。程序运行后,分别输出3个+、5个@、8个0。程序运行后输出: +++ @@@@@ 00000000 回顾求绝对值函数的用法: Dim x As Long = abs( -3) Print x 以上代码将函数计算结果返回并赋给变量x。同样,我们自定义的函数也可以定义返回值。以下代码定义了函数maxfun(),即返回两个整数中的最大值。 Sub 游戏执行过程(hWndForm As hWnd) Dim result As Long = maxfun(3, 5) Print result End Sub Function maxfun(x As Long ,y As Long ) As Long Dim max As Long = x If x < y Then max = y Return max End Function 程序运行后输出:5 函数定义Function maxfun() As Long中,尾部的As Long表示函数的返回值为整型。函数中首先求出参数x、y的最大值,赋给变量max。利用return max语句将计算结果max返回出来,同时退出maxfun()函数的运行。调用函数时,即可将函数的返回值赋给其他变量。 利用函数的返回值,也可以实现更复杂的功能,比如,以下代码可以求解3个数的最大值: Dim result As Long = maxfun(maxfun(3,5),4) 提示 当我们要解决的问题比较复杂时,可以把问题分块,使得每一块功能相对独立,用一个独立的函数来实现。用好函数可以降低程序设计的复杂性、提高代码的可靠性,避免程序开发的重复劳动,并易于程序维护和功能扩充。 回顾6-3,求解两个点之间的距离是一个常见的功能,所以可以将其封装为函数,方便多次调用: ' 求解两个点之间的距离 Function Dist2Points(x1 As Long, y1 As Long, x2 As Long, y2 As Long) As Long Dim result As Long result = Sqr((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) Return result End Function 其中,sqr()为求平方根函数 进一步,定义函数判断图6-4中的两个圆是否相交,其中调用了刚定义的Dist2Points()函数。如果相交则返回1,函数退出;否则返回0。 ' 判断两个圆是否相交 Function isTwoCirclesIntersect(x1 As Long, y1 As Long,r1 As Long , x2 As Long, y2 As Long, r2 As Long ) As Long If (Dist2Points(x1, y1, x2, y2) < r1 + r2) Then Return 1 Else Return 0 End Function 生成两个数之间的随机整数也是一个常见的功能,可以封装为函数: '生成[min,max]之间的随机整数 Function randBetweenMinMax(小 As Long, 大 As Long) As Long Randomize Dim r As Long = int(Rnd * (大 - 小 + 1)) + 小 Return r End Function 利用上面定义的3个函数改进6.3节的代码,程序的结构会更加清晰,也更容易理解: ' 判断两个圆是否相交 Function isTwoCirclesIntersect(x1 As Long, y1 As Long,r1 As Long , x2 As Long, y2 As Long, r2 As Long ) As Long If (Dist2Points(x1, y1, x2, y2) < r1 + r2) Then Return 1 Else Return 0 End Function ' 求解两个点之间的距离 Function Dist2Points(x1 As Long, y1 As Long, x2 As Long, y2 As Long) As Long Dim result As Long result = Sqr((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) Return result End Function '生成[min,max]之间的随机整数 Function randBetweenMinMax(小 As Long, 大 As Long) As Long Randomize Dim r As Long = int(Rnd * (大 - 小 + 1)) + 小 Return r End Function Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim 圆心x(99) As Long '数组存储所有圆心的x坐标 Dim 圆心y(99) As Long '数组存储所有圆心的y坐标 Dim 半径(99) As Long '数组存储所有圆的半径 Dim 圆的个数 As Long = 0 Dim 游戏W As Long = DpiScaleI(Form1.ScaleWidth) '游戏区的尺寸 Dim 游戏H As Long = DpiScaleI(Form1.ScaleHeight) Dim 圆的最小半径 As Long = 5 Dim 圆的最大半径 As Long = 40 Dim circleNum As Long ' 生成的圆的个数 Dim As Long x, y, r ' 新增圆的圆心坐标、半径 Dim isNewCircleOK As Long '用于判断新生成的圆是否OK '生成圆,把数据保存在数组中 Dim i As Long While 圆的个数 < 100 '当圆的个数小于100时,循环运行 isNewCircleOK = 0 ' 假设开始不OK While isNewCircleOK = 0 ' 当新生成的圆不OK时,重复生成新圆进行比较 x = Int(Rnd *游戏W) '新圆的圆心x坐标 y = Int(Rnd *游戏H) '新圆的圆心y坐标 ' r =randBetweenMinMax(圆的最小半径,圆的最大半径) '新圆的半径 For i = 0 To 圆的个数 -1 If isTwoCirclesIntersect(圆心x(i),圆心y(i),半径(i),x,y,r) Then Exit For ' 如果已有圆和新圆相交跳出循环,此时i<圆的个数 Next If (i = 圆的个数) Then ' 如果上面for语句都不跳出,说明i等于circleNum isNewCircleOK = 1 ' 这个新生成的圆和已有圆都不相交 End If Wend 圆心x(圆的个数) = x '把新圆的圆心坐标添加到数组中 圆心y(圆的个数) = y 半径(圆的个数) = r '把新圆的半径添加到数组中 圆的个数 += 1 '圆的个数+1 Wend gg.Pen 1, BGR(105, 105, 105) 'GDI的颜色值。 gg.Brush BGR(204, 204, 0) 'GDI的颜色值。 For 圆的个数 = 1 To 100 gg.Cls For i = 0 To 圆的个数 -1 gg.DrawEllipse 圆心x(i) - 半径(i), 圆心y(i) - 半径(i), 半径(i) * 2, 半径(i) * 2 Next gg.DrawString 10, 10, Str(圆的个数) gg.Redraw Sleep 50 Next End Sub 提示 在FFB语言中,函数和变量一样都需要先定义、后使用。
2026年-1月-22日
45 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_6.3_新圆不和已有圆相交
假设有两个圆,其圆心坐标分别为(x1,y1)、(x2,y2),半径分别为r1、r2,如图6-4所示。 记录两个圆心之间距离的平方dist2 = (x1−x2)(x1−x2)+(y1−y2)(y1−y2)。当两个圆正好相切时,圆心距离平方r2 = (r1+r2)(r1+r2)。当dist2<r2时,两个圆相交。 每次随机生成一个新圆后,首先与所有已经生成的圆比较,如果和任何一个圆相交,则重新生成一个新圆;如果新圆和所有已生成的圆都不相交,则循环结束,将此新圆添加到数组中。完整代码参看 Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim 圆心x(99) As Long '数组存储所有圆心的x坐标 Dim 圆心y(99) As Long '数组存储所有圆心的y坐标 Dim 半径(99) As Long '数组存储所有圆的半径 Dim 圆的个数 As Long = 0 Dim 游戏W As Long = DpiScaleI(Form1.ScaleWidth) '游戏区的尺寸 Dim 游戏H As Long = DpiScaleI(Form1.ScaleHeight) Dim 圆的最小半径 As Long = 5 Dim 圆的最大半径 As Long = 40 Dim circleNum As Long ' 生成的圆的个数 Dim As Long x, y, r ' 新增圆的圆心坐标、半径 Dim isNewCircleOK As Long '用于判断新生成的圆是否OK '生成圆,把数据保存在数组中 Dim i As Long While 圆的个数 < 100 '当圆的个数小于100时,循环运行 isNewCircleOK = 0 ' 假设开始不OK While isNewCircleOK = 0 ' 当新生成的圆不OK时,重复生成新圆进行比较 x = Int(Rnd *游戏W) '新圆的圆心x坐标 y = Int(Rnd *游戏H) '新圆的圆心y坐标 ' r = Int(Rnd * (圆的最大半径 - 圆的最小半径 + 1)) + 圆的最小半径 '新圆的半径 For i = 0 To 圆的个数 -1 Dim dist2 As Long = (圆心x(i) - x) * (圆心x(i) - x) + (圆心y(i) - y) * (圆心y(i) - y) Dim r2 As Long = (半径(i) + r) * (半径(i) + r) If (dist2 < r2) Then ' 如果已有圆和新圆相交 Exit For '跳出循环,此时i<圆的个数 End If Next If (i = 圆的个数) Then ' 如果上面for语句都不跳出,说明i等于circleNum isNewCircleOK = 1 ' 这个新生成的圆和已有圆都不相交 End If Wend 圆心x(圆的个数) = x '把新圆的圆心坐标添加到数组中 圆心y(圆的个数) = y 半径(圆的个数) = r '把新圆的半径添加到数组中 圆的个数 += 1 '圆的个数+1 Wend gg.Pen 1, BGR(105, 105, 105) 'GDI的颜色值。 gg.Brush BGR(204, 204, 0) 'GDI的颜色值。 For 圆的个数 = 1 To 100 gg.Cls For i = 0 To 圆的个数 -1 gg.DrawEllipse 圆心x(i) - 半径(i), 圆心y(i) - 半径(i), 半径(i) * 2, 半径(i) * 2 Next gg.DrawString 10, 10, Str(圆的个数) gg.Redraw Sleep 100 Next End Sub 程序运行后输出如图
2026年-1月-22日
45 阅读
0 评论
VisualFreeBasic编程文档
2026-1-22
VisualFreeBasic游戏趣味编程_6.2_每次增加一个随机圆
为了显示圆生成的过程,我们修改6-1的代码,实现每隔100毫秒,添加一个随机圆并绘制。完整代码参看 Sub 游戏执行过程(hWndForm As hWnd) Dim gg As yGDI = hWndForm Dim 圆心x(99) As Long '数组存储所有圆心的x坐标 Dim 圆心y(99) As Long '数组存储所有圆心的y坐标 Dim 半径(99) As Long '数组存储所有圆的半径 Dim 圆的个数 As Long = 100 Dim 游戏W As Long = DpiScaleI(Form1.ScaleWidth) '游戏区的尺寸 Dim 游戏H As Long = DpiScaleI(Form1.ScaleHeight) Dim 圆的最小半径 As Long = 5 Dim 圆的最大半径 As Long = 40 '生成圆,把数据保存在数组中 Dim i As Long For i = 0 To 圆的个数 -1 圆心x(i) = Int(Rnd *游戏W) 圆心y(i) = Int(Rnd *游戏H) 半径(i) = Int(Rnd * (圆的最大半径 - 圆的最小半径 + 1)) + 圆的最小半径 Next gg.Pen 1, BGR(105, 105, 105) 'GDI的颜色值。 gg.Brush BGR(204, 204, 0) 'GDI的颜色值。 For 圆的个数 = 1 To 100 gg.Cls For i = 0 To 圆的个数 -1 gg.DrawEllipse 圆心x(i) - 半径(i), 圆心y(i) - 半径(i), 半径(i) * 2, 半径(i) * 2 Next gg.DrawString 10,10,Str(圆的个数) gg.Redraw Sleep 100 Next End Sub
2026年-1月-22日
48 阅读
0 评论
VisualFreeBasic编程文档
10
11
12
13
14