Tell me more ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Description

Create a fully working "Guess the number" game. The game is played by two players as follows:

  1. player one chooses a number (A) between 1 and N
  2. player two tries to guess A choosing a number (B) in the same range
  3. the first player responds "higher" if A > B, "lower" if A < B or "correct" if A = B.
  4. steps 2-3 are repeated I times or until "correct" is responded.
  5. If "correct" is heard, player two wins otherwise he loses.

Specs

Minimum specs for a valid entry:

  • user can play either as player one or player two.
  • computer plays the other role.
  • computer must really try to guess the number while playing as player two (so, guessing against the given data or ignoring the given data is cheating)
  • N = 100 or input by the user (your choice)
  • I = 5 or input by the user (your choice)
  • program must announce then winner at the end.
  • full human readable instructions of what to do in each step (e.g "Play as player one or player two?", "Enter another guess:", etc) - don't go nuts on this one; just keep it simple.

Winning conditions

In that order:

  1. Highest voted entry wins if it's at least 3 votes ahead of the second highest voted entry.
  2. Shortest entry wins.
share|improve this question
I didn't explicitely read we needed an AI on that one. Could you confirm both players are human? – J B Feb 21 '11 at 16:32
@JB: sorry about that :/ You do need an AI. I'm updating the question now... – Eelvex Feb 21 '11 at 16:37
1  
I think the instruction texts for each step should be given, otherwise it's hard to compare the answers. – Joey Feb 23 '11 at 2:12
@Joey Definitely – Let_Me_Be Feb 23 '11 at 14:59
Is user input validation important? – zzzzBov Mar 8 '11 at 20:15

10 Answers

up vote 3 down vote accepted

Windows PowerShell, 289

nal ^ Read-Host
filter p{"Player $_ wins.";exit}
$p=1-(^ Player 1 or 2)
$n=($x=1)..($y=99)|random
if($p){$n=^ Enter number}1..5|%{if($p){'{0:"higher";"lower";"correct";2|p}'-f($n-(^ Guess))|iex}else{"Guessing, "+($g=$x..$y|random);@{104='$x=$g+1';108='$y=$g-1';99='2|p'}[+(^)[0]]|iex}}
1|p

History:

  • 2011-02-21 18:44 (620) Ungolfed.
  • 2011-02-21 19:15 (365) First round of golfing.
  • 2011-02-21 19:31 (359) Some inlining.
  • 2011-02-21 19:38 (340) Some strings shortened.
  • 2011-02-21 19:44 (339) whilefor
  • 2011-02-21 19:53 (331) Some duplicate strings pulled into variables.
  • 2011-02-21 19:53 (330) Another variable inlined.
  • 2011-02-21 19:53 (328) Optimized loop condition. Can't use a pipeline, though.
  • 2011-02-22 01:57 (326) else{if...}elseif – saves the braces.
  • 2011-02-22 12:42 (325) Moved plenty of stuff around, using a hashtable instead of the switch to avoid naming the loop. Now I can use just break and a pipeline, too. Winner announcement moved into a filter that uses exit so no break required, ever.
  • 2011-02-23 01:23 (308) Instead of an elseif chain for checking the guess I just use a format string with different values for negative, positive and zero values. Saves a lot.
  • 2011-02-23 02:16 (306) Using subtraction instead of equality.
  • 2011-03-12 02:27 (289) Reduced to the same level of rudimentary user interaction as the Ruby solution. Of course it's shorter then.
share|improve this answer

C 397 Characters

N,H=99,L=0,c=0,w=1;main(){char s[9];puts("Play as player 1 or 2: ");scanf("%d",&N);if(N-1){getchar();do{N=rand()%(H-L)+L+1;printf("My guess: %d\n",N);gets(s);if(*s=='c'){w=2;break;}if(*s-'l')H=N-1;else L=N-1;c++;}while(c<5);}else{N=rand()%99+1;while(c<5){puts("Enter guess: ");scanf("%d",&H);if(H==N){puts("correct");break;}else puts(H>N?"higher":"lower");c++;}if(c==5)w=2;}printf("Winner %d",w);}

In a more readable form.

