通过写“猜数字”游戏学习 Fortran
Fortran 是在打孔卡时代编写的语言,因此它的语法非常有限。但你仍然可以用它编写有用和有趣的程序。
Fortran 77 是我学习的第一门编译型编程语言。一开始时,我自学了如何在 Apple II 上用 BASIC 编写程序,后来又学会在 DOS 上用 QBasic 编写程序。但是当我去大学攻读物理学时,我又学习了 Fortran。
Fortran 曾经在科学计算中很常见。曾几何时,所有计算机系统都有一个 Fortran 编译器。Fortran 曾经像今天的 Python 一样无处不在。因此,如果你是像我这样的物理学专业学生,在 1990 年代工作,那你肯定学习了 Fortran。
我一直认为 Fortran 与 BASIC 有点相似,所以每当我需要编写一个简短程序,来分析实验室数据或执行其他一些数值分析时,我都会很快想到 Fortran。我在空闲时用 Fortran 编写了一个“猜数字”游戏,其中计算机会在 1 到 100 之间选择一个数字,并让我猜这个数字。程序会一直循环,直到我猜对了为止。
“猜数字”程序练习了编程语言中的几个概念:如何为变量赋值、如何编写语句以及如何执行条件判断和循环。这是学习新编程语言时一个很好的的实践案例。
Fortran 编程基础
虽然 Fortran 这些年来一直在更新,但我最熟悉的还是 Fortran 77,这是我多年前学习的实现版本。Fortran 是程序员还在打孔卡上编程的年代创建的,因此“经典” Fortran 仅限于处理可以放在打孔卡上的数据。这意味着你只能编写符合以下限制条件的经典 Fortran 程序(LCTT 译注:后来的 Fortran 95 等版本已经对这些限制做了很大的改进,如有兴趣建议直接学习新版):
- 每张卡只允许一行源代码。
- 仅识别第 1-72 列(最后八列,73-80,保留给卡片分类器)。
- 行号(“标签”)位于第 1-5 列。
- 程序语句在第 7-72 列。
- 要表示跨行,请在第 6 列中输入一个连续字符(通常是
+
)。 - 要创建注释行,请在第 1 列中输入
C
或*
。 - 只有字符
A
到Z
(大写字母)、0
到9
(数字)和特殊字符= + - * / ( ) , . $ ' :
和空格能够使用。
虽然有这些限制,你仍然可以编写非常有用和有趣的程序。
在 Fortran 中猜数字
通过编写“猜数字”游戏来探索 Fortran。这是我的实现代码:
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C PROGRAM TO GUESS A NUMBER 1-100
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
PROGRAM GUESSNUM
INTEGER SEED, NUMBER, GUESS
PRINT *, 'ENTER A RANDOM NUMBER SEED'
READ *, SEED
CALL SRAND(SEED)
NUMBER = INT( RAND(0) * 100 + 1 )
PRINT *, 'GUESS A NUMBER BETWEEN 1 AND 100'
10 READ *, GUESS
IF (GUESS.LT.NUMBER) THEN
PRINT *, 'TOO LOW'
ELSE IF (GUESS.GT.NUMBER) THEN
PRINT *, 'TOO HIGH'
ENDIF
IF (GUESS.NE.NUMBER) GOTO 10
PRINT *, 'THATS RIGHT!'
END
如果你熟悉其他编程语言,你大概可以通过阅读源代码来弄清楚这个程序在做什么。前三行是注释块,表示程序的功能。第四行 PROGRAM GUESSNUM
将其标识为一个 程序,并由最后一行的 END
语句关闭。
定义变量后,程序会提示用户输入随机数种子。Fortran 程序无法从操作系统初始化随机数生成器,因此你必须始终使用“种子”值和 SRAND
子程序 启动随机数生成器。
Fortran 使用 RAND(0)
函数生成 0 到 0.999…… 之间的随机数。参数 0
告诉 RAND
函数生成一个随机数。将此随机数乘以 100 以生成 0 到 99.999…… 之间的数字,然后加 1 得到 1 到 100.999…… 之间的值。INT
函数将结果截断为整数;因此,变量 NUMBER
就是一个介于 1 到 100 之间的随机数。
程序会给出提示,然后进入一个循环。Fortran 不支持更现代的编程语言中可用的 while
或 do-while
循环(LCTT 译注:Fortran 95 等新版支持,也因此在一定程度上减少了 GOTO
的使用)。相反,你必须使用标签(行号)和 GOTO
语句来构建自己的循环。这就是 READ
语句有一个行号的原因:你可以在循环末尾使用 GOTO
跳转到此标签。
穿孔卡片没有 <
(小于)和 >
(大于)符号,因此 Fortran 采用了另一种语法来进行值比较。要测试一个值是否小于另一个值,请使用 .LT.
(小于)。要测试一个值是否大于另一个值,请使用 .GT.
(大于)。等于和不等于分别是 .EQ.
和 .NE.
。
在每次循环中,程序都会验证用户的猜测值。如果用户的猜测值小于随机数,程序打印 TOO LOW
,如果猜测大于随机数,程序打印 TOO HIGH
。循环会一直持续,直到用户的猜测值等于目标随机数为止。
当循环退出时,程序打印 THATS RIGHT!
并立即结束运行。
$ gfortran -Wall -o guess guess.f
$ ./guess
ENTER A RANDOM NUMBER SEED
93759
GUESS A NUMBER BETWEEN 1 AND 100
50
TOO LOW
80
TOO HIGH
60
TOO LOW
70
TOO LOW
75
TOO HIGH
73
TOO LOW
74
THATS RIGHT!
每次运行程序时,用户都需要输入不同的随机数种子。如果你总是输入相同的种子,程序给出的随机数也会一直不变。
在其他语言中尝试
在学习一门新的编程语言时,这个“猜数字”游戏是一个很好的入门程序,因为它以非常简单的方式练习了几个常见的编程概念。通过用不同的编程语言实现这个简单的游戏,你可以弄清一些核心概念以及比较每种语言的细节。
你有最喜欢的编程语言吗?如何用你最喜欢的语言来编写“猜数字”游戏?跟随本系列文章来查看你可能感兴趣的其他编程语言示例吧。
via: https://opensource.com/article/21/1/fortran