Go Fish: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 401: Line 401:
]
]
; c and p = computer and player
chand: [] ;-- c and p = computer and player
chand: []
cguesses: []
cguesses: []
phand: []
phand: []
Line 412: Line 411:
***************
***************
}
}
pip: ["a" "2" "3" "4" "5" "6" "7" "8" "9" "10" "j" "q" "k"]
pip: ["a" "2" "3" "4" "5" "6" "7" "8" "9" "10" "j" "q" "k"] ;-- suits are not relevant
pile: [] ;-- where discarded cards go
pile: []
;---------------------
;---------------------
Line 425: Line 424:
clear-and-show: func [duration str][
clear-and-show: func [duration str][
{
Poor persons animation.
Blips message to screen after a pause of duration length.

}
clear-screen
clear-screen
print str
print str
Line 438: Line 442:
find-in: func [blk str][
find-in: func [blk str][
"Finds a string value in a block. Series in series."
foreach i blk [if find i str [return i]]
foreach i blk [if find i str [return i]]
]
]
Line 445: Line 450:
deal-cards num hand
deal-cards num hand
][
][
; take from pile if deck is empty
append hand rejoin [trim/all form take pile] ;-- take from pile if deck is empty
append hand rejoin [trim/all form take pile]
]
]
]
]
Line 453: Line 457:
{
{
Randomly picks from hand minus guessed.
Randomly picks from hand minus guessed.

Simulates a person asking for different cards on
Simulates a person asking for different cards on
their next turn if their previous guess resulted
their next turn if their previous guess resulted
Line 472: Line 476:
return new-deck
return new-deck
]
]
shuffle: function [deck [block!]] [deck: random deck]
shuffle: function [deck [block!]] [deck: random deck]
Line 478: Line 481:
transfer-cards: func [
transfer-cards: func [
"Transfers cards from one hand to another"
"Transfers cards from player to player"
fhand "from hand"
fhand "from hand"
thand "to hand"
thand "to hand"
Line 520: Line 523:
][
][
if empty? fhand [go-fish 3 fhand]
if empty? fhand [go-fish 3 fhand]

if none? find-in thand kind [ ;-- player has to hold rank asked for
clear-and-show 1.0
"You have to have that rank in your hand to ask for it.^/Computers turn..."
exit
]

either find-in fhand kind [
either find-in fhand kind [
check-for-books thand kind
check-for-books thand kind
transfer-cards fhand thand kind
transfer-cards fhand thand kind
show-cards
show-cards
if find-in thand kind [ ;-- player has to have rank asked for
if find-in thand kind [
p: ask "Your guess: "
p: ask "Your guess: "
either p = "x" [halt][player-turn fhand thand p]
either p = "x" [halt][player-turn fhand thand p]
Line 536: Line 546:
check-for-books: func [
check-for-books: func [
{
Checks for a book in a players hand.
Increments the players book score, and
discards the book from the players hand
}
hand "from or to hand"
hand "from or to hand"
kind "rank of cards"
kind "rank of cards"
Line 566: Line 581:
}
}
if empty? chand [
if empty? chand [ ; computer has no more cards? fish 3 cards.
go-fish 3 chand
go-fish 3 chand
show-cards
show-cards
Line 580: Line 595:
}
}


if empty? phand [
if empty? phand [ ;-- player has no more cards? fish 3 cards.
go-fish 3 phand
go-fish 3 phand
show-cards
show-cards
Line 604: Line 619:


demo
demo

</lang>
</lang>



Revision as of 01:49, 9 February 2022

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

Write a program to let the user play Go Fish against a computer opponent. Use the following rules:

  • Each player is dealt nine cards to start with.
  • On their turn, a player asks their opponent for a given rank (such as threes or kings). A player must already have at least one card of a given rank to ask for more.
    • If the opponent has any cards of the named rank, they must hand over all such cards, and the requester can ask again.
    • If the opponent has no cards of the named rank, the requester draws a card and ends their turn.
  • A book is a collection of every card of a given rank. Whenever a player completes a book, they may remove it from their hand.
  • If at any time a player's hand is empty, they may immediately draw a new card, so long as any new cards remain in the deck.
  • The game ends when every book is complete. The player with the most books wins.

The game's AI need not be terribly smart, but it should use at least some strategy. That is, it shouldn't choose legal moves entirely at random.

You may want to use code from Playing Cards.

Related tasks:


Aime

See Go Fish/Aime

AutoHotkey

See Go Fish/AutoHotkey

C

See Go Fish/C

C++

See Go Fish/C++

D

See Go Fish/D

Erlang

See Go Fish/Erlang

FreeBASIC

<lang freebasic> ' Go Fish ~ ¡Pesca!

Const cartas = "A234567890JQK"

Declare Sub Reparto_Cartas Declare Sub Pescar_Carta_Jug Declare Sub Pescar_Carta_CPU Declare Sub Comprobar_Libro_Jug Declare Sub Comprobar_Libro_CPU Declare Sub Comprobar_Fin_Partida Declare Sub Intro

Dim Shared As Integer play(13), compu(13), deck(13), guess(13), poss(13), asked(13) Dim Shared As String nombre, Snombre, CartaPedida Dim Shared puntos(2) As Byte = {0,0} Dim Shared As Integer remca = 4*Len(cartas) Dim Shared As Integer i, k, j, cn For i = 1 To 13

   deck(i) = 4

Next i For i = 1 To 9

   Reparto_Cartas
   deck(k) -= 1
   compu(k) += 1
   Reparto_Cartas
   deck(k) -= 1
   play(k) += 1

Next i Dim As Integer v, po

Sub Reparto_Cartas

   remca -= 1
   Dim As Integer sc = remca * Rnd + 1
   For k = 1 To 13
       sc -= deck(k)
       If sc <= 0 Then Return
   Next k

End Sub

Sub Pescar_Carta_Jug

   Reparto_Cartas
   Print " " &Mid(cartas,k,1) &"."
   deck(k) -= 1
   play(k) += 1

End Sub

Sub Pescar_Carta_CPU

   Reparto_Cartas
   Print "a carta."
   deck(k) -= 1
   compu(k) += 1

End Sub

Sub Comprobar_Libro_Jug

   For i = 1 To 13
       If play(i) <> 4 Then
       Else
           Color 11: Print Snombre &" completa el libro de " &Mid(cartas,i,1) &"'s.": Color 7
           play(i) = 0
           puntos(0) += 1
       End If
   Next i

End Sub

Sub Comprobar_Libro_CPU

   For i = 1 To 13
       If compu(i) <> 4 Then
       Else
           Color 11: Print Snombre &" completa el libro de " &Mid(cartas,i,1) &"'s.": Color 7
           compu(i) = 0
           puntos(1) += 1
       End If
   Next i

End Sub

Sub Comprobar_Fin_Partida

   Dim As Integer np = 0, nc = 0
   For i = 1 To 13
       np += play(i)
       nc += compu(i)
   Next i
   If remca = 0 Or np = 0 Or nc = 0 Then         
       Color 15: Print
       Print "*** ­FIN de la partida! ***"
       Print
       If puntos(0) < puntos(1) Then 
           Print "La CPU ha ganado."
       Elseif puntos(0) > puntos(1) Then 
           Print nombre &" ha ganado." 
       Else 
           Print "­Es un empate!"
       End If
       Sleep: End
   End If

End Sub

Sub Intro

   Color 15 
   Print "                __ _     _      "
   Print "  __ _  ___    / _(_)___| |__   "
   Print " /  ` |/ _ \  | |_| / __| '_ \  "
   Print "| (_) | (_) | |  _| \__ \ | | | "
   Print " \__, |\___/  |_| |_|___/_| |_| "
   Print " |___/                          "
   Print "                                "
   Color 14: Locate 10, 2: Input "Como te llamas: ", nombre

End Sub

'--- Programa Principal --- Cls Randomize Timer Intro Do

   Dim As boolean MuestraMano = false
   While MuestraMano = false
       Color 15: Print Chr(10) &"Puntos >> " &nombre &": "; puntos(0); "  CPU: "; puntos(1)
       Color 13: Print Chr(10) &space(10) &remca &" cartas restantes"
       Color 14: Print Chr(10) &"Tu mano: ";
       For i = 1 To 13
           If Not play(i) Then 
               For j = 1 To play(i)
                   Print Mid(cartas,i,1); " ";
               Next j
           End If
       Next i
       Print
       
       Dim As boolean PideCarta = false
       While PideCarta = false
           Comprobar_Fin_Partida
           Snombre = nombre
           Color 7: Print
           Input "¨Que carta pides... "; CartaPedida
           Print
           If CartaPedida <> "" Then cn = Instr(cartas, Ucase(CartaPedida)): PideCarta = true
           If cn = 0 Then 
               Print "Lo siento, no es una opción valida.": PideCarta = false
               Elseif play(cn) = 0 Then Color 12: Print "­No tienes esa carta!": Color 7: PideCarta = false
           End If
       Wend
       
       guess(cn) = 1
       If compu(cn) = 0 Then 
           Print Snombre &", ";
           Color 15: Print "­ve a pescar!"
           Color 7: Print Snombre &" pesca un";: Pescar_Carta_Jug
           Comprobar_Libro_Jug
           MuestraMano = true
       Else
           v = compu(cn)
           compu(cn) = 0
           play(cn) += v
           Print Snombre &" consigue " &v &" carta(s) mas."
           Comprobar_Libro_Jug
           MuestraMano = false
       End If
   Wend
   Snombre = "CPU"
   For i = 1 To 13
       asked(i) = 0
   Next i
   Dim As boolean Turno_CPU_2 = false
   While Turno_CPU_2 = false
       Comprobar_Fin_Partida
       po = 0
       For i = 1 To 13
           If (compu(i) > 0) And (guess(i) > 0) Then poss(i) = 1: po += 1
       Next i
       If po = 0 Then 
           Do
               k = (Rnd*12)+1
           Loop While compu(k) = 0 Or asked(k)
       Else
           Do
               k = (Rnd*12)+1
           Loop While poss(k) = 0
           guess(k) = 0
           asked(k) = 1
       End If
       Print: Print Snombre &" quiere tus " &Mid(cartas,k,1) &"'s."
       asked(k) = 1
       If play(k) = 0 Then 
           Print Snombre &", ";
           Color 15: Print "­ve a pescar!"
           Color 7:Print Snombre &" pesca un";: Pescar_Carta_CPU
           Comprobar_Libro_CPU
           Turno_CPU_2 = true
       Else
           v = play(k)
           play(k) = 0
           compu(k) += v
           Print Snombre &" consigue " &v &" carta(s) mas."
           Comprobar_Libro_CPU
           Turno_CPU_2 = false
       End If
   Wend 

Loop End </lang>

Go

See Go Fish/Go

Haskell

See Go Fish/Haskell

Icon and Unicon

See Go Fish/Unicon

J

See Go Fish/J

Java

See Go Fish/Java

Julia

see Go Fish/Julia

Kotlin

See Go Fish/Kotlin

Locomotive Basic

See Go Fish/Locomotive Basic

Mathematica / Wolfram Language

See Go Fish/Mathematica

Nim

See Go Fish/Nim

OCaml

See Go Fish/OCaml

Perl

<lang perl>#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Go_Fish use warnings; use List::Util qw( first shuffle );

my $pat = qr/[atjqk2-9]/; # ranks my $deck = join , shuffle map { my $rank = $_; map "$rank$_", qw( S H C D ) }

 qw( a t j q k ), 2 .. 9;

my $mebooks = my $youbooks = 0;

my $me = substr $deck, 0, 2 * 9, ; my $mepicks = join , $me =~ /$pat/g; arrange($me); $mebooks++ while $me =~ s/($pat).\1.\1.\1.//; my $you = substr $deck, 0, 2 * 9, ; my $youpicks = join , $you =~ /$pat/g; arrange($you); $youbooks++ while $you =~ s/($pat).\1.\1.\1.//;

while( $mebooks + $youbooks < 13 )

 {
 play( \$you, \$youbooks, \$youpicks, \$me, \$mebooks, 1 );
 $mebooks + $youbooks == 13 and last;
 play( \$me, \$mebooks, \$mepicks, \$you, \$youbooks, 0 );
 }

print "me $mebooks you $youbooks\n";

sub arrange { $_[0] = join , sort $_[0] =~ /../g }

sub human

 {
 my $have = shift =~ s/($pat).\K(?!\1)/ /gr;
 local $| = 1;
 my $pick;
 do
   {
   print "You have $have, enter request: ";
   ($pick) = lc(<STDIN>) =~ /$pat/g;
   } until $pick and $have =~ /$pick/;
 return $pick;
 }

sub play

 {
 my ($me, $mb, $lastpicks, $you, $yb, $human) = @_;
 my $more = 1;
 while( arrange( $$me ), $more and $$mb + $$yb < 13 )
   {
  1. use Data::Dump 'dd'; dd \@_, "deck $deck";
   if( $$me =~ s/($pat).\1.\1.\1.// )
     {
     print "book of $&\n";
     $$mb++;
     }
   elsif( $$me )
     {
     my $pick = $human ? do { human($$me) } : do
       {
       my %picks;
       $picks{$_}++ for my @picks = $$me =~ /$pat/g;
       my $pick = first { $picks{$_} } split(//, $$lastpicks), shuffle @picks;
       print "pick $pick\n";
       $$lastpicks =~ s/$pick//g;
       $$lastpicks .= $pick;
       $pick;
       };
     if( $$you =~ s/(?:$pick.)+// )
       {
       $$me .= $&;
       }
     else
       {
       print "GO FISH !!\n";
       $$me .= substr $deck, 0, 2, ;
       $more = 0;
       }
     }
   elsif( $deck )
     {
     $$me .= substr $deck, 0, 2, ;
     }
   else
     {
     $more = 0;
     }
   }
 arrange( $$me );
 }</lang>

Phix

See Go Fish/Phix

PicoLisp

See Go Fish/PicoLisp

PowerShell

See Go Fish/PowerShell

PureBasic

See Go Fish/PureBasic

Python

See Go Fish/Python

Racket

This example is incorrect. Please fix the code and remove this message.

Details: link broken.

See gofish.rkt. Documentation: Go Fish.

Raku

(formerly Perl 6) See Go Fish/Raku

Red

<lang red> Red [

   Title:  "Go Fish"
   Author: "gltewalt"

]

chand: []  ;-- c and p = computer and player cguesses: [] phand: [] cbooks: 0 pbooks: 0 gf: {

   ***************
   *   GO FISH   *
   ***************

} pip: ["a" "2" "3" "4" "5" "6" "7" "8" "9" "10" "j" "q" "k"] ;-- suits are not relevant pile: []  ;-- where discarded cards go

---------------------
Helper functions -
---------------------

clear-screen: does [

   "clears the console"
   call/console either system/platform = 'Linux ["clear"]["cls"]

]

clear-and-show: func [duration str][

   {
       Poor persons animation. 
       Blips message to screen after a pause of duration length.
   }
   clear-screen
   print str 
   wait duration 
   clear-screen

]

deal-cards: func [num hand][

   loop num [
       append hand rejoin [trim/all form take deck]
   ] 

]

find-in: func [blk str][

   "Finds a string value in a block. Series in series."
   foreach i blk [if find i str [return i]]

]

go-fish: func [num hand][

   either not empty? deck [
       deal-cards num hand
   ][
       append hand rejoin [trim/all form take pile]    ;-- take from pile if deck is empty
   ]

]

guess-from: func [hand guessed][

   {
       Randomly picks from hand minus guessed.
       Simulates a person asking for different cards on
       their next turn if their previous guess resulted
       in a Go Fish.
   }
   random/seed now/time
   either any [empty? guessed empty? exclude hand guessed][
       random/only hand 
   ][
       random/only exclude hand guessed
   ]

]

make-deck: function [] [

   "make-deck and shuffle from https://rosettacode.org/wiki/Playing_cards#Red"
    new-deck: make block! 52
    foreach p pip [loop 4 [append/only new-deck p]]
    return new-deck

] shuffle: function [deck [block!]] [deck: random deck]

------------- end of helper functions -----------------

transfer-cards: func [

   "Transfers cards from player to player"
   fhand "from hand"
   thand "to hand"
   kind "rank of cards"
   /local 
       c "collected"

][

   c: collect [forall fhand [keep find fhand/1 kind]]
   remove-each i c [none = i]  ;-- remove none values from collected
   forall c [append thand c/1] ;-- append remaining values to "to hand"
   remove-each i fhand [if find/only c i [i]] ;-- remove those values from "from hand"

]

computer-turn: func [

   fhand "from hand"
   thand "to hand"
   kind  "rank of cards"
   /local 
       a 

][

   a: ask rejoin ["Do you have any " kind " s? "]
   if a = "x" [halt]
   either any [a = "y" a = "yes"][
       check-for-books thand kind
       transfer-cards fhand thand kind
       show-cards
       computer-turn fhand thand guess-from thand cguesses
   ][  
       clear-and-show 0.4 gf 
       go-fish 1 thand   
       append cguesses kind 
   ]

]

player-turn: func [

   fhand "from hand"
   thand "to hand"
   kind  "rank of cards"
   /local
       p 

][

   if empty? fhand [go-fish 3 fhand]
   if none? find-in thand kind [   ;-- player has to hold rank asked for
       clear-and-show 1.0 
       "You have to have that rank in your hand to ask for it.^/Computers turn..."
       exit
   ]
   either find-in fhand kind [
       check-for-books thand kind
       transfer-cards fhand thand kind 
       show-cards
       if find-in thand kind [ 
           p: ask "Your guess: "
           either p = "x" [halt][player-turn fhand thand p]
           check-for-books thand p 
       ]
   ][
       clear-and-show 0.4 gf 
       go-fish 1 thand 
   ]

]

check-for-books: func [

   {
       Checks for a book in a players hand.
       Increments the players book score, and
       discards the book from the players hand
   }
   hand "from or to hand"
   kind "rank of cards"
   /local 
       c "collected"

][

   c: collect [
       forall hand [keep find hand/1 kind]
   ]
   remove-each i c [none = i] 
   if 4 = length? c [
       either hand = phand [pbooks: pbooks + 1][cbooks: cbooks + 1]
       remove-each i hand [if find/only c i [i]]   ;-- remove book from hand
       forall c [append pile c/1]  ;-- append discarded book to the pile
   ]

]

show-cards: does [

   clear-and-show 0 ""
   print [newline "Player cards:" newline sort phand newline]
   print ["Computer books:" cbooks]
   print ["Player books:" pbooks newline]

]

game-round: has [c p][

   print {
         -------------------
         -  COMPUTER TURN  -
         -------------------
         }

   if empty? chand [  ; computer has no more cards? fish 3 cards.
       go-fish 3 chand
       show-cards
   ]
   computer-turn phand chand c: guess-from chand cguesses
   check-for-books chand c
   show-cards

   print {
         -------------------
         -   PLAYER TURN   -
         -------------------
         }
   if empty? phand [   ;-- player has no more cards? fish 3 cards.
       go-fish 3 phand
       show-cards
   ]
   p: ask "Your guess: "
   either p = "x" [halt][player-turn chand phand find-in phand p]
   check-for-books phand p 
   show-cards

]

demo: does [

   deck: shuffle make-deck
   deal-cards 9 chand
   deal-cards 9 phand
   show-cards
   while [cbooks + pbooks < 13][
       game-round  
   ]
   clear-and-show 0 ""
   print "GAME OVER" 
   print [newline "Computer books:" cbooks newline "Player books:" pbooks]

]

demo </lang>

Ruby

See Go Fish/Ruby

Tcl

See Go Fish/Tcl

Wren

See Go Fish/Wren