# Nim game

**Nim game**

You are encouraged to solve this task according to the task description, using any language you may know.

Nim is a simple game where the second player - if they know the trick - will always win.

The game has only 3 rules.

- start with 12 tokens
- each player takes 1, 2, or 3 tokens in turn
- the player who takes the last token wins.

To win every time, the second player simply takes 4 minus the number the first player took. So if the first player takes 1, the second takes 3 - if the first player takes 2, the second should take 2 - and if the first player takes 3, the second player will take 1.

- Task

Design a simple Nim game where the human player goes first, and the computer always wins. The game should enforce the rules.

## Contents

- 1 11l
- 2 8080 Assembly
- 3 8086 Assembly
- 4 Ada
- 5 Algol-M
- 6 AsciiDots
- 7 AutoHotkey
- 8 AWK
- 9 BlooP
- 10 C
- 11 C++
- 12 C#
- 13 Common Lisp
- 14 Crystal
- 15 Factor
- 16 FreeBASIC
- 17 Go
- 18 IS-BASIC
- 19 Haskell
- 20 Java
- 21 JavaScript
- 22 Julia
- 23 Kotlin
- 24 Lua
- 25 MiniScript
- 26 Nim
- 27 Perl
- 28 Phix
- 29 Plain English
- 30 Prolog
- 31 Python
- 32 Racket
- 33 Raku
- 34 REXX
- 35 Ring
- 36 Ruby
- 37 Rust
- 38 S-Basic
- 39 Scala
- 40 Smalltalk
- 41 Tiny BASIC
- 42 Wren

## 11l[edit]

V tokens = 12

F getTokens(curTokens) -> N