main()
{
        int i,N,H=100,L=0,c=0,w=1;
        char s[10];
        puts("Play as player 1 or 2: ");
        scanf("%d",&i);
        if(i-1)
        {
                getchar();
                do{
                        N=rand()%(H-L)+L+1;
                        printf("My guess: %d\n",N);
                        gets(s);
                        if(s[0]=='c')break;
                        else if(s[0]=='h')H=N-1;
                        else L=N-1;
                        c++;
                }while (c<5);
                if(c<5)w=2;
        }
        else
        {
                N=rand()%99+1;
                while (c<5)
                {
                        puts("Enter another guess: ");
                        scanf("%d",&H);
                        if(H==N){printf("correct\n");break;}
                        else if(H>N)printf("higher\n");
                        else printf("lower\n");
                        c++;
                }
                if(c==5)w=2;
        }
        printf("Winner %d",w);
}
share|improve this answer
@Joey Corrected Now. – fR0DDY Feb 24 '11 at 9:07

Good old plain C

#include <stdio.h>
#define x(s) puts(s)
main(){int c,i,l,h,g;srand(time(NULL));p:x("You want to guess (1) or should I (2)?");scanf("%d",&c);i=5;if(c==2){x("Think a number 1..100");h=100;l=1;goto t;}if(c==1){x("Guess a number 1..100");h=rand()%100+1;goto g;}return 0;t:if(!i--)goto u;printf("%d (1)higher (2)lower (3)correct",g=rand()%(h-l)+l);scanf("%d",&c);if(c==1)l=g;if(c==2)h=g;if(c==3)goto c;goto t;g:if (!i--)goto c;scanf("%d",&g);if(g>h)x("lower");if(g<h)x("higher");if(g==h){x("correct");goto u;}goto g;u:x("You win");goto p;c:x("I win");goto p;}
  • 23/11/2011 16:44:00 883 nice and cosy
  • 24/11/2011 09:38:00 616 fixed & shortened
  • 24/11/2011 11:52:00 555 shortened
share|improve this answer
you wrote this in the future? that's very clever!! – mikera Mar 8 '11 at 21:44

Lua 360 Chars

i=io.read p=print I=5 N=100 math.randomseed(os.time())r=math.random p"Play as player one or two?"o=i"*n">1 _=o and p("Input number between 1 and",N)n=o and i"*n"or r(I,N)l,u=1,N for k=1,I do p"Guess!"g=o and r(l,u)or i"*n"p("Guessed",g)if n==g then p"Correct"break elseif n>g then p"Higher"l=g else p"Lower"u=g end end p(o and"I"or"You",n==g and"Won"or"Loose")

Non-golfed version:

i=io.read
p=print
I=5
N=100
math.randomseed(os.time())      -- Make things less predictable
r=math.random                   
p"Play as player one or two?"
o=i"*n">1
_=o and p("Input number between 1 and",N) -- if one, ask for number
n=o and i"*n"or r(I,N)          -- get number from user or random
l,u=1,N                         -- boundaries for doing "smart" guessing
for k=1,I do
    p"Guess!"
    g=o and r(l,u)or i"*n"      -- get guess (random or input)
    p("Guessed",g)
    if n==g then p"Correct!"break -- break loop if guessed correctly
    elseif n>g then             -- if guess to low
    p"Higher"l=g else           -- print + update boundaries
    p"Lower"u=g end
end
p(o and"I"or"You",n==g and"Won"or"Loose") -- Determine outcome!
share|improve this answer

C#:

Character count: With spaces: 575 No spaces: 464

    static void Main()
    {
        Action<object> w = s => Console.WriteLine(s);
        Func<object, byte> r = t => { w(t); var s = Console.ReadLine(); return Convert.ToByte(s); };
        var p = r("Player (1/2):");
        int N = 100, g, i = 0, c, d;
        var q = new List<int>(Enumerable.Range(0, N));
        Func<Guid> x = Guid.NewGuid;
        c = p == 1 ? r("Number:") : q.OrderBy(j => x()).First();
        m: i++;
        g = p == 2 ? r("Guess:") : q.OrderBy(j => x()).First();
        d = g < c ? -1 : (g > c ? 1 : 0);
        w(d == -1 ? "Higher" : (d == 1 ? "Lower" : "correct"));
        q = q.Where(n => d == -1 ? n > g : n < g).ToList();
        if(c != g && i < 5) goto m;
        r(g);
    }

