LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

Input help?

Root / Programming Questions / [.]

CrazyblobCreated:
Actually, IF VARIABLE THEN is the same as IF VARIABLE!=0 THEN. Any number that isn't 0 counts as true, including negative numbers.

Yup, thank you guys. I'm working on a text adventure type of game, so that's why I've been asking for this info.. and cuz I'm new to programming.
ayy I'm doing that too but on and off cuz BASIC bad and slowly becoming an adult plskillme

Yeah basics pretty old.. I guess I better start learning python

Btw if you want you can use DEF'd statements instead of GOTO because DEF is less likely to mess up somewhere and can be neater.

How's it less likely to mess up?

Lumage showed something using an IF statement and a GOTO. Not really a big deal I think.

The GOTOs were bugging me too .... a lot.
VAR RETRIES = 0, LOCKED = FALSE, PW$
VAR VALID_PASSWORD$[0]

'READ THE LIST OF VALID PASSWORDS
READ PW$
WHILE PW$ != ""
 PUSH VALID_PASSWORD$, PW$
 READ PW$
WEND

PW$ = GET_PASSWORD$()
IF PW$ == "V360" THEN PRINT "MASTER, .... IT'S YOU!"

IF PW$ != "" THEN
 LOG_IN
ELSE
 PRINT "GAME OVER"
ENDIF

END

DEF GET_PASSWORD$()
 VAR PW$, I, VALID

 IF LOCKED THEN
  PRINT "ACCESS DENIED"
 ELSE
  VALID = FALSE
  REPEAT
   INPUT "PASSWORD"; PW$
   'IS THAT A VALID PASSWORD?
   FOR I = 0 TO LEN(VALID_PASSWORD$) - 1
    IF PW$ == VALID_PASSWORD$[I] THEN
     VALID = TRUE
     BREAK
    ENDIF
   NEXT I
   IF VALID == FALSE THEN
    RETRIES = RETRIES + 1
    PRINT "INVALID PASSWORD."
    IF RETRIES > 3 THEN
     LOCKED = TRUE
     PW$ = ""
     PRINT "TOO MANY FAILED LOGINS. LOCKED!"
    ENDIF
   ENDIF
  UNTIL VALID OR LOCKED
 ENDIF
 RETURN PW$
END

DEF LOG_IN
 PRINT "C:>"
END

@PASSWORDS
DATA "PASSWORD", "V360", ""
Here is my overly long take with some tricky edge cases to puzzle over. Note that the password list is data driven. You can add, edit, and delete passwords without altering the code outside of the data statement. The pw$ variable in get_password and the one at global scope are different variables with the same name. Spooky. If you call get password after your retries are up it will kick you out. The while/wend, repeat/until and for loops save you from making a bunch of line labels as do the functions. You could move the code into new programs and reuse it now. Get_password has () in the call because it returns a value. Log_in doesn't return a value so you don't use ().

or you could just not complicate things for someone clearly trying to learn

It was actually designed to be useful to someone just starting out and trying to learn. GOTO has been considered harmful to writing clean code since the 70s. If you are just starting out using GOTO/GOSUB will hurt you in the long run and naturally lead to unmaintainable spaghetti code. In the example I showed WHILE/WEND, FOR/NEXT, and a REPEAT/UNTIL loops. I even put in an decent example of BREAK to skip unneccesary processing. I showed the different DEF syntax for a function and a subroutine too. Learning those will help you write cleaner, more maintainable, more reusable, more readable code. There is a lot to study packed into less than 60 lines, but I do think it is worth studying.

I agree with Lumage. Throwing a huge pile of concepts at someone all at once, while telling them the stuff they do understand is bad and wrong, is not a good way to teach someone. Yeah, GOTOs can contribute to hard-to-read code over time compared to more advanced control flow, but this is not an immediate problem that has to be addressed when they're still learning basic concepts like comparison operators. Program structure and code maintenance can be worried about later. It also strikes me as odd that this is all in the name of cleaner and more readable code, because the code you've given is fairly convoluted and difficult to follow. GET_PASSWORD$() could be rewritten as something like this:
DEF CONTAINS(ARRAY[], ITEM)
 VAR I
 FOR I=0 TO LEN(ARRAY)-1
  IF ARRAY[I]==ITEM THEN RETURN TRUE
 NEXT
 RETURN FALSE
END

DEF GET_PASSWORD$()
 VAR TRY,PW$

 IF LOCKED THEN
  PRINT "ACCESS DENIED"
  RETURN ""
 ENDIF

 FOR TRY=1 TO 3
  INPUT "PASSWORD";PW$
  IF CONTAINS(VALID_PASSWORD$,PW$) THEN
   RETURN PW$
  ELSE
   PRINT "INVALID PASSWORD."
  ENDIF
 NEXT

 PRINT "TOO MANY FAILED LOGINS. LOCKED!"
 LOCKED=TRUE
 RETURN ""
END

My own take, while we're at it (to further modularize). Side note, this is purely functional with the exception of the CONTAINS$ function and PRINT statements.
DEF CONTAINS$(PASSWORDS$[], WORD$)
 VAR I
 FOR I=0 TO LEN(PASSWORDS)-1
  IF PASSWORDS[I]==WORD THEN RETURN WORD
 NEXT
 RETURN ""
END

DEF CHECK$(WORD$)
 IF WORD$=="" THEN
  PRINT "Invalid password, try again!" 
 ELSE
  PRINT "Success!"
 ENDIF
 RETURN WORD$
END

DEF CHECKPASS$(CHECKS%)
 VAR PASS$
 IF CHECKS%==3 THEN
  PRINT "Access denied, too many password attempts!"
  RETURN ""
 ELSE
  LINPUT "Input password: ", PASS$
  VAR TESTER$=CHECK$(CONTAINS$(PASS))
  IF TESTER$=="" THEN
   RETURN CHECKPASS$(CHECKS% + 1)
  ELSE
   RETURN TESTER$
 ENDIF
END

CHECKPASS$(0)
I haven't tested this, and I haven't written SB in over a year, so please let me know if there are any problems.