these pretzels are making me thirsty

Jan 10, 2015  

All right, here’s another one of the series of hypothetically pedagogical text games in Go. This one is based on the original Bagels, which I then appropriated as Pretzels.

Here’s the code:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

const (
	minRange  = 100
	maxRange  = 999
	numDigits = 3
	maxTries  = 20
)

const (
	picoStr    = " -- PICO -- "
	fermiStr   = " -- FERMI -- "
	pretzelStr = " -- PRETZEL -- "
)

func showIntro() {
	fmt.Println("\nWelcome to 'PRETZELS' !!")
	fmt.Println("------------------------")
	fmt.Println(
		"\nHere are the rules. I'm going to guess a THREE-DIGIT number, and then " +
			"you have to guess it. I will give you clues as follows: \n" +
			"   PICO -- you got one digit correct, BUT in the wrong position\n" +
			"  FERMI -- you got on digit correct, AND in the right position\n" +
			"PRETZEL -- you got NO digits correct.\n")
	fmt.Printf("You get %d chances to guess it!\n\n", maxTries)
}

func getDigits(num int, digits []int) {
	var i int
	for {
		digits[i] = num % 10
		i++
		num /= 10
		if num == 0 {
			break
		}
	}
}

func showFeedback(targetDigits []int, guess int) {
	guessDigits := make([]int, numDigits)
	getDigits(guess, guessDigits)
	somethingMatched := false
	for i := 0; i < len(guessDigits); i++ {
		if guessDigits[i] == targetDigits[i] {
			fmt.Printf(fermiStr)
			somethingMatched = true
			continue
		}
		for j := 0; j < len(targetDigits); j++ {
			if guessDigits[i] == targetDigits[j] {
				fmt.Printf(picoStr)
				somethingMatched = true
				break
			}
		}
	}
	if !somethingMatched {
		fmt.Printf(pretzelStr)
	}
	fmt.Println()
}

func main() {
	showIntro()

	rand.Seed(time.Now().Unix())
	target := minRange + rand.Intn(maxRange-minRange)
	targetDigits := make([]int, numDigits)
	getDigits(target, targetDigits)

	var numTries int
	for {
		fmt.Printf("\nWhat is Guess #%d ? ", numTries+1)
		var guess int
		fmt.Scan(&guess)

		if guess < minRange || guess > maxRange {
			fmt.Printf("You MUST choose a number between %d and %d, try again ...\n\n", minRange, maxRange)
			continue
		}
		showFeedback(targetDigits, guess)
		if guess == target {
			fmt.Println("\nYou got it!!\n")
			break
		}
		if numTries > maxTries {
			fmt.Println("\nOOPS ... you ran out of chances! :(\n")
			fmt.Printf("(The number I thought of was %d)\n\n", target)
			break
		}
		numTries++
	}
	fmt.Println("\n\n     ... these pretzels are making me thirsty! ...\n")
}

and here’s the eye-watering original:

