Nim game: Difference between revisions
m (added the text "human".) |
Thundergnat (talk | contribs) (→{{header|Perl 6}}: Add a Perl 6 example) |
||
Line 336: | Line 336: | ||
Computer wins! |
Computer wins! |
||
</pre> |
</pre> |
||
=={{header|Perl 6}}== |
|||
{{works with|Rakudo|2019.03}} |
|||
<lang perl6>say my $tokens = 12, " tokens remaing.\n"; |
|||
while my $player = prompt "How many tokens do you want to remove; 1, 2 or 3? : " { |
|||
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> |
|||
{{out|Sample output}} |
|||
<pre>12 tokens remaing. |
|||
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? : 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.</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
Revision as of 10:24, 11 April 2019
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> %$MXTRL .-$"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 v0.5 by Prof_Apex 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!
C++
<lang cpp>#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; } }
}</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!
Kotlin
<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!
Perl 6
<lang perl6>say my $tokens = 12, " tokens remaing.\n";
while my $player = prompt "How many tokens do you want to remove; 1, 2 or 3? : " {
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 remaing. 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? : 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
<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 0.5 by Prof_Apex 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!