您在QBasic中打高尔夫球有哪些一般提示?我正在寻找可以应用于编码高尔夫球问题的想法,这些想法至少在某些方面是QBasic特有的(例如,“删除评论”不是答案)。
还欢迎提供有关QB64仿真器的提示。它具有Microsoft QBasic所没有的一些额外功能。
您在QBasic中打高尔夫球有哪些一般提示?我正在寻找可以应用于编码高尔夫球问题的想法,这些想法至少在某些方面是QBasic特有的(例如,“删除评论”不是答案)。
还欢迎提供有关QB64仿真器的提示。它具有Microsoft QBasic所没有的一些额外功能。
Answers:
QBasic中有几个循环结构:FOR ... NEXT
,WHILE ... WEND
,和DO ... LOOP
。您也可以使用GOTO
或(在某些情况下)RUN
循环播放。
FOR ... NEXT
非常擅长 与Python不同的是,它甚至总是比等效WHILE
或GOTO
循环短,即使它变得更奇特:
FOR i=1TO 19STEP 2:?i:NEXT
i=1:WHILE i<20:?i:i=i+2:WEND
i=1:9?i:i=i+2:IF i<20GOTO 9
请注意,您无需在后面重复变量名NEXT
,并且可以消除数字和大多数后续关键字之间的空格。
WHILE ... WEND
当您有一个可能需要执行0次的循环时非常有用。但是,如果您知道循环将至少执行一次,则GOTO
可能会缩短一个字节:
WHILE n>1:n=n\2:WEND
1n=n\2:IF n>1GOTO 1
DO ... LOOP
用于无限循环(除非RUN
可以改为使用)。尽管它的字符数与无条件字符数相同GOTO
,但阅读起来却更加直观。(请注意,“无限循环”可以包括环,你打破使用出来GOTO
。)的DO WHILE
/ DO UNTIL
/ LOOP WHILE
/ LOOP UNTIL
语法过于冗长; 最好WHILE
还是使用或GOTO
适当使用。GOTO
如上所述,它是编写do / while循环的最短通用方法。使用一位数字的行号代替标签。请注意,当a GOTO
是语句THEN
部分中唯一的内容时IF
,可以使用两种同样简洁的快捷方式语法:
IF x>y GOTO 1
IF x>y THEN 1
GOTO
也可以用于创建更复杂的控制流。反对者称其为“意大利面条式代码”,但这就是代码式的高尔夫:不可读取性几乎是一种优点!GOTO
自豪!
RUN
当您需要跳转到程序中的固定位置并且不需要保留任何变量的值时,此功能很有用。RUN
本身将从顶部重新启动程序;标签或行号,它将在该行重新启动。我主要使用它来创建无状态无限循环。在要求您测试一个整数是否可被另一个整数整除的程序中,显而易见的方法是使用MOD
:
x MOD 3=0
但是更简单的方法是使用整数除法:
x\3=x/3
也就是说,x
int-div 3
等于x
float-div 3
。
请注意,这两种方法都会0
以错误和-1
真实返回,因此您可能需要取反或减去结果而不是相加。
如果您需要相反的条件(即x
是不是整除3
),明显的方法是使用不-等于操作:
x\3<>x/3
但是如果x
保证是非负数,我们可以保存一个字节。整数除法会截断结果,因此它将始终小于或等于浮点除法。因此,我们可以将条件写为:
x\3<x/3
同样,如果x
保证为负,则截断会增加结果,我们可以编写x\3>x/3
。如果您不知道的迹象x
,您必须坚持<>
。
与许多语言一样,知道哪些字符可以删除也不能删除是很重要的。
IF""=a$THEN?0
FOR i=1TO 10STEP 2
。QBasic 1.1(可从archive.org获得)和QB64之间有一些区别:
?123x
变为PRINT 123; x
。上面的例外是像1e2
和一样的序列1d+3
,它们被当作科学记数法并扩展为100!
和1000#
(分别为单精度和双精度)。d
,e
或f
水平,除非他们是一个结构良好的科学记数法文本的一部分。(例如,您不能像1 FOR
或9 END
QBasic中那样在或中省略行号之后的空格。)如果表达式之一是字符串,则只能在print语句中推断分号:?123"abc"
Works,而不能是?TAB(5)123
or ?123x
。PRINT
以TAB
或结束的语句中SPC
。(QB64没有。)0
可以在小数点(.1
或1.
)之前或之后省略,但不能全部省略(.
)。ENDIF
等同于END IF
。Next
报表Next:Next:Next
可能会浓缩为
Next k,j,i
其中对于迭代器For
环路i
,j
以及k
-按照这个顺序。
例如以下(69字节)
Input n,m,o
For i=0To n
For j=0To m
For k=0To o
?i;j;k
Next
Next
Next
可以压缩到65字节
Input n,m,o
For i=0To n
For j=0To m
For k=0To o
?i;j;k
Next k,j,i
至于这如何影响格式和缩进,我认为处理此问题的最佳方法是将下一条语句与最外层的for语句对齐。例如。
Input n,m,o
For i=0To n
For j=0To m
For k=0To o
?i;j;k
Next k,j,i
QBasic中有几种方法来获取用户键盘输入:INPUT
,LINE INPUT
,INPUT$
,和INKEY$
。
INPUT
是您的标准多用途输入语句。该程序将停止正在执行的操作,显示一个光标,并让用户键入一些输入,以终止Enter。INPUT
可以读取数字或字符串,并且可以读取多个以逗号分隔的值。您可以指定一个字符串作为提示,可以使用默认的问号提示,甚至可以(我今晚才刚刚学到)完全取消该提示。一些示例调用:
INPUT x$,y
?
提示,并读取以逗号分隔的字符串和数字。INPUT"Name";n$
Name?
并读取字符串。INPUT"x=",x
x=
(无问号!注意语法中的逗号)并读取数字。INPUT;"",s$
INPUT
操作)。例如,如果PRINT s$
紧接在此之后,屏幕将显示为User_inputUser_input
。INPUT
是您无法读取其中包含逗号的字符串,因为它INPUT
使用逗号作为字段分隔符。要读取一行任意(可打印ASCII)字符,请使用LINE INPUT
。它具有与相同的语法选项INPUT
,只是它只需要一个变量,该变量必须是字符串变量。另一个区别是LINE INPUT
默认情况下不显示提示。如果需要,则必须明确指定。INPUT$(n)
不显示任何提示或光标,而只是等待用户输入n
字符,然后返回包含这些字符的字符串。与INPUT
或不同LINE INPUT
,用户不需要Enter事后按下,而实际上Enter可以是以下字符之一(它将给出ASCII字符13,类似于C的语言称为\r
)。
通常,这INPUT$(1)
通常在循环中用作。在单个按键可以做事的交互式程序中INPUT$
很好。不幸的是,它仅适用于具有ASCII码的键。其中包括诸如和,但不包括箭头键和以及其他。EscBackspaceInsertDelete
这是INKEY$
从哪里来的。类似于INPUT$(1)
它返回单个按键1的结果,但不同之处在于:
INKEY$
不用争论。在INPUT$(n)
用户停止输入n
字符之前停止执行时,INKEY$
不会停止执行。如果用户当前正在按某个键,则INKEY$
返回表示该键的字符串;否则,返回一个字符串。如果不是,则返回""
。这意味着,如果您想用来INKEY$
获取下一个按键,则必须将其包装在一个繁忙的等待循环中:2
k$=""
WHILE""=k$
k$=INKEY$
WEND
两者INPUT$
和都INKEY$
返回与ASCII字符(包括转义符,制表符和退格键等控制字符)相对应的键的ASCII字符。但是,INKEY$
也可以处理一些没有ASCII码的键。对于这些文件(即帮助文件),“ INKEY $返回一个2字节的字符串,该字符串由空字符(ASCII 0)和键盘扫描代码组成。”
像泥一样清澈?这是一些例子。如果使用INKEY$
上面的循环捕获向左箭头键的按键,k$
它将包含字符串"␀K"
(K
代表扫描代码为75)。对于右箭头,为"␀M"
(77)。向下翻页是"␀Q"
(81)。F5为"␀?"
(63)。
还是像泥一样清澈?是的 这不是世界上最直观的事情。帮助文件中有一张扫描代码表,但是我总是只写一个小程序来打印结果,INKEY$
然后按一堆键找出正确的值。一旦知道哪些字符对应于哪些键,就可以使用RIGHT$(k$,1)
并LEN(k$)
区分可能遇到的所有不同情况。
底线?INKEY$
很奇怪,但这是您的程序需要非阻塞输入或需要使用箭头键的唯一方法。
1不包括Shift,Ctrl,Alt,PrntScr,Caps Lock,和类似的。那些不算在内。:^ P
2这WHILE ... WEND
是我从QBasic书籍中学到的成语。打高尔夫球的目的,但是,一个GOTO
循环时间较短。
在QBasic中,习惯上使用该DIM
语句创建变量,并为其指定名称和类型。但是,这不是强制性的,QBasic也可以通过变量名称的后缀来派生类型。由于您不能同时声明和初始化变量,因此跳过DIM
代码高尔夫通常是明智的。功能上相同的两个摘要*:
DIM a AS STRING: a = "example"
a$ = "example"
*请注意,这确实会创建两个不同的变量名称。
我们可以通过$
在字符串,!
单精度数字和%
双精度数的变量名的末尾添加变量来指定变量的类型。如果未指定类型,则假定为单打。
a$ = "Definitely a string"
b! = "Error!"
请注意,这也适用于数组。通常,数组定义为:
DIM a(20) AS STRING
但是数组也不需要DIM
医学:
a$(2) = "QBasic 4 FUN!"
a$
现在是一个包含11个插槽的字符串数组:从索引0到索引10,包括索引10。之所以这样做,是因为QBasic具有允许对数组进行基于0和基于1索引的选项。默认数组类型同时支持这两种方式。
还记得我们DIM
上面插入的二十插槽阵列吗?实际上有21个插槽,因为相同的原理适用于变暗和非变暗阵列。
IF
语句IF
语句是相当昂贵的,打下来可以节省很多字节。
考虑以下(改编自一个答案由埃里克Outgolfer):
IF RND<.5THEN
x=x-1
a(i)=1
ELSE
y=y-1
a(i)=0
ENDIF
我们可以做的第一件事是ENDIF
使用单行IF
语句保存:
IF RND<.5THEN x=x-1:a(i)=1ELSE y=y-1:a(i)=0
只要您不尝试将其与其他任何内容放在同一行,此方法就起作用。特别是,如果您有嵌套的IF
语句,则仅最里面的语句可以是单行的。
但是在这种情况下,我们可以IF
完全不用数学。考虑一下我们实际想要的:
RND<.5
为true(-1
),我们希望:
x
减少1y
保持不变a(i)
成为1RND<.5
为false(0
),则我们希望:
x
保持不变y
减少1a(i)
变成0现在,如果我们保存条件的结果的变量(r=RND<.5
),我们可以计算出新的价值x
,y
以及a(i)
:
r
是-1
,x=x-1
; 当r
是0
,x=x+0
。r
是-1
,y=y+0
; 当r
是0
,y=y-1
。r
是-1
,a(i)=1
; 当r
是0
,a(i)=0
。因此,我们的最终代码如下所示:
r=RND<.5
x=x+r
y=y-1-r
a(i)=-r
与原始版本相比节省了多达20个字节(40%)。
数学方法经常可以令人惊讶地应用,但是当两种情况之间的逻辑存在差异时(例如,当您需要在一种情况下输入某些内容而不在另一种情况下输入某些内容时),您仍然需要使用IF
。
在没有实例化的情况下,QBasic中的数组DIM
只有11个插槽。如果挑战要求的插槽超过11个(或N个插槽,其中N可以大于11),则应DIM
使用阵列。另外,假设我们要用数据填充此数组:
DIM a$(12)
a$(0) = "Value 1"
a$(1) = "Value 2"
...
即使打高尔夫球,也可能占用很多空间。在这种情况下,这样做可能会更便宜(以字节为单位):
a$ = "value 1value 2"
在这里,我们将所有内容放在1个串联字符串中。以后,我们像这样访问它:
?MID$(a$,i*7,7)
对于这种方法,重要的是所有值的长度相等。取最长的值并填充所有其他值:
a$="one two threefour "
您无需填充最后一个值,甚至可以跳过右引号!如果挑战指定答案中不允许使用空格,请使用RTRIM$()
来解决该问题。
您可以在此处看到此技术的实际应用。
PRINT
(?
)有一些怪癖数字印有前导和尾随空格。
打印会增加换行符。可以通过在语句末尾添加逗号来代替制表符或使用分号来避免任何插入来更改此行为:
打印时,例如,不必在不同的操作之间使用&
或;
在不同的操作之间使用。?1"x"s$
应打印数字1
,每边各有一个空格,字母x
和内容s$
?"foo"
?"bar"
?10
?"foo",
?"bar"
?"foo";
?"bar"
?1CHR$(65)
?1" "CHR$(65)
?"A","B
产出
foo
bar
10
foo bar
foobar
1 A
1 A
A B
只需使用以下命令即可打印换行符 ?
-
在此处打印减号。在数字之后还会打印一个空格。我发现摆脱这些空间的最好方法是PRINT USING
--dunno,如果您想将其添加到此答案中,或者它应该是一个单独的答案。
WRITE
可能代替 PRINT
PRINT
通常是您要执行输出的方式,因为它非常灵活并且具有?
快捷方式。但是,该WRITE
命令可以在特定情况下为您节省字节:
WRITE
将其用双引号("
)引起来。如果您需要使用双引号将其输出,WRITE s$
则比短得多?CHR$(34);s$;CHR$(34)
。参见,例如,已知最短的QBasic quine。WRITE
请勿像在数字之前或之后添加空格PRINT
。WRITE n
比短得多?MID$(STR$(n),2)
。参见例如QB64中的FizzBuzz。WRITE
用逗号隔开:WRITE 123,"abc"
输出123,"abc"
。我想不出一种有用的方案,但这并不意味着就没有这种方案。的局限性WRITE
:
PRINT a;b
。LOCATE
,但这会占用很多字节。)有几个功能可以处理字符而不是字符串,但是char
QBasic中没有数据类型,只有string ($)
类型。以ASC()
函数为例,该函数返回字符的ASCII密钥代码。如果我们进入
PRINT ASC("lala")
l
QBasic 仅考虑第一个。这样,我们不必费心将字符串切成长度为1的字符串。
另一个例子来自这个问题,其中STRING$()
一个答案中使用了函数。
STRING $函数采用两个参数,即数字n和字符串s $,并构造一个由s $第一个字符的n个副本组成的字符串
@DLosc,在这里
请注意,当QBasic提供一个多字符字符串并且只需要一个字符时,它会自动获取第一个字符而忽略其余字符。