5 PRINT TAB(33);"BAGELS"
10 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY":PRINT:PRINT
15 REM *** BAGLES NUMBER GUESSING GAME
20 REM *** ORIGINAL SOURCE UNKNOWN BUT SUSPECTED TO BE
25 REM *** LAWRENCE HALL OF SCIENCE, U.C. BERKELY
30 DIM A1(6),A(3),B(3)
40 Y=0:T=255
50 PRINT:PRINT:PRINT
70 INPUT "WOULD YOU LIKE THE RULES (YES OR NO)";A$
90 IF LEFT$(A$,1)="N" THEN 150
100 PRINT:PRINT "I AM THINKING OF A THREE-DIGIT NUMBER.  TRY TO GUESS"
110 PRINT "MY NUMBER AND I WILL GIVE YOU CLUES AS FOLLOWS:"
120 PRINT "   PICO   - ONE DIGIT CORRECT BUT IN THE WRONG POSITION"
130 PRINT "   FERMI  - ONE DIGIT CORRECT AND IN THE RIGHT POSITION"
140 PRINT "   BAGELS - NO DIGITS CORRECT"
150 FOR I=1 TO 3
160 A(I)=INT(10*RND(1))
165 IF I-1=0 THEN 200
170 FOR J=1 TO I-1
180 IF A(I)=A(J) THEN 160
190 NEXT J
200 NEXT I
210 PRINT:PRINT "O.K.  I HAVE A NUMBER IN MIND."
220 FOR I=1 TO 20
230 PRINT "GUESS #";I,
240 INPUT A$
245 IF LEN(A$)<>3 THEN 630
250 FOR Z=1 TO 3:A1(Z)=ASC(MID$(A$,Z,1)):NEXT Z
260 FOR J=1 TO 3
270 IF A1(J)<48 THEN 300
280 IF A1(J)>57 THEN 300
285 B(J)=A1(J)-48
290 NEXT J
295 GOTO 320
300 PRINT "WHAT?"
310 GOTO 230
320 IF B(1)=B(2) THEN 650
330 IF B(2)=B(3) THEN 650
340 IF B(3)=B(1) THEN 650
350 C=0:D=0
360 FOR J=1 TO 2
370 IF A(J)<>B(J+1) THEN 390
380 C=C+1
390 IF A(J+1)<>B(J) THEN 410
400 C=C+1
410 NEXT J
420 IF A(1)<>B(3) THEN 440
430 C=C+1
440 IF A(3)<>B(1) THEN 460
450 C=C+1
460 FOR J=1 TO 3
470 IF A(J)<>B(J) THEN 490
480 D=D+1
490 NEXT J
500 IF D=3 THEN 680
505 IF C=0 THEN 545
520 FOR J=1 TO C
530 PRINT "PICO ";
540 NEXT J
545 IF D=0 THEN 580
550 FOR J=1 TO D
560 PRINT "FERMI ";
570 NEXT J
580 IF C+D<>0 THEN 600
590 PRINT "BAGELS";
600 PRINT
605 NEXT I
610 PRINT "OH WELL."
615 PRINT "THAT'S TWNETY GUESSES.  MY NUMBER WAS";100*A(1)+10*A(2)+A(3)
620 GOTO 700
630 PRINT "TRY GUESSING A THREE-DIGIT NUMBER.":GOTO 230
650 PRINT "OH, I FORGOT TO TELL YOU THAT THE NUMBER I HAVE IN MIND"
660 PRINT "HAS NO TWO DIGITS THE SAME.":GOTO 230
680 PRINT "YOU GOT IT!!!":PRINT
690 Y=Y+1
700 INPUT "PLAY AGAIN (YES OR NO)";A$
720 IF LEFT$(A$,1)="YES" THEN 150
730 IF Y=0 THEN 750
740 PRINT:PRINT "A";Y;"POINT BAGELS BUFF!!"
750 PRINT "HOPE YOU HAD FUN.  BYE."
999 END

And just to show how much fun this is (copy-paste and try it!), here’s a sample run:

$ go run pretzels.go

Welcome to 'PRETZELS' !!
------------------------

Here are the rules. I'm going to guess a THREE-DIGIT number, and then you have to guess it. I will give you clues as follows:
   PICO -- you got one digit correct, BUT in the wrong position
  FERMI -- you got on digit correct, AND in the right position
PRETZEL -- you got NO digits correct.

You get 20 chances to guess it!


What is Guess #1 ? 123
 -- PRETZEL --

What is Guess #2 ? 456
 -- PICO --

What is Guess #3 ? 789
 -- PICO --  -- PICO --

What is Guess #4 ? 100
 -- PRETZEL --

What is Guess #5 ? 987
 -- PICO --  -- PICO --

What is Guess #6 ? 8797
You MUST choose a number between 100 and 999, try again ...


What is Guess #6 ? 897
 -- FERMI --  -- FERMI --

What is Guess #7 ? 894
 -- FERMI --  -- FERMI --  -- FERMI --

You got it!!



     ... these pretzels are making me thirsty! ...