Nim game: Difference between revisions

From Rosetta Code
Content added Content deleted
(add javascript (browser))
m (alphabetized entries ;D)
Line 419: Line 419:


Computer wins!
Computer wins!
</pre>

=={{header|Go}}==
<lang go>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
}
}
}</lang>

{{out}}
Sample game:
<pre>
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!
</pre>
</pre>


Line 509: Line 583:


Computer wins.
Computer wins.
</pre>



=={{header|Lua}}==
<lang Lua>
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.")
</lang>

{{out}}
Sample game output:
<pre>
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.
</pre>

=={{header|Go}}==
<lang go>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
}
}
}</lang>

{{out}}
Sample game:
<pre>
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!
</pre>
</pre>


Line 763: Line 683:


Computer wins!
Computer wins!
</pre>

=={{header|Lua}}==
<lang Lua>
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.")
</lang>

{{out}}
Sample game output:
<pre>
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.
</pre>
</pre>



Revision as of 15:24, 16 April 2019


Task
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.

AsciiDots

<lang AsciiDots> %$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

</lang>

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!

BlooP

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. <lang BlooP> 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]; </lang>

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

<lang c>

  1. 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; } </lang>

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++

Translation of: Go

<lang cpp>#include <iostream>

  1. 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;
       }
   }

}</lang>

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!

Common Lisp

<lang lisp> (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!") </lang>

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!

Go

<lang go>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
       }
   }

}</lang>

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!

JavaScript

Browser Version

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. <lang Javascript> 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; } } </lang>

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

Translation of: Perl 6

<lang julia>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()

</lang>

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

Translation of: Go

<lang scala>// 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
       }
   }

}</lang>

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

<lang Lua> 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.") </lang>

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.

Perl

Translation of: Perl 6

<lang perl>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;

}</lang>

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.

Perl 6

Works with: Rakudo version 2019.03

<lang perl6>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;

}</lang>

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.

Python

Works on Python 3 <lang Python> 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!") </lang>

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!

REXX

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. <lang rexx>/*REXX program plays the NIM game with a human opponent; the pot size can be specified. */ pad= copies('─', 8) /*eyecatcher literal used in messages. */ 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 pot= pot/1 /*normalize the pot (number). */

    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  */
    #= 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</lang>

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!