Edit do while is now "Goto" (shiver)

share|improve this answer

Javascript

This is about 800 characters, and includes your basic binary selection 'AI' for the computer player half. I could probably save a few characters if I got rid of all my vars but I don't like leaking variables even while code golfing. I also did a two step "Is this correct?"/"Is this higher?" thing with confirm pop-ups rather than giving a prompt pop-up and checking for "correct"/"higher"/"lower" though that could maybe also save some characters, I didn't really check.

Also, I only tested it on Firefox 4, so I don't know if some of the things I'm doing work consistently, particularly coalescing an invalid input, parsed as NaN, to a default value in my wp function.

function game(N, I) {
    var wa=function(a){window.alert(a)};
    var wc=function(s){return window.confirm(s)};
    var wp=function(s){return window.prompt(s)};
    var ri=function(s,d){return parseInt(wp(s),10)||d};
    var m=function(l,h){return Math.round((h+l)/2)};
    N = N || pd("Highest possible number?",100);
    I = I || pd("How many guesses?",5);
    var p = wc("Be player 2?");
    var s = [1,N];
    var a = p?Math.ceil(Math.random()*N):Math.min(N,Math.max(1,ri("Pick a number from 1 to " + N,1)));
    var w = 0;
    var g = 0;
    if(p) while(I--){while(!(g = ri("Guess:",0)));if(g==a){wa("correct");w=p+1;break;}else{wa(g<a?"higher":"lower")}}
    else while(I--){g = m(s[0],s[1]);if(wc("Is "+g+" correct?")) { w=p+1;break;} else if (wc("Is "+g+" higher?")){s=[s[0],g];}else{s=[g,s[1]];}}
    if(!w)w=!p+1;
    wa("Player " + w + " wins!");
}
game(100,5);
share|improve this answer

JavaScript

New minified version (dropped var and reduced alert calls:

268 chars

function g(m){n=u(confirm('Player pick?'));function u(p){if (p){do{n=parseInt(prompt('Number'))}while(isNaN(n)||!n||n>m)}else{n=parseInt(Math.random()*m)+1}return n}while(g!==n){do{g=parseInt(prompt('Guess'))}while(isNaN(g));alert(g<n?'higher':g>n?'lower':'correct')}}

To run call g(100);, self-execution is not counted, as it adds a variable number of characters (275 chars for g(100);).

original (somewhere around 600 chars including whitespace):

function guessTheNumber(m)
{
  var n = getNum(confirm('Player pick the number?')), g;

  function getNum(p)
  {
    var n;
    if (p)
    {
      do
      {
        n = parseInt(prompt('What number?'));
      } while(isNaN(n) || !n || n > m);
    }
    else
    {
      n = parseInt(Math.random() * m) + 1;
    }
    return n;
  }

  while(g!==n)
  {
    do
    {
      g = parseInt(prompt('Take a guess!'));
    } while(isNaN(g));
    if (g < n)
    {
      alert('higher');
    }
    else if (g > n)
    {
      alert('lower');
    }
    else
    {
      alert('correct!');
    }
  }
}

Minified (312):

function g(m){var g,n=u(confirm('Player pick?'));function u(p){var n;if (p){do{n=parseInt(prompt('Number'))}while(isNaN(n)||!n||n>m)}else{n=parseInt(Math.random()*m)+1}return n}while(g!==n){do{g=parseInt(prompt('Guess'))}while(isNaN(g));if(g<n) alert('higher');else if(g>n) alert('lower');else alert('correct')}}
share|improve this answer
sorry, I didn't notice. Better put your latest code on the top. (Also, I can't get it to run properly :-/) – Eelvex Mar 11 '11 at 20:27
@Eelvex: While you're trying to get that to run, my solution is shorter than the currently accepted again. And you should really specify the exact strings to be used when interacting with the user. Basically everything Magnus has done was to use more concise interaction which of course is shorter. – Joey Mar 12 '11 at 1:31
Am I seeing that correctly and this program does not handle the case where the human is player 1 correctly? At least I don't see code for the AI to guess a number and the player to enter »higher«, »lower« or »correct« anywhere ... – Joey Mar 12 '11 at 1:35
@Joey, I was under the impression that if a human player were to go first, they'd only have to pick a number. I guess I'm a bit foggy on why a human player would be choosing higher, lower, and correct – zzzzBov Mar 12 '11 at 2:06
Just follow the instructions for players 1 and 2. One of them is a human, the other is a computer. There is no difference in protocol, though. Also the sentence »computer must really try to guess the number while playing as player two« very much implies that the computer has to guess a number. – Joey Mar 12 '11 at 2:09
show 1 more comment