print(‘How many tokens would you like to take? ’, end' ‘’)

V take = Int(input())

I (take < 1 | take > 3)

print("Number must be between 1 and 3.\n")

getTokens(curTokens)

R

:tokens = curTokens - take

print(‘You take #. tokens.’.format(take))

print("#. tokens remaining.\n".format(:tokens))

F compTurn(curTokens)

V take = curTokens % 4

:tokens = curTokens - take

print(‘Computer takes #. tokens.’.format(take))

print("#. tokens remaining.\n".format(:tokens))

L tokens > 0

getTokens(tokens)

compTurn(tokens)

print(‘Computer wins!’)

- Output:

How many tokens would you like to take? 2 You take 2 tokens. 10 tokens remaining. Computer takes 2 tokens. 8 tokens remaining. How many tokens would you like to take? 1 You take 1 tokens. 7 tokens remaining. Computer takes 3 tokens. 4 tokens remaining. How many tokens would you like to take? 3 You take 3 tokens. 1 tokens remaining. Computer takes 1 tokens. 0 tokens remaining. Computer wins!

## 8080 Assembly[edit]

It may not be a very interesting game, but it assembles to only 222 bytes.

bdos: equ 5 ; CP/M syscalls

puts: equ 9

putch: equ 2

getch: equ 1

maxtokens: equ 12 ; you can change this for more tokens

org 100h

lxi d,nim

call outs

mvi b,maxtokens ; 12 tokens

gameloop: lxi d,tokens ; Show tokens

call outs

mov c,b

showtokens: dcr c

jm tokensdone

mvi a,'|'

call outa

jmp showtokens

tokensdone: lxi d,nl

call outs

lxi d,prompt ; Show prompt

call outs

readinput: call ina ; Read input

sui '1' ; Subtract '1' (lowest acceptable

jc wrong ; input)

cpi 3 ; range of values is [0..2]

jnc wrong

cmp b ; can't take more than there are either

jnc wrong

cma ; negate; -a = ~(a-1)

mov c,a ; keep value

add b ; subtract from tokens

mov b,a

mvi a,4 ; computer take 4-X tokens

add c

mov c,a

lxi d,response ; print how many I take

call outs

mvi a,'0'

add c

call outa

mov a,b ; subtract the ones I take

sub c

jz done ; if I took the last one, I won

mov b,a

lxi d,nl

call outs

call outs

jmp gameloop

done: lxi d,lose ; there's no win condition

jmp outs

;; Invalid input

wrong: lxi d,wronginp

call outs

jmp readinput

;; Read character into A and keep registers

ina: push b

push d

push h

mvi c,getch

call bdos

jmp restore

;; Print A and keep registers

outa: push b

push d

push h

mvi c,putch

mov e,a

call bdos

jmp restore

;; Print string and keep registers

outs: push b

push d

push h

mvi c,puts

call bdos

;; Restore registers

restore: pop h

pop d

pop b

ret

nim: db 'Nim',13,10,13,10,'$'

prompt: db 'How many will you take (1-3)? $'

response: db 13,10,'I take $'

tokens: db 'Tokens: $'

lose: db 13,10,'You lose!$'

nl: db 13,10,'$'

wronginp: db 8,7,32,8,'$' ; beep and erase choice

## 8086 Assembly[edit]

This is a decent demonstration of the greater versatility of the 8086
when compared to the 8080. Where the 8080 only allowed complex operations
on its `A`

register, the other registers being limited to
loading, incrementing and decrementing, the 8086 allows most operations to use
any registers as its operands, leading to much shorter assembly code for the same
program.

The trade-off is a more complex instruction encoding, usually requiring two
bytes per instruction, minus any immediate operands. But that is ultimately
worth it: whereas the 8080 version takes 222 bytes, this 8086 Nim assembles to
only 173 bytes, mostly as a result of the three-instruction pattern of "load data into `A`

, do something with it, then store it elsewhere" simplifying to just one instruction to manipulate
the data in place.

;; MS-DOS Nim; assembles with nasm.

bits 16

cpu 8086

getch: equ 1

putch: equ 2

puts: equ 9 ; INT 21h calls

maxtokens: equ 12 ; Amount of tokens there are

section .text

org 100h

mov dx,nim ; Print sign-on

call outs

mov ch,maxtokens ; CH = amount of tokens we have

loop: mov dx,tokens ; Tokens: |||...

call outs

mov ah,putch ; Print a | for each token

mov dl,'|'

mov dh,ch

puttoks: int 21h

dec dh

jnz puttoks

mov dx,prompt ; Ask the user how many to take

call outs

ask: mov ah,getch ; Read keypress

int 21h

sub al,'1' ; Make number (minus one)

jc bad ; Carry, it was <1 (bad)

inc al ; Add 1 (because we subtracted '1')

cmp al,3

ja bad ; If it was >3, it is bad

cmp al,ch

ja bad ; If it was > amount left, it is bad

sub ch,al ; Remove your tokens from pile

mov cl,4 ; I take 4-N, which is 3-N-1

sub cl,al

sub ch,cl ; Remove my tokens from pile

mov dx,response ; Tell the user how many I took.

call outs

mov dl,'0'

add dl,cl

mov ah,putch

int 21h

cmp ch,0 ; Are there any tokens left?

jne loop ; If not, prompt again

mov dx,lose ; But otherwise, you've lost

; Fall through into print string routine and then stop.

;; Print string in DX. (This saves a byte each CALL)

outs: mov ah,puts

int 21h

ret

;; Input is bad; beep, erase, ask again

bad: mov dx,wronginp

call outs

jmp ask

section .data

nim: db 'Nim$'

prompt: db 13,10,'How many will you take (1-3)? $'

response: db 13,10,'I take $'

tokens: db 13,10,13,10,'Tokens: $'

lose: db 13,10,'You lose!$'

wronginp: db 8,7,32,8,'$'

## Ada[edit]

with Ada.Text_IO;

procedure Nim is

subtype Token_Range is Positive range 1 .. 3;

package TIO renames Ada.Text_IO;

package Token_IO is new TIO.Integer_IO(Token_Range);

procedure Get_Tokens(remaining : in Natural; how_many : out Token_Range) is

begin

loop

TIO.Put("How many tokens would you like to take? ");

begin

Token_IO.Get(TIO.Standard_Input, how_many);

exit when how_many < remaining;

raise Constraint_Error;

exception

when TIO.Data_Error | Constraint_Error =>

if not TIO.End_Of_Line(TIO.Standard_Input) then

TIO.Skip_Line(TIO.Standard_Input);

end if;

TIO.Put_Line("Invalid input.");

end;

end loop;

end;

tokens : Natural := 12;

how_many : Token_Range;

begin

loop

TIO.Put_Line(tokens'Img & " tokens remain.");

-- no exit condition here: human cannot win.

Get_Tokens(tokens, how_many);

TIO.Put_Line("Human takes" & how_many'Img & " tokens.");

tokens := tokens - how_many;

-- computer's turn: take the remaining N tokens to amount to 4.

how_many := tokens mod 4;

TIO.Put_Line("Computer takes" & how_many'Img & " tokens.");

tokens := tokens - how_many;

Ada.Text_IO.New_Line;

exit when tokens = 0;

end loop;

TIO.Put_Line("Computer won!");

end Nim;

- Output:

12 tokens remain. How many tokens would you like to take? a Invalid input. How many tokens would you like to take? 1 Human takes 1 tokens. Computer takes 3 tokens. 8 tokens remain. How many tokens would you like to take? 2 Human takes 2 tokens. Computer takes 2 tokens. 4 tokens remain. How many tokens would you like to take? 3 Human takes 3 tokens. Computer takes 1 tokens. Computer won!

## Algol-M[edit]

BEGIN

PROCEDURE WELCOME;

BEGIN

WRITE("THE GAME OF NIM");

WRITE("");

WRITE("WE BEGIN WITH 12 TOKENS. ON EACH TURN, A");

WRITE("PLAYER MAY TAKE BETWEEN 1 AND 3 TOKENS.");

WRITE("THE PLAYER WHO TAKES THE LAST TOKEN WINS.");

WRITE("");

END;

PROCEDURE SHOW(N);

INTEGER N;

BEGIN

WRITE("REMAINING TOKENS:",N);

END;

INTEGER FUNCTION GETNUM(LOWLIM, TOPLIM);

INTEGER LOWLIM, TOPLIM;

BEGIN

INTEGER OK, N;

OK := 0;

WHILE OK = 0 DO

BEGIN

WRITE("YOU TAKE:");

READ(N);

IF N < LOWLIM OR N > TOPLIM THEN

BEGIN

WRITE("MUST TAKE BETWEEN",LOWLIM," AND",TOPLIM,".");

WRITE("TRY AGAIN.");

END

ELSE

OK := 1;

END;

GETNUM := N;

END;

INTEGER FUNCTION PLAY(PLAYER, TOKENS, TAKEN);

INTEGER PLAYER, TOKENS, TAKEN;

BEGIN

IF PLAYER = 1 THEN % HUMAN PLAYER'S MOVE %

TAKEN := GETNUM(1,3)

ELSE % MACHINE'S MOVE %

TAKEN := 4 - TAKEN;

PLAY := TAKEN;

END;

PROCEDURE REPORT(WINNER);

INTEGER WINNER; % MACHINE = 0, HUMAN = 1 %

BEGIN

IF WINNER = 0 THEN

WRITE("I TOOK THE LAST ONE, SO I WIN. SORRY ABOUT THAT.")

ELSE

WRITE("YOU TOOK THE LAST ONE. YOU WIN. CONGRATULATIONS!");

END;

% MAIN CODE BEGINS HERE %

INTEGER PLAYER, TOKENS, TAKEN, HUMAN, MACHINE;

MACHINE := 0;

HUMAN := 1;

TOKENS := 12;

TAKEN := 0;

PLAYER := HUMAN;

WELCOME;

WRITE("YOU GO FIRST.");

WHILE TOKENS > 0 DO

BEGIN

SHOW(TOKENS);

TAKEN := PLAY(PLAYER, TOKENS, TAKEN);

TOKENS := TOKENS - TAKEN;

IF PLAYER = MACHINE THEN WRITE("I TOOK:",TAKEN);

IF TOKENS > 0 THEN PLAYER := 1 - PLAYER;

END;

REPORT(PLAYER);

WRITE("THANKS FOR PLAYING!");

END

- Output:

THE GAME OF NIM WE GEGIN WITH 12 TOKENS. ON EACH TURN, A PLAYER MAY TAKE BETWEEN 1 AND 3 TOKENS. THE PLAYER WHO TAKES THE LAST TOKEN WINS. YOU GO FIRST. REMAINING TOKENS: 12 YOU TAKE: -> 4 MUST TAKE BETWEEN 1 AND 3. TRY AGAIN. YOU TAKE: -> 3 REMAINING TOKENS: 9 I TOOK: 1 REMAINING TOKENS: 8 YOU TAKE: ->2 REMAINING TOKENS: 6 I TOOK: 2 REMAINING TOKENS: 4 YOU TAKE: -> 1 REMAINING TOKENS: 3 I TOOK: 3 I TOOK THE LAST ONE, SO I WIN. SORRY ABOUT THAT. THANKS FOR PLAYING!

## AsciiDots[edit]

%$LMRTX

.-$"Nim Dots"-$""-

/$_"Number must be "\

T /----~------\ |

*M /---+-*-[o] | |

R [-]\ .>#3-+[>][<]-1#<.| |

.-#12>--^ \"stod "$-#_$-" ekat uoY"_$---/ \--*----*-/ |

.>$_"How many dots would you like to take"---#?---/ |

\X X---------<".3 dna 1 neewteb"$/

/-----*L |

[-]--\ R |

| *-$_"Computer takes "-$_#-$" dots"/

M-*#4[%]

\---/

/----------------$"computer wins!"-&

/---~--

*#0[=]

L-------------*---*>$_#-$" dots remaining."-$""

T

- Output:

Nim Dots How many dots would you like to take?: 3 You take 3 dots 9 dots remaining. Computer takes 1 dots 8 dots remaining. How many dots would you like to take?: 1 You take 1 dots 7 dots remaining. Computer takes 3 dots 4 dots remaining. How many dots would you like to take?: 2 You take 2 dots 2 dots remaining. Computer takes 2 dots 0 dots remaining. computer wins!

## AutoHotkey[edit]

Play:

tokens := 12

while tokens {

while !(D>0 && D<4)

InputBox, D, Nim Game, % "Tokens Remaining = " tokens

. "`nHow many tokens would you like to take?"

. "`nChoose 1, 2 or 3"

tokens -= D

MsgBox % "Computer Takes " 4-D

tokens -= 4-d, d:=0

}

MsgBox, 262212,,Computer Always Wins!`nWould you like to play again?

IfMsgBox, Yes

gosub Play

else

ExitApp

return

## AWK[edit]

# syntax: GAWK -f NIM_GAME.AWK

BEGIN {

tokens = 12

printf("Nim game - using %d tokens\n",tokens)

while (tokens > 0) {

for (;;) {

printf("how many tokens 1-3? ")

getline ans

if (ans ~ /^[123]$/) {

tokens -= ans

prn("player")

break

}

print("invalid input, try again")

}

tokens -= ans = tokens % 4

prn("computer")

}

print("computer wins")

exit(0)

}

function prn(who) {

printf("%s takes %d token%s; there are %d remaining\n",who,ans,(ans==1)?"":"s",tokens)

}

- Output:

Nim game - using 12 tokens how many tokens 1-3? 1 player takes 1 token; there are 11 remaining computer takes 3 tokens; there are 8 remaining how many tokens 1-3? 2 player takes 2 tokens; there are 6 remaining computer takes 2 tokens; there are 4 remaining how many tokens 1-3? 3 player takes 3 tokens; there are 1 remaining computer takes 1 token; there are 0 remaining computer wins

## BlooP[edit]

Bloop has no input capabilites, so the game is defined as a procedure, called with 3 numbers (since the game will last only 3 rounds anyhow). The procedure can be called with more numbers - extra parameters are ignored in most implementations I have found. Since there is no easy way to get more inputs, any incorrect values are converted to correct ones.

DEFINE PROCEDURE ''DIVIDE'' [A,B]:

BLOCK 0: BEGIN

IF A < B, THEN:

QUIT BLOCK 0;

CELL(0) <= 1;

OUTPUT <= 1;

LOOP AT MOST A TIMES:

BLOCK 2: BEGIN

IF OUTPUT * B = A, THEN:

QUIT BLOCK 0;

OUTPUT <= OUTPUT + 1;

IF OUTPUT * B > A, THEN:

BLOCK 3: BEGIN

OUTPUT <= CELL(0);

QUIT BLOCK 0;

BLOCK 3: END;

CELL(0) <= OUTPUT;

BLOCK 2: END;

BLOCK 0: END.

DEFINE PROCEDURE ''MINUS'' [A,B]:

BLOCK 0: BEGIN

IF A < B, THEN:

QUIT BLOCK 0;

LOOP AT MOST A TIMES:

BLOCK 1: BEGIN

IF OUTPUT + B = A, THEN:

QUIT BLOCK 0;

OUTPUT <= OUTPUT + 1;

BLOCK 1: END;

BLOCK 0: END.

DEFINE PROCEDURE ''MODULUS'' [A,B]:

BLOCK 0: BEGIN

CELL(0) <= DIVIDE[A,B];

OUTPUT <= MINUS[A,CELL(0) * B];

BLOCK 0: END.

DEFINE PROCEDURE ''PLAYER_TURN'' [TOKENS_LEFT, TAKE]:

BLOCK 0: BEGIN

CELL(0) <= TAKE;

IF TAKE > 3, THEN:

BLOCK 1: BEGIN

CELL(0) <= MODULUS [TAKE, 3] + 1;

PRINT ['take must be between 1 and 3. setting take to ', CELL(0), '.'];

BLOCK 1: END;

IF TAKE < 1, THEN:

BLOCK 2: BEGIN

CELL(0) <= 1;

PRINT ['take must be between 1 and 3. setting take to 1.'];

BLOCK 2: END;

OUTPUT <= MINUS [TOKENS_LEFT, CELL(0)];

PRINT ['player takes ', CELL(0), ' tokens.'];

PRINT ['tokens remaining: ', OUTPUT];

PRINT [''];

BLOCK 0: END.

DEFINE PROCEDURE ''COMPUTER_TURN'' [TOKENS_LEFT]:

BLOCK 0: BEGIN

CELL(0) <= MODULUS [TOKENS_LEFT, 4];

OUTPUT <= MINUS [TOKENS_LEFT, CELL(0)];

PRINT ['computer takes ', CELL(0), ' tokens.'];

PRINT ['tokens remaining: ', OUTPUT];

PRINT [''];

BLOCK 0: END.

DEFINE PROCEDURE ''PLAY_GAME'' [FST, SEC, THD]:

BLOCK 0: BEGIN

CELL(0) <= FST;

CELL(1) <= SEC;

CELL(2) <= THD;

OUTPUT <= 12;

LOOP 3 TIMES:

BLOCK 1: BEGIN

OUTPUT <= PLAYER_TURN [OUTPUT, CELL(0)];

CELL(0) <= CELL(1);

CELL(1) <= CELL(2);

OUTPUT <= COMPUTER_TURN [OUTPUT];

BLOCK 1: END;

PRINT ['computer wins!'];

BLOCK 0: END.

PLAY_GAME [1,4,3];

- Output:

Sample game:

> PLAYER TAKES 1 TOKENS. > TOKENS REMAINING: 11 > > COMPUTER TAKES 3 TOKENS. > TOKENS REMAINING: 8 > > TAKE MUST BE BETWEEN 1 AND 3. SETTING TAKE TO 2. > PLAYER TAKES 2 TOKENS. > TOKENS REMAINING: 6 > > COMPUTER TAKES 2 TOKENS. > TOKENS REMAINING: 4 > > PLAYER TAKES 3 TOKENS. > TOKENS REMAINING: 1 > > COMPUTER TAKES 1 TOKENS. > TOKENS REMAINING: 0 > > COMPUTER WINS! => 0

## C[edit]

#include <stdio.h>

int playerTurn(int numTokens, int take);

int computerTurn(int numTokens);

int main(void)

{

printf("Nim Game\n\n");

int Tokens = 12;

while(Tokens > 0)

{

printf("How many tokens would you like to take?: ");

int uin;

scanf("%i", &uin);

int nextTokens = playerTurn(Tokens, uin);

if (nextTokens == Tokens)

{

continue;

}

Tokens = nextTokens;

Tokens = computerTurn(Tokens);

}

printf("Computer wins.");

return 0;

}

int playerTurn(int numTokens, int take)

{

if (take < 1 || take > 3)

{

printf("\nTake must be between 1 and 3.\n\n");

return numTokens;

}

int remainingTokens = numTokens - take;

printf("\nPlayer takes %i tokens.\n", take);

printf("%i tokens remaining.\n\n", remainingTokens);

return remainingTokens;

}

int computerTurn(int numTokens)

{

int take = numTokens % 4;

int remainingTokens = numTokens - take;

printf("Computer takes %u tokens.\n", take);

printf("%i tokens remaining.\n\n", remainingTokens);

return remainingTokens;

}

- Output:

Sample game:

Nim Game How many tokens would you like to take?: 4 Take must be between 1 and 3. How many tokens would you like to take?: 2 Player takes 2 tokens. 10 tokens remaining. Computer takes 2 tokens. 8 tokens remaining. How many tokens would you like to take?: 1 Player takes 1 tokens. 7 tokens remaining. Computer takes 3 tokens. 4 tokens remaining. How many tokens would you like to take?: 3 Player takes 3 tokens. 1 tokens remaining. Computer takes 1 tokens. 0 tokens remaining. Computer wins.

## C++[edit]

#include <iostream>

#include <limits>

using namespace std;

void showTokens(int tokens) {

cout << "Tokens remaining " << tokens << endl << endl;

}

int main() {

int tokens = 12;

while (true) {

showTokens(tokens);

cout << " How many tokens 1, 2 or 3? ";

int t;

cin >> t;

if (cin.fail()) {

cin.clear();

cin.ignore(numeric_limits<streamsize>::max(), '\n');

cout << endl << "Invalid input, try again." << endl << endl;

} else if (t < 1 || t > 3) {

cout << endl << "Must be a number between 1 and 3, try again." << endl << endl;

} else {

int ct = 4 - t;

string s = (ct > 1) ? "s" : "";

cout << " Computer takes " << ct << " token" << s << endl << endl;

tokens -= 4;

}

if (tokens == 0) {

showTokens(0);

cout << " Computer wins!" << endl;

return 0;

}

}

}

- Output:

Sample game:

Tokens remaining 12 How many tokens 1, 2 or 3? nim Invalid input, try again. Tokens remaining 12 How many tokens 1, 2 or 3? 1 Computer takes 3 tokens Tokens remaining 8 How many tokens 1, 2 or 3? 0 Must be a number between 1 and 3, try again. Tokens remaining 8 How many tokens 1, 2 or 3? 2 Computer takes 2 tokens Tokens remaining 4 How many tokens 1, 2 or 3? 3 Computer takes 1 token Tokens remaining 0 Computer wins!

## C#[edit]

using System;

namespace nimGame

{

class Program

{

static void Main(string[] args)

{

Console.WriteLine("There are twelve tokens.\n" +

"You can take 1, 2, or 3 on your turn.\n" +

"Whoever takes the last token wins.\n");

int tokens = 12;

while (tokens > 0)

{

Console.WriteLine("There are " + tokens + " remaining.");

Console.WriteLine("How many do you take?");

int playertake = Convert.ToInt32(Console.ReadLine());

if (playertake < 1 | playertake > 3)

{

Console.WriteLine("1, 2, or 3 only.");

}

else

{

tokens -= playertake;

Console.WriteLine("I take " + (4 - playertake) + ".");

tokens -= (4 - playertake);

}

}

Console.WriteLine("I win again.");

Console.ReadLine();

}

}

}

- Output:

Sample game:

There are twelve tokens. You can take 1, 2, or 3 on your turn. Whoever takes the last token wins. There are 12 remaining. How many do you take? 3 I take 1. There are 8 remaining. How many do you take? 1 I take 3. There are 4 remaining. How many do you take? 2 I take 2. I win again.

## Common Lisp[edit]

(defun pturn (curTokens)

(write-string "How many tokens would you like to take?: ")

(setq ans (read))

(setq tokensRemaining (- curTokens ans))

(format t "You take ~D tokens~%" ans)

(printRemaining tokensRemaining)

tokensRemaining)

(defun cturn (curTokens)

(setq take (mod curTokens 4))

(setq tokensRemaining (- curTokens take))

(format t "Computer takes ~D tokens~%" take)

(printRemaining tokensRemaining)

tokensRemaining)

(defun printRemaining (remaining)

(format t "~D tokens remaining~%~%" remaining))

(format t "LISP Nim~%~%")

(setq tok 12)

(loop

(setq tok (pturn tok))

(setq tok (cturn tok))

(if (<= tok 0)

(return)))

(write-string "Computer wins!")

- Output:

LISP Nim How many tokens would you like to take?: 2 You take 2 tokens 10 tokens remaining Computer takes 2 tokens 8 tokens remaining How many tokens would you like to take?: 1 You take 1 tokens 7 tokens remaining Computer takes 3 tokens 4 tokens remaining How many tokens would you like to take?: 3 You take 3 tokens 1 tokens remaining Computer takes 1 tokens 0 tokens remaining Computer wins!

## Crystal[edit]

tokens = 12

until tokens <= 0

puts "There are #{tokens} tokens remaining.\nHow many tokens do you take?"

until (input = (gets || "").to_i?) && (1..3).includes? input

puts "Enter an integer between 1 and 3."

end

puts "Player takes #{input} tokens.\nComputer takes #{4-input} tokens."

tokens -= 4

end

puts "Computer wins."

## Factor[edit]

USING: interpolate io kernel math math.parser sequences ;

IN: rosetta-code.nim-game

: get-input ( -- n )

"Number of tokens to take (1, 2, or 3): " write readln

string>number dup { 1 2 3 } member?

[ drop "Invalid move." print get-input ] unless ;

: .remaining ( n -- )

nl [I -~~==[ ${} tokens remaining ]==~~-I] nl nl ;

: .choice ( str n -- )

dup 1 = "" "s" ? [I ${} took ${} token${}I] nl ;

: (round) ( -- )

"You" get-input "Computer" 4 pick - [ .choice ] [email protected] ;

: round ( n -- n-4 )

dup dup .remaining [ drop (round) 4 - round ] unless-zero ;

: nim-game ( -- ) 12 round drop "Computer wins!" print ;

MAIN: nim-game

- Output:

-~~==[ 12 tokens remaining ]==~~- Number of tokens to take (1, 2, or 3): 1 You took 1 token Computer took 3 tokens -~~==[ 8 tokens remaining ]==~~- Number of tokens to take (1, 2, or 3): 3 You took 3 tokens Computer took 1 token -~~==[ 4 tokens remaining ]==~~- Number of tokens to take (1, 2, or 3): 4 Invalid move. Number of tokens to take (1, 2, or 3): 2 You took 2 tokens Computer took 2 tokens -~~==[ 0 tokens remaining ]==~~- Computer wins!

## FreeBASIC[edit]

dim as ubyte heap=12, take

while heap > 0

print using "There are ## tokens remaining. How many would you like to take?"; heap

input take

while take=0 orelse take>3

print "You must take 1, 2, or 3 tokens. How many would you like to take?"

input take

wend

print using "On my turn I will take ## tokens."; 4-take

heap = heap - 4

wend

print "I got the last token. I win! Better luck next time."

## Go[edit]

package main

import (

"bufio"

"fmt"

"os"

"strconv"

)

func showTokens(tokens int) {

fmt.Println("Tokens remaining", tokens, "\n")

}

func main() {

tokens := 12

scanner := bufio.NewScanner(os.Stdin)

for {

showTokens(tokens)

fmt.Print(" How many tokens 1, 2 or 3? ")

scanner.Scan()

if scerr := scanner.Err(); scerr != nil {

fmt.Println("Error reading standard input:", scerr)

return

}

t, err := strconv.Atoi(scanner.Text())

if err != nil || t < 1 || t > 3 {

fmt.Println("\nMust be a number between 1 and 3, try again.\n")

} else {

ct := 4 - t

s := "s"

if ct == 1 {

s = ""

}

fmt.Print(" Computer takes ", ct, " token", s, "\n\n")

tokens -= 4

}

if tokens == 0 {

showTokens(0)

fmt.Println(" Computer wins!")

return

}

}

}

- Output:

Sample game:

Tokens remaining 12 How many tokens 1, 2 or 3? 2 Computer takes 2 tokens Tokens remaining 8 How many tokens 1, 2 or 3? 4 Must be a number between 1 and 3, try again. Tokens remaining 8 How many tokens 1, 2 or 3? 1 Computer takes 3 tokens Tokens remaining 4 How many tokens 1, 2 or 3? 3 Computer takes 1 token Tokens remaining 0 Computer wins!

## IS-BASIC[edit]

100 PROGRAM "Nim.bas"

110 RANDOMIZE

120 CLEAR SCREEN

130 LET TOKENS=12

140 PRINT "Starting with";TOKENS;"tokens.":PRINT

150 DO

160 PRINT "How many tokens will you take? (1-3) ";

170 DO

180 LET K=VAL(INKEY$)

190 LOOP UNTIL K>0 AND K<4

200 LET TOKENS=MAX(TOKENS-K,0):LET G=0

210 PRINT K:PRINT TAB(19);TOKENS;"remainig.":PRINT

220 IF TOKENS>0 THEN

230 LET L=MOD(TOKENS,4)

240 IF L=0 THEN LET L=MIN(RND(3)+1,TOKENS)

250 LET TOKENS=TOKENS-L:LET G=-1

260 PRINT "Computer takes";L;"tokens.";TOKENS;"remaining.":PRINT

270 END IF

280 LOOP WHILE TOKENS>0

290 IF G THEN

300 PRINT "Computer wins!"

310 ELSE

320 PRINT "You win!"

330 END IF

## Haskell[edit]

import Data.Char (isDigit, digitToInt)

import System.IO

prompt :: String

prompt = "How many do you take? 1, 2 or 3? "

getPlayerSelection :: IO Int

getPlayerSelection = do

hSetBuffering stdin NoBuffering

c <- getChar

putChar '\n'

if isDigit c && digitToInt c <= 3 then

pure (digitToInt c)

else do

putStrLn "Invalid input"

putStr prompt

getPlayerSelection

play :: Int -> IO ()

play n = do

putStrLn $ show n ++ token n ++ " remain."

if n == 0 then putStrLn "Computer Wins!"

else do

putStr prompt

playerSelection <- getPlayerSelection

let computerSelection

| playerSelection > 4 = playerSelection - 4

| otherwise = 4 - playerSelection

putStrLn $ "Computer takes " ++ show computerSelection ++ token computerSelection ++ ".\n"

play (n - computerSelection - playerSelection)

where token 1 = " token"

token _ = " tokens"

main :: IO ()

main = play 12

- Output:

12 tokens remain. How many do you take? 1, 2 or 3? 3 Computer takes 1 token. 8 tokens remain. How many do you take? 1, 2 or 3? 2 Computer takes 2 tokens. 4 tokens remain. How many do you take? 1, 2 or 3? 1 Computer takes 3 tokens. 0 tokens remain. Computer Wins!

## Java[edit]

import java.util.Scanner;

public class NimGame {

public static void main(String[] args) {

runGame(12);

}

private static void runGame(int tokens) {

System.out.printf("Nim game.%n%n");

Scanner in = new Scanner(System.in);;

do {

boolean humanInputOk = false;

int humanTokens = 0;

while ( ! humanInputOk ) {

System.out.printf("Human takes how many tokens? ");

String input = in.next();

try {

humanTokens = Integer.parseInt(input);

if ( humanTokens >= 1 && humanTokens <= 3 ) {

humanInputOk = true;

}

else {

System.out.printf("Try a number between 1 and 3.%n");

}

}

catch (NumberFormatException e) {

System.out.printf("Invalid input. Try a number between 1 and 3.%n");

}

}

tokens -= humanTokens;

System.out.printf("You take %d token%s.%n%d token%s remaining.%n%n", humanTokens, humanTokens > 1 ? "s" : "", tokens, tokens != 1 ? "s" : "");

if ( tokens == 0 ) {

System.out.printf("You win!!.%n%n");

break;

}

int computerTokens = 4 - humanTokens;

tokens -= computerTokens;

System.out.printf("Computer takes %d token%s.%n%d token%s remaining.%n%n", computerTokens, computerTokens != 1 ? "s" : "", tokens, tokens != 1 ? "s" : "");

if ( tokens == 0 ) {

System.out.printf("Computer wins!!.%n%n");

}

} while (tokens > 0);

in.close();

}

}

- Output:

Sample game:

Nim game. Human takes how many tokens? nim Invalid input. Try a number between 1 and 3. Human takes how many tokens? 0 Try a number between 1 and 3. Human takes how many tokens? 2 You take 2 tokens. 10 tokens remaining. Computer takes 2 tokens. 8 tokens remaining. Human takes how many tokens? 1 You take 1 token. 7 tokens remaining. Computer takes 3 tokens. 4 tokens remaining. Human takes how many tokens? 3 You take 3 tokens. 1 token remaining. Computer takes 1 token. 0 tokens remaining. Computer wins!!.

## JavaScript[edit]

### Browser Version[edit]

This is the easy but dirty way - with prompt for input, and console.log for output. The Nim class was structured so that input and output could be customized, for example to use HTML DOM elements for in and out, instead of the terminal.

class Nim {

constructor(tokens, printFun) {

this.startTokens = tokens;

this.tokens = tokens;

this.printFun = printFun;

}

playerTurn(take) {

take = Math.round(take);

if (take < 1 || take > 3) {

this.printFun("take must be between 1 and 3.\n")

return false;

}

this.tokens -= take;

this.printFun("Player takes " + take + " tokens.");

this.printRemaining()

if (this.tokens === 0) {

this.printFun("Player wins!\n");

}

return true;

}

computerTurn() {

let take = this.tokens % 4;

this.tokens -= take;

this.printFun("Computer takes " + take + " tokens.");

this.printRemaining();

if (this.tokens === 0) {

this.printFun("Computer wins.\n");

}

}

printRemaining() {

this.printFun(this.tokens + " tokens remaining.\n");

}

}

let game = new Nim(12, console.log);

while (true) {

if (game.playerTurn(parseInt(prompt("How many tokens would you like to take?")))){

game.computerTurn();

}

if (game.tokens == 0) {

break;

}

}

- Output:

Sample game:

(prompt) How many tokens would you like to take? 2 Player takes 2 tokens. 10 tokens remaining. Computer takes 2 tokens. 8 tokens remaining. (prompt) How many tokens would you like to take? 4 take must be between 1 and 3. (prompt) How many tokens would you like to take? 0 take must be between 1 and 3. (prompt) How many tokens would you like to take? 3 Player takes 3 tokens. 5 tokens remaining. Computer takes 1 tokens. 4 tokens remaining. (prompt) How many tokens would you like to take? 1 Player takes 1 tokens. 3 tokens remaining. Computer takes 3 tokens. 0 tokens remaining. Computer wins.

## Julia[edit]

function nimgame()

tcount = 12

takenum = 0

while true

while true

permitted = collect(1:min(3,tcount))

println("$tcount tokens remain.\nHow many do you take ($permitted)? ")

takenum = parse(Int, strip(readline(stdin)))

if takenum in permitted

break

end

end

tcount -= 4

println("Computer takes $(4 - takenum). There are $tcount tokens left.")

if tcount < 1

println("Computer wins as expected.")

break

end

end

end

nimgame()

- Output:

12 tokens remain. How many do you take ([1, 2, 3])? 3 Computer takes 1. There are 8 tokens left. 8 tokens remain. How many do you take ([1, 2, 3])? 2 Computer takes 2. There are 4 tokens left. 4 tokens remain. How many do you take ([1, 2, 3])? 1 Computer takes 3. There are 0 tokens left. Computer wins as expected.

## Kotlin[edit]

// Version 1.3.21

fun showTokens(tokens: Int) {

println("Tokens remaining $tokens\n")

}

fun main() {

var tokens = 12

while (true) {

showTokens(tokens)

print(" How many tokens 1, 2 or 3? ")

var t = readLine()!!.toIntOrNull()

if (t == null || t < 1 || t > 3) {

println("\nMust be a number between 1 and 3, try again.\n")

} else {

var ct = 4 - t

var s = if (ct > 1) "s" else ""

println(" Computer takes $ct token$s\n")

tokens -= 4

}

if (tokens == 0) {

showTokens(0)

println(" Computer wins!")

return

}

}

}

- Output:

Sample game:

Tokens remaining 12 How many tokens 1, 2 or 3? 3 Computer takes 1 token Tokens remaining 8 How many tokens 1, 2 or 3? nim Must be a number between 1 and 3, try again. Tokens remaining 8 How many tokens 1, 2 or 3? 2 Computer takes 2 tokens Tokens remaining 4 How many tokens 1, 2 or 3? 1 Computer takes 3 tokens Tokens remaining 0 Computer wins!

## Lua[edit]

tokens = 12

print("Nim Game\n")

print("Starting with " .. tokens .. " tokens.\n\n")

function printRemaining()

print(tokens .. " tokens remaining.\n")

end

function playerTurn(take)

take = math.floor(take)

if (take < 1 or take > 3) then

print ("\nTake must be between 1 and 3.\n")

return false

end

tokens = tokens - take

print ("\nPlayer takes " .. take .. " tokens.")

printRemaining()

return true

end

function computerTurn()

take = tokens % 4

tokens = tokens - take

print("Computer takes " .. take .. " tokens.")

printRemaining()

end

while (tokens > 0) do

io.write("How many tokens would you like to take?: ")

if playerTurn(io.read("*n")) then

computerTurn()

end

end

print ("Computer wins.")

- Output:

Sample game output:

Nim Game Starting with 12 tokens. How many tokens would you like to take?: 3 Player takes 3 tokens. 9 tokens remaining. Computer takes 1 tokens. 8 tokens remaining. How many tokens would you like to take?: 4 Take must be between 1 and 3. How many tokens would you like to take?: 1 Player takes 1 tokens. 7 tokens remaining. Computer takes 3 tokens. 4 tokens remaining. How many tokens would you like to take?: 2 Player takes 2 tokens. 2 tokens remaining. Computer takes 2 tokens. 0 tokens remaining. Computer wins.

## MiniScript[edit]

tokens = 12

print "Nim Game"

print "Starting with " + tokens + " tokens."

printRemaining = function()

print tokens + " tokens remaining."

end function

playerTurn = function(take)

take = floor(val(take))

if take < 1 or take > 3 then

print "Take must be between 1 and 3."

return false

end if

globals.tokens = tokens - take

print "Player takes " + take + " tokens."

printRemaining

return true

end function

computerTurn = function()

take = tokens % 4

globals.tokens = tokens - take

print "Computer takes " + take + " tokens."

printRemaining

end function

while tokens > 0

if playerTurn(input("How many tokens would you like to take? ")) then

computerTurn

end if

end while

print "Computer wins."

- Output:

Nim Game Starting with 12 tokens. How many tokens would you like to take? 0 Take must be between 1 and 3. How many tokens would you like to take? 1 Player takes 1 tokens. 11 tokens remaining. Computer takes 3 tokens. 8 tokens remaining. How many tokens would you like to take? 2 Player takes 2 tokens. 6 tokens remaining. Computer takes 2 tokens. 4 tokens remaining. How many tokens would you like to take? 2 Player takes 2 tokens. 2 tokens remaining. Computer takes 2 tokens. 0 tokens remaining. Computer wins.

## Nim[edit]

import strutils

import terminal

var tokens = 12

styledEcho(styleBright, "Nim in Nim\n")

proc echoTokens() =

styledEcho(styleBright, "Tokens remaining: ", resetStyle, $tokens, "\n")

proc player() =

var take = '0'

styledEcho(styleBright, "- Your turn -")

echo "How many tokens will you take?"

while true:

stdout.styledWrite(styleDim, "Take (1–3): ", resetStyle)

take = getch()

stdout.write(take, '\n')

if take in {'1'..'3'}:

tokens -= parseInt($take)

break

else:

echo "Please choose a number between 1 and 3."

echoTokens()

proc computer() =

styledEcho(styleBright, "- Computer's turn -")

let take = tokens mod 4

tokens -= take

styledEcho("Computer took ", styleBright, $take, " ",

if take == 1: "token"

else: "tokens")

echoTokens()

while tokens > 0:

player()

computer()

styledEcho(styleBright, "Computer wins!")

- Output:

- Your turn - How many tokens will you take? Take (1–3): 1 Tokens remaining: 11 - Computer's turn - Computer took 3 tokens Tokens remaining: 8 - Your turn - How many tokens will you take? Take (1–3): 2 Tokens remaining: 6 - Computer's turn - Computer took 2 tokens Tokens remaining: 4 - Your turn - How many tokens will you take? Take (1–3): 3 Tokens remaining: 1 - Computer's turn - Computer took 1 token Tokens remaining: 0 Computer wins!

## Perl[edit]

use strict;

use warnings;

use feature 'say';

my $tokens = 12;

say "$tokens tokens remaining.\n";

while (1) {

print "How many tokens do you want to remove; 1, 2 or 3? : ";

(my $player = <>) =~ s/\s//g;

say "Nice try. $tokens tokens remaining.\n" and next

unless $player =~ /^[123]$/;

$tokens -= 4;

say "Computer takes @{[4 - $player]}.\n$tokens tokens remaining.\n";

say "Computer wins." and last

if $tokens <= 0;

}

- Output:

12 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 3 Computer takes 1. 8 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : -1 Nice try. 8 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 2 Computer takes 2. 4 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 1 Computer takes 3. 0 tokens remaining. Computer wins.

## Phix[edit]

integer tokens = 12, player = 0 while true do printf(1,"%2d tokens remaining. ",tokens) if tokens=0 then printf(1,"Computer wins.\n") exit end if printf(1,"How many tokens do you want to remove; 1, 2, or 3?:") while player<1 or player>3 do player=getc(0)-'0' end while printf(1,"%d. Computer takes %d.\n",{player,4-player}) tokens -= 4; player = 0 end while

- Output:

12 tokens remaining. How many tokens do you want to remove; 1, 2, or 3?:1. Computer takes 3. 8 tokens remaining. How many tokens do you want to remove; 1, 2, or 3?:2. Computer takes 2. 4 tokens remaining. How many tokens do you want to remove; 1, 2, or 3?:3. Computer takes 1. 0 tokens remaining. Computer wins.

## Plain English[edit]

To run:

Start up.

Play the game of Nim.

Write "The computer wins! Press esc to exit." on the console.

Wait for the escape key.

Shut down.

A piece is a number.

To play the game of Nim:

Put 12 into a piece count.

Loop.

If the piece count is 0, exit.

Write "There are " then the piece count then " pieces remaining." on the console.

Ask the player to take some pieces.

Subtract the pieces from the piece count.

Ask the computer to take some other pieces given the pieces.

Subtract the other pieces from the piece count.

Repeat.

To ask the player to take some pieces:

Write "Would you like to take 1, 2, or 3 pieces? " on the console without advancing.

Read a count from the console.

If the count is not between 1 and 3, repeat.

Format the count and "piece" or "pieces" into a string.

Write "You took " then the string then "." on the console.

Put the count into the pieces.

To ask the computer to take some pieces given some other pieces:

Put 4 minus the other pieces into a count.

Format the count and "piece" or "pieces" into a string.

Write "The computer took " then the string then "." on the console.

Put the count into the pieces.

- Output:

There are 12 pieces remaining. Would you like to take 1, 2, or 3 pieces? apple Would you like to take 1, 2, or 3 pieces? 4 Would you like to take 1, 2, or 3 pieces? 2 You took 2 pieces. The computer took 2 pieces. There are 8 pieces remaining. Would you like to take 1, 2, or 3 pieces? 3 You took 3 pieces. The computer took 1 piece. There are 4 pieces remaining. Would you like to take 1, 2, or 3 pieces? 1 You took 1 piece. The computer took 3 pieces. The computer wins! Press esc to exit.

## Prolog[edit]

nim :- next_turn(12), !.

next_turn(N) :-

% Player Turn

format('How many dots would you like to take? '),

read_line_to_codes(user_input, Line),

number_codes(PlayerGuess, Line),

member(PlayerGuess,[1,2,3]),

N1 is N - PlayerGuess,

format('You take ~d dots~n~d dots remaining.~n~n', [PlayerGuess, N1]),

% Computer Turn

CompGuess is 4 - PlayerGuess,

N2 is N1 - CompGuess,

format('Computer takes ~d dots~n~d dots remaining.~n~n', [CompGuess, N2]),

(

N2 = 0

-> format('Computer wins!')

; next_turn(N2)

).

- Output:

?- nim. How many dots would you like to take? 2 You take 2 dots 10 dots remaining. Computer takes 2 dots 8 dots remaining. How many dots would you like to take? 3 You take 3 dots 5 dots remaining. Computer takes 1 dots 4 dots remaining. How many dots would you like to take? 1 You take 1 dots 3 dots remaining. Computer takes 3 dots 0 dots remaining. Computer wins! true. ?-

## Python[edit]

Works on Python 3

print("Py Nim\n")

def getTokens(curTokens):

global tokens

print("How many tokens would you like to take? ", end='')

take = int(input())

if (take < 1 or take > 3):

print("Number must be between 1 and 3.\n")

getTokens(curTokens)

return

tokens = curTokens - take

print(f'You take {take} tokens.')

print(f'{tokens} tokens remaining.\n')

def compTurn(curTokens):

global tokens

take = curTokens % 4

tokens = curTokens - take

print (f'Computer takes {take} tokens.')

print (f'{tokens} tokens remaining.\n')

tokens = 12

while (tokens > 0):

getTokens(tokens)

compTurn(tokens)

print("Computer wins!")

- Output:

Py Nim How many tokens would you like to take? 2 You take 2 tokens. 10 tokens remaining. Computer takes 2 tokens. 8 tokens remaining. How many tokens would you like to take? 1 You take 1 tokens. 7 tokens remaining. Computer takes 3 tokens. 4 tokens remaining. How many tokens would you like to take? 3 You take 3 tokens. 1 tokens remaining. Computer takes 1 tokens. 0 tokens remaining. Computer wins!

## Racket[edit]

#lang racket

(define (print-remaining tokens-remaining)

(printf "~a tokens remain.\n" tokens-remaining))

(define (read-tokens)

(define num (read))

(cond

[(and (natural? num) (< num 4)) num]

[else

(display "Please enter a number between 1 to 3\n")

(read-tokens)]))

(define (pturn tokens-remaining)

(cond

[(not (zero? tokens-remaining))

(print-remaining tokens-remaining)

(display "Your turn. How many tokens? ")

(define n (read-tokens))

(cturn (- tokens-remaining n) n)]

[else (display "Computer wins!")]))

(define (cturn tokens-remaining p-took)

(cond

[(not (zero? tokens-remaining))

(print-remaining tokens-remaining)

(define c-take (- 4 p-took))

(printf "Computer takes ~a tokens\n" c-take)

(pturn (- tokens-remaining c-take))]

[else (display "You win!")]))

(pturn 12)

## Raku[edit]

(formerly Perl 6)

say my $tokens = 12, " tokens remaining.\n";

loop {

my $player = trim prompt "How many tokens do you want to remove; 1, 2 or 3? : ";

say "Nice try. $tokens tokens remaining.\n" and

next unless $player eq any <1 2 3>;

$tokens -= 4;

say "Computer takes {4 - $player}.\n$tokens tokens remaining.\n";

say "Computer wins." and last if $tokens <= 0;

}

- Sample output:

12 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 3 Computer takes 1. 8 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 6 Nice try. 8 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : G Nice try. 8 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 2 Computer takes 2. 4 tokens remaining. How many tokens do you want to remove; 1, 2 or 3? : 1 Computer takes 3. 0 tokens remaining. Computer wins.

## REXX[edit]

Programming notes: extra error checking was done with specific informative error messages. Also included was a method of quitting the game. The number of (starting) tokens (the *pot*) can be specified on the command line, the default is **12**.

/*REXX program plays the NIM game with a human opponent; the pot size can be specified. */

parse arg pot _ . 1 __ /*obtain optional argument from the CL.*/

if pot=='' | pot=="," then pot= 12 /*Not specified? Then use the default.*/

if _\=='' then do; call ser "Too many arguments entered: " __; exit 13; end

if \isNum(pot) then do; call ser "argument isn't numeric: " pot; exit 13; end

if \isInt(pot) then do; call ser "argument isn't an integer: " pot; exit 13; end

if pot<4 then do; call ser "The pot number is too small: " pot; exit 13; end

if pot>100 then do; call ser "The pot number is too large: " pot; exit 13; end

pad= copies('─', 8) /*literal used as an eyecatcher in msgs*/

pot= pot/1 /*normalize the pot (number). */

t= pot//4

if pot>12 & t\==0 then do; say pad 'The computer takes ' t " token"s(t).

pot= pot - t

end

do forever; call show pot

do until ok; ok= 1; say

say pad "How many tokens do you want to take away (1, 2, or 3) (or QUIT)?"

parse pull t _ . 1 q 1 __; upper q; say

if abbrev('QUIT',q,1) then do; say pad 'Quitting.'; exit 1; end

if t='' then call ser "No arguments entered."

if _\=='' then call ser "Too many arguments entered: " __

if \isNum(t) then call ser "Argument isn't numeric: " t

if \isInt(t) then call ser "Argument isn't an integer: " t

if t<1 then call ser "Argument can't be less than 1: " t

if t>3 then call ser "Argument can't be greater than 3: " t

end /*while*/

t= t/1 /*Normalize the number: 001 2. +3 */

#= max(1, 4-t) /*calculate the computer's take─away. */

say pad 'The computer takes ' # " token"s(#).

pot= pot - t - # /*calculate the number of tokens in pot*/

if pot==0 then do; say pad 'No tokens left.' /*No tokens left in the pot? */

say pad "The computer wins!" /*Display a braggart message.*/

exit /*exit this computer program.*/

end

end /*forever*/ /*keep looping until there's a winner. */

exit /*stick a fork in it, we're all done. */

/*──────────────────────────────────────────────────────────────────────────────────────*/

isNum: return datatype( arg(1), 'N') /*verify that the arg is a number. */

isInt: return datatype( arg(1), 'W') /* " " " " " an integer. */

show: say; say pad "Tokens remaining: " arg(1)' ' pad; say; return

s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1)

ser: if ok then say pad '***error***' arg(1); ok= 0; return

- output when using the default input:

──────── Tokens remaining: 12 ──────── ──────── How many tokens do you want to take away (1, 2, or 3) (or QUIT)? 2 ◄■■■■■■■■■■■ user input ──────── The computer takes 2 tokens. ──────── Tokens remaining: 8 ──────── ──────── How many tokens do you want to take away (1, 2, or 3) (or QUIT)? 3 ◄■■■■■■■■■■■ user input ──────── The computer takes 1 token. ──────── Tokens remaining: 4 ──────── ──────── How many tokens do you want to take away (1, 2, or 3) (or QUIT)? 1 ◄■■■■■■■■■■■ user input ──────── The computer takes 3 tokens. ──────── No tokens left. ──────── The computer wins!

## Ring[edit]

# Project : CalmoSoft Nim Game

# Date : 16/04/2020-13:27:07

# Update : 31/03/2021-19:41:09

# Author : Gal Zsolt (~ CalmoSoft ~)

# Email : <[email protected]>

load "stdlib.ring"

load "guilib.ring"

limit = 4

limit1 = 1

limit2 = 3

limit3 = 5

limit4 = 7

match1 = limit1

match2 = limit2

match3 = limit3

match4 = limit4

move1 = 0

move2 = 0

move3 = 0

move4 = 0

Button1 = list(limit1)

Button2 = list(limit2)

Button3 = list(limit3)

Button4 = list(limit4)

pcMove = 0

width = 60

height = 60

yourScore = 0

pcScore = 0

C_FONTSIZE = 15

C_NIM = "images/nim.jpg"

C_COMPUTER = "images/computer.jpg"

C_PROGRAMMER = "images/programmer.jpg"

app = new qApp

{

win = new qWidget() {

app.StyleFusionBlack()

setWindowTitle('CalmoSoft Nim Game')

setWinIcon(self,"images/nim.jpg")

setWindowFlags(Qt_SplashScreen | Qt_CustomizeWindowHint)

reSize(620,460)

for Col = 1 to limit1

Button1[Col] = new QPushButton(win) {

y = 230+(Col-1)*height

setgeometry(y+10,70,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

}

next

for Col = 1 to limit2

Button2[Col] = new QPushButton(win) {

y = 170+(Col-1)*height

setgeometry(y+10,150,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

}

next

for Col = 1 to limit3

Button3[Col] = new QPushButton(win) {

y = 110+(Col-1)*height

setgeometry(y+10,230,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

}

next

for Col = 1 to limit4

Button4[Col] = new QPushButton(win) {

y = 50+(Col-1)*height

setgeometry(y+10,310,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

}

next

Row1 = new QPushButton(win) {

setgeometry(500,70,width,height)

setStyleSheet("color:Black;background-color:Orange")

setSizePolicy(1,1)

setclickevent("deleteRow1()")

settext("Row1") }

Row2 = new QPushButton(win) {

setgeometry(500,150,width,height)

setStyleSheet("color:Black;background-color:Orange")

setSizePolicy(1,1)

setclickevent("deleteRow2()")

settext("Row2") }

Row3 = new QPushButton(win) {

setgeometry(500,230,width,height)

setStyleSheet("color:Black;background-color:Orange")

setSizePolicy(1,1)

setclickevent("deleteRow3()")

settext("Row3") }

Row4 = new QPushButton(win) {

setgeometry(500,310,width,height)

setStyleSheet("color:Black;background-color:Orange")

setSizePolicy(1,1)

setclickevent("deleteRow4()")

settext("Row4") }

labelYourScore = new QLabel(win) { setgeometry(60,20,150,30)

setFont(new qFont("Verdana",C_FONTSIZE,50,0))

settext("Your score: 0") }

labelComputerScore = new QLabel(win) { setgeometry(350,20,150,30)

setFont(new qFont("Verdana",C_FONTSIZE,50,0))

settext("PC score: 0") }

btnNewGame = new QPushButton(win) { setgeometry(60,400,80,30)

setFont(new qFont("Verdana",C_FONTSIZE,50,0))

settext("New")

setclickevent("newGame()") }

btnExit = new QPushButton(win) { setgeometry(400,400,80,30)

setFont(new qFont("Verdana",C_FONTSIZE,50,0))

settext("Exit")

setclickevent("pQuit()") }

btnPcMove = new QPushButton(win) { setgeometry(200,400,140,30)

setFont(new qFont("Verdana",C_FONTSIZE,50,0))

settext("PC move")

setclickevent("pcMove()") }

show()

}

exec()

}

func deleteRow1()

if move2 = 1 or move3 = 1 or move4 = 1

move1 = 0

return

else

move1 = 1

ok

if (match1 > 0) and (move1 = 1)

if pcMove = 1

Button1[match1] { seticon(new qicon(new qpixmap(C_COMPUTER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match1 = match1 - 1

move1 = 0

ok

if pcMove = 0

Button1[match1] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match1 = match1 - 1

ok

gameOver()

ok

func deleteRow2()

if move1 = 1 or move3 = 1 or move4 = 1

move2 = 0

return

else

move2 = 1

ok

if match2 > 0 and move2 = 1

if pcMove = 1

Button2[match2] { seticon(new qicon(new qpixmap(C_COMPUTER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match2 = match2 - 1

move2 = 0

ok

if pcMove = 0

Button2[match2] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match2 = match2 - 1

ok

gameOver()

ok

func deleteRow3()

if move1 = 1 or move2 = 1 or move4 = 1

move3 = 0

return

else

move3 = 1

ok

if match3 > 0 and move3 = 1

if pcMove = 1

Button3[match3] { seticon(new qicon(new qpixmap(C_COMPUTER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match3 = match3 - 1

move3 = 0

ok

if pcMove = 0

Button3[match3] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match3 = match3 - 1

ok

gameOver()

ok

func deleteRow4()

if move1 = 1 or move2 = 1 or move3 = 1

move4 = 0

return

else

move4 = 1

ok

if match4 > 0 and move4 = 1

if pcMove = 1

Button4[match4] { seticon(new qicon(new qpixmap(C_COMPUTER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match4 = match4 - 1

move4 = 0

ok

if pcMove = 0

Button4[match4] { seticon(new qicon(new qpixmap(C_PROGRAMMER)))

setIconSize(new qSize(55,55))

setenabled(false) }

match4 = match4 - 1

ok

gameOver()

ok

func pcMove()

move1 = 0

move2 = 0

move3 = 0

move4 = 0

pcMove = 1

for n = 1 to limit

if match1 > 0

rnd = random(match1-1)+1

for m = 1 to rnd

deleteRow1()

next

exit

ok

if match2 > 0

rnd = random(match2-1)+1

for m = 1 to rnd

deleteRow2()

next

exit

ok

if match3 > 0

rnd = random(match3-1)+1

for m = 1 to rnd

deleteRow3()

next

exit

ok

if match4 > 0

rnd = random(match4-1)+1

for m = 1 to rnd

deleteRow4()

next

exit

ok

next

pcMove = 0

func gameOver()

if (match1 = 0) and (match2 = 0) and (match3 = 0) and (match4 = 0)

if pcMove = 0

pcScore = pcScore + 1

labelComputerScore.settext("PC score: " + string(pcScore))

msgBox("Game Over! You Lost!")

else

yourScore = yourScore + 1

labelYourScore.settext("Your score: " + string(yourScore))

msgBox("Game Over! You Win!")

ok

ok

func newGame()

match1 = limit1

match2 = limit2

match3 = limit3

match4 = limit4

move1 = 0

move2 = 0

move3 = 0

move4 = 0

pcMove = 0

for Col = 1 to limit1

Button1[Col] = new QPushButton(win) {

y = 230+(Col-1)*height

setgeometry(y+10,70,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

show()

}

next

for Col = 1 to limit2

Button2[Col] = new QPushButton(win) {

y = 170+(Col-1)*height

setgeometry(y+10,150,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

show()

}

next

for Col = 1 to limit3

Button3[Col] = new QPushButton(win) {

y = 110+(Col-1)*height

setgeometry(y+10,230,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

show()

}

next

for Col = 1 to limit4

Button4[Col] = new QPushButton(win) {

y = 50+(Col-1)*height

setgeometry(y+10,310,width,height)

setSizePolicy(1,1)

seticon(new qicon(new qpixmap(C_NIM)))

setIconSize(new qSize(60,60))

show()

}

next

func msgBox(cText)

mb = new qMessageBox(win) {

setWindowTitle('CalmoSoft Nim Game')

setText(cText)

setstandardbuttons(QMessageBox_OK)

result = exec()

}

func pQuit()

win.close()

app.Quit()

Necessary image files:
Images file

Output:

Nim Game - video

## Ruby[edit]

[12, 8, 4].each do |remaining|

puts "There are #{remaining} dots.\nHow many dots would you like to take? "

unless (num=gets.to_i).between?(1, 3)

puts "Please enter one of 1, 2 or 3"

redo

end

puts "You took #{num} dots, leaving #{remaining-num}.\nComputer takes #{4-num}.\n\n"

end

puts "Computer took the last and wins."

- Output:

There are 12 dots. How many dots would you like to take? foo Please enter one of 1, 2 or 3 There are 12 dots. How many dots would you like to take? 1 You took 1 dots, leaving 11. Computer takes 3. There are 8 dots. How many dots would you like to take? 3 You took 3 dots, leaving 5. Computer takes 1. There are 4 dots. How many dots would you like to take? 2 You took 2 dots, leaving 2. Computer takes 2. Computer took the last and wins.

## Rust[edit]

fn main() {

let mut tokens = 12;

println!("Nim game");

println!("Starting with {} tokens.", tokens);

println!("");

loop {

tokens = p_turn(&tokens);

print_remaining(&tokens);

tokens = c_turn(&tokens);

print_remaining(&tokens);

if tokens == 0 {

println!("Computer wins!");

break;

}

}

}

fn p_turn(tokens: &i32) -> i32 {

loop { //try until we get a good number

println!("How many tokens would you like to take?");

let mut take = String::new();

io::stdin().read_line(&mut take)

.expect("Sorry, I didn't understand that.");

let take: i32 = match take.trim().parse() {

Ok(num) => num,

Err(_) => {

println!("Invalid input");

println!("");

continue;

}

};

if take > 3 || take < 1 {

println!("Take must be between 1 and 3.");

println!("");

continue;

}

return tokens - take;

}

}

fn c_turn(tokens: &i32) -> i32 {

let take = tokens % 4;

println!("Computer takes {} tokens.", take);

return tokens - take;

}

fn print_remaining(tokens: &i32) {

println!("{} tokens remaining.", tokens);

println!("");

}

- Output:

sample game:

Nim game Starting with 12 tokens. How many tokens would you like to take? foo Invalid input How many tokens would you like to take? 3 9 tokens remaining. Computer takes 1 tokens. 8 tokens remaining. How many tokens would you like to take? 5 Take must be between 1 and 3. How many tokens would you like to take? 2 6 tokens remaining. Computer takes 2 tokens. 4 tokens remaining. How many tokens would you like to take? 1 3 tokens remaining. Computer takes 3 tokens. 0 tokens remaining. Computer wins!

## S-Basic[edit]

$constant maxtokens = 12

$constant machine = 0

$constant human = 1

$constant false = 0

$constant true = 0FFFFH

procedure welcome

print "Welcome to the Game of Nim."

print "We begin with";maxtokens;" tokens. On each turn, a player"

print "may take between 1 and 3 tokens. The player who takes the"

print "last token wins."

end

procedure show(n = integer)

var i = integer

print "Available tokens:";n;" ";

rem - provide a visual display

for i = 1 to n

print "o ";

next i

end

function getnum(lowlim, toplim = integer) = integer

var ok, n = integer

repeat

begin

input "You take:";n

if n < lowlim or n > toplim then

begin

print "Must take between";lowlim;" and";toplim

print "Try again."

ok = false

end

else

ok = true

end

until ok

end = n

function play(player, tokens, taken = integer) = integer

if player = human then

taken = getnum(1,3)

else

taken = 4 - taken

end = taken

procedure report(player = integer)

if player = human then

print "You took the last one. You win. Congratulations!"

else

print "I took the last one, so I win. Sorry about that."

end

var player, tokens, taken = integer

welcome

tokens = maxtokens

taken = 0

player = human

print "You go first."

repeat

begin

show tokens

taken = play(player, tokens, taken)

tokens = tokens - taken

if player = machine then print "I took:";taken

if tokens > 0 then player = 1 - player

end

until tokens = 0

report player

print "Thanks for playing!"

end

- Output:

Welcome to the Game of Nim. We begin with 12 tokens. On each turn, a player may take between 1 and 3 tokens. The player who takes the last token wins. You go first. Available tokens: 12 o o o o o o o o o o o o You take:? 4 Must take between 1 and 3 Try again. You take:? 3 Available tokens: 9 o o o o o o o o o I took: 1 Available tokens: 8 o o o o o o o o You take:? 2 Available tokens: 6 o o o o o o I took: 2 Available tokens: 4 o o o o You take:? 1 Available tokens: 3 o o o I took: 3 I took the last one, so I win. Sorry about that. Thanks for playing!

## Scala[edit]

var tokens = 12

def playerTurn(curTokens: Int): Unit =

{

val take = readLine("How many tokens would you like to take? ").toInt

if (take < 1 || take > 3) {

println("Number must be between 1 and 3.")

playerTurn(curTokens)

}

else {

tokens = curTokens - take

println(s"You take $take tokens. $tokens tokens remaining.\n")

}

}

def compTurn(curTokens: Int): Unit =

{

val take = curTokens % 4

tokens = curTokens - take

println(s"Computer takes $take tokens. $tokens remaining.\n")

}

def main(args: Array[String]): Unit =

{

while (tokens > 0)

{

playerTurn(tokens)

compTurn(tokens)

}

println("Computer wins!")

}

## Smalltalk[edit]

Object subclass: Nim [

| tokens |

<comment: 'I am a game of nim'>

Nim class >> new [

<category: 'instance creation'>

^(super new) init: 12

]

init: t [

<category: 'instance creation'>

tokens := t.

^self

]

pTurn [

| take |

<category: 'gameplay'>

Transcript nextPutAll: 'How many tokens will you take?: '.

take := (stdin nextLine) asNumber.

((take < 1) | (take > 3))

ifTrue: [Transcript nextPutAll: 'Invalid input';nl;nl. self pTurn]

ifFalse: [tokens := tokens - take]

]

cTurn [

| take |

<category: 'gameplay'>

take := tokens - (4 * (tokens // 4)). "tokens % 4"

Transcript nextPutAll: 'Computer takes '.

take printOn: Transcript.

Transcript nextPutAll: ' tokens';nl.

tokens := tokens - take

]

mainLoop [

<category: 'main loop'>

Transcript nextPutAll: 'Nim game';nl.

Transcript nextPutAll: 'Starting with '.

tokens printOn: Transcript.

Transcript nextPutAll: ' tokens';nl;nl.

1 to: 3 do: [ :n | "The computer always wins on the 3rd turn"

self pTurn.

self printRemaining.

self cTurn.

self printRemaining.

(tokens = 0)

ifTrue:[Transcript nextPutAll: 'Computer wins!';nl. ^0]

]

]

printRemaining [

<category: 'information'>

tokens printOn: Transcript.

Transcript nextPutAll: ' tokens remaining';nl;nl

]

]

g := Nim new.

g mainLoop.

- Output:

sample game:

Nim game Starting with 12 tokens How many tokens will you take?: foo Invalid input How many tokens will you take?: 3 9 tokens remaining Computer takes 1 tokens 8 tokens remaining How many tokens will you take?: 4 Invalid input How many tokens will you take?: 2 6 tokens remaining Computer takes 2 tokens 4 tokens remaining How many tokens will you take?: 1 3 tokens remaining Computer takes 3 tokens 0 tokens remaining Computer wins!

## Tiny BASIC[edit]

10 LET H = 12

20 PRINT "There are"

30 PRINT H

40 PRINT "tokens remaining. How many would you like to take?"

50 INPUT T

60 IF T > 3 THEN GOTO 170

70 IF T < 1 THEN GOTO 170

80 LET H = H - T

90 IF H = 0 THEN GOTO 190

100 LET T = 4 - T

110 PRINT "I will take"

120 PRINT T

130 PRINT "tokens."

140 LET H = H - T

150 IF H = 0 THEN GOTO 210

160 GOTO 20

170 PRINT "You must take 1, 2, or 3 tokens."

180 GOTO 50

190 PRINT "Congratulations. You got the last token."

200 END

210 PRINT "I got the last token. I win. Better luck next time."

220 END

## Wren[edit]

import "io" for Stdin, Stdout

var showTokens = Fn.new { |tokens| System.print("Tokens remaining %(tokens)\n") }

var tokens = 12

while (true) {

showTokens.call(tokens)

System.write(" How many tokens 1, 2 or 3? ")

Stdout.flush()

var t = Num.fromString(Stdin.readLine())

if (t.type != Num || !t.isInteger || t < 1 || t > 3) {

System.print("\nMust be an integer between 1 and 3, try again.\n")

} else {

var ct = 4 - t

var s = (ct != 1) ? "s" : ""

System.write(" Computer takes %(ct) token%(s)\n\n")

tokens = tokens - 4

}

if (tokens == 0) {

showTokens.call(0)

System.print(" Computer wins!")

break

}

}

- Output:

Sample game:

Tokens remaining 12 How many tokens 1, 2 or 3? 2 Computer takes 2 tokens Tokens remaining 8 How many tokens 1, 2 or 3? 4 Must be an integer between 1 and 3, try again. Tokens remaining 8 How many tokens 1, 2 or 3? 1 Computer takes 3 tokens Tokens remaining 4 How many tokens 1, 2 or 3? 3 Computer takes 1 token Tokens remaining 0 Computer wins!

- Puzzles
- Games
- Programming Tasks
- Solutions by Programming Task
- 11l
- 8080 Assembly
- 8086 Assembly
- Ada
- Algol-M
- AsciiDots
- AutoHotkey
- AWK
- BlooP
- C
- C++
- C sharp
- Common Lisp
- Crystal
- Factor
- FreeBASIC
- Go
- IS-BASIC
- Haskell
- Java
- JavaScript
- Julia
- Kotlin
- Lua
- MiniScript
- Nim
- Perl
- Phix
- Plain English
- Prolog
- Python
- Racket
- Raku
- REXX
- Ring
- Ruby
- Rust
- S-Basic
- Scala
- Smalltalk
- Tiny BASIC
- Wren