BASIC, 184

100 INPUT "P1 NUMBER? ";
200 FOR I%=1 TO 5
300 INPUT "P2 GUESS? ";G%
400 INPUT "P1 SENTENCE? ";S$
500 IF S$="CORRECT" THEN 800
600 NEXT I%
700 PRINT "WINNER 1":END
800 PRINT "WINNER 2"

Here's the no-AI version.

share|improve this answer

Java, 1886 chars:

import java.io.*;import java.util.*;import java.util.regex.*;public class GuessGame {int L=1;int H=100;int G=5;int N;String HS="higher";String LS="lower";String CS="correct";public static void main(String[] args){if (args.length==2)new GuessGame(Integer.parseInt(args[0]),Integer.parseInt(args[1])).play();else if(args.length==0)new GuessGame(100,5).play();else System.out.println("usage GuessGame HighInteger NumberGuess");}GuessGame(int H,int G){this.H = H;this.G = G;}void play(){int pNum=getInt("Play As Player 1 or Player 2?","1|2");if(pNum==1)playP2();else playP1();System.out.println("The number was "+N);}int getInt(String pmpt,String val){BufferedReader cin=new BufferedReader(new InputStreamReader(System.in));int i=0;Pattern p=Pattern.compile(val);boolean fnd=false;String ln="";try{while(!fnd){System.out.println(pmpt);ln=cin.readLine();Matcher m=p.matcher(ln);fnd=m.find();}i=Integer.parseInt(ln);} catch (Exception ex) {}return i;}String processGuess(int g){if(N>g)return HS;else if(N<g)return LS;else return CS;}void playP1(){N=new Random().nextInt(H);for(;G>0;G--){String rslt=processGuess(getInt("Player 2, enter your guess:","\\d?"));System.out.println(rslt);if(rslt.equals(CS)){System.out.println("Player 2 wins!");break;}}}void playP2() {N=getInt("Player 1, enter your number:", "\\d+");int max=H;int min=L;int nextGuess=min+(max-min)/2;for (;G>0;G--){System.out.println("Player 2, enter your guess:" + nextGuess);String rslt=processGuess(nextGuess);System.out.println(rslt);if(rslt.equals(HS)){min=nextGuess+1;nextGuess=fuzzify(nextGuess+(max-nextGuess)/2,min,max);}if (rslt.equals(LS)){max=nextGuess-1;nextGuess=fuzzify(nextGuess-(nextGuess-min)/2,min,max);}if(rslt.equals(CS)){System.out.println("Player 2 wins!");break;}}}int fuzzify(int i,int mn,int mx){int fz=new Random().nextInt(3);if(fz==1)return Math.max(mn,--i);if(fz==2)return Math.min(mx,++i);return i;}}

Non golfed version:

import java.io.*;
import java.util.*;
import java.util.regex.*;
public class GuessGame {
    int L = 1;
    int H = 100;
    int G = 5;
    int N;
    String HS = "higher";
    String LS = "lower";
    String CS = "correct";
    public static void main(String[] args) {
        if (args.length == 2)
            new GuessGame(Integer.parseInt(args[0]), Integer.parseInt(args[1])).play();
        else if (args.length == 0)
            new GuessGame(100, 5).play();
        else
            System.out.println("usage GuessGame HighInteger NumberGuess");
    }
    GuessGame(int H, int G) {
        this.H = H;
        this.G = G;
    }
    void play() {
        int pNum = getInt("Play As Player 1 or Player 2?","1|2");
        if (pNum == 1)
            playP2();
        else
            playP1();
        System.out.println("The number was " + N);
    }
    int getInt(String pmpt, String val) {
        BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
        int i = 0;
        Pattern p = Pattern.compile(val);
        boolean fnd = false;
        String ln = "";
        try {
            while (!fnd) {
                System.out.println(pmpt);
                ln = cin.readLine();
                Matcher m = p.matcher(ln);
                fnd = m.find();
            }
            i = Integer.parseInt(ln);
        } catch (Exception ex) {}
        return i;
    }
    String processGuess(int g) {
        if (N > g)
            return HS;
        else if (N < g)
            return LS;
        else
            return CS;
    }
    void playP1() {
        N = new Random().nextInt(H);
        for (; G > 0; G--) {
            String rslt = processGuess(getInt("Player 2, enter your guess:", "\\d?"));
            System.out.println(rslt);
            if (rslt.equals(CS)) {
                System.out.println("Player 2 wins!");
                break;
            }
        }
    }
    void playP2() {
        N = getInt("Player 1, enter your number:", "\\d+");
        int max = H;
        int min = L;
        int nextGuess = min + (max - min) / 2;
        for (; G > 0; G--) {
            System.out.println("Player 2, enter your guess:" + nextGuess);
            String rslt = processGuess(nextGuess);
            System.out.println(rslt);
            if (rslt.equals(HS)) {
                min = nextGuess + 1;
                nextGuess = fuzzify(nextGuess + (max - nextGuess) / 2, min, max);
            }
            if (rslt.equals(LS)) {
                max = nextGuess - 1;
                nextGuess = fuzzify(nextGuess - (nextGuess - min) / 2, min, max);
            }
            if (rslt.equals(CS)) {
                System.out.println("Player 2 wins!");
                break;
            }
        }
    }
    int fuzzify(int i, int mn, int mx) {
        int fz = new Random().nextInt(3);
        if (fz == 1)
            return Math.max(mn, --i);
        if (fz == 2)
            return Math.min(mx, ++i);
        return i;
    }
}
share|improve this answer
First of all: That doesn't even compile, as Java has no multi-line strings. You cannot expect to break lines in the middle of a string and that to work. – Joey Mar 3 '11 at 19:24
Ok, I stopped trying to make it look good on the screen and just pasted the single line. – Joe Zitzelberger Mar 3 '11 at 20:38
Furthermore (savings in parentheses): The class can be named with a single letter (40). There is plenty of unnecessary whitespace in there (80). You can collapse declarations of multiple variables of the same type, e.g. int a=5,b=10 (34). You can name the arguments in the constructor different from the fields to avoid this. (10). You can eliminate L altogether since it always remains at 1 (4). You can leave out initialization of H and G which get set in the constructor anyway (6). You can use one-letter names for all variables and methods (235). – Joey Mar 3 '11 at 20:41
True, but that would be totally unreadable. This is the point where I see code-golf really becomming code-bowling. But if I find some time, I'll polish it up tonight. – Joe Zitzelberger Mar 3 '11 at 20:49
Correction for the previous figure: (272). You can rewrite fuzzify using the conditional operator (20). You can inline the BufferedReader in getInt (19). You can use String#matches to avoid the Pattern and Matcher in getInt (48). You can use the conditional operator in processGuess as well (30). I'm now down to 1360 instead of your initial 1953. – Joey Mar 3 '11 at 21:08
show 3 more comments

Ruby 1.9 (298)

b=->f{puts "> "+f;gets}
a=->f{b[f].to_i}
q=a["Player 1 or 2?"]
i,j,g=100,1
n=q<2?a["Enter number:"]:rand(i)+j
5.times{q<2?(g=j+(i-j)/2
c=b["Guessing, #{g}"]
c[0]==?c?break: c[0]==?h?j=g :i=g):(
g=a["Guess:"]
puts g==n ?"correct":g<n ?"higher":"lower"
g==n&&break)}
puts "Player #{g==n ?2:1} won!"

Not very friendly instructions though.

share|improve this answer
Very nice! If only you had some randomization when AI is player 2... – Eelvex Mar 11 '11 at 18:35
@Eelvex, beaten by 30 chars. – zzzzBov Mar 11 '11 at 20:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.