2015-12-06 12 views
9

Ho creato una funzione RPS che randomizza la mossa del computer per un turno. Ad esempio, se si digita in rps ("rock"), la funzione sputerà a caso sia roccia, carta, forbici insieme al risultato (vittoria, perdita, pareggio).Provare a randomizzare un gioco di roccia, carta, forbici in R

rps = function(move){ 
    options = c("rock", "paper", "scissors") 
    comp.move = sample(options, size = 1) 
    if(move == "rock" & comp.move == "rock"){ 
    names(comp.move) = "tie" 
}else 
if(move == "rock" & comp.move == "scissors"){ 
    names(comp.move) = "loss" 
}else 
if(move == "rock" & comp.move == "paper"){ 
    names(comp.move) = "win" 
}else 
if(move == "paper" & comp.move == "paper"){ 
    names(comp.move) = "tie" 
}else 
if(move == "paper" & comp.move == "scissors"){ 
    names(comp.move) = "win" 
}else 
if(move == "paper" & comp.move == "rock"){ 
    names(comp.move) = "loss" 
}else 
if(move == "scissors" & comp.move == "scissors"){ 
    names(comp.move) = "tie" 
}else 
if(move == "scissors" & comp.move == "rock"){ 
    names(comp.move) = "win" 
}else 
if(move == "scissors" & comp.move == "paper"){ 
    names(comp.move) = "loss" 
} 
    return(comp.move) 
} 

Ora, voglio giocare una versione del gioco in cui ciò accade 50 volte. Ho già creato un vettore di lunghezza 50 che ha le mosse umane preregistrate.

human.move = c("rock", "paper", "scissors", "paper", "paper", "rock", "scissors", "rock", "rock", "paper", "paper", "scissors", "rock", "rock", "paper", "paper", "paper", "scissors", "paper", "rock", "paper", "rock", "rock", "scissors", "scissors", "paper", "rock", "paper", "scissors", "rock", "paper", "paper", "scissors", "rock", "paper", "rock", "paper", "paper", "scissors", "scissors", "paper", "rock", "rock", "scissors", "scissors", "rock", "paper", "scissors", "scissors", "rock") 

Come faccio ad avere il computer per eseguire la funzione rps su ogni elemento in questo vettore, e mi danno i risultati? Attualmente la mia funzione prende solo il primo elemento del mio vettore di mosse umane (che è rock) e confronta solo le sue mosse casuali con quelle.

rps.random=function(move,n=50){ 
comp.moves = vector("character") 

for(i in human.move){ 
comp.move=rps(move[i]) 
comp.moves = append(comp.moves,comp.move, after = length(comp.moves)) 
} 
return(comp.moves) 
} 
+0

Molte delle risposte sotto sono grandi, e coinvolgere riscrivere gran parte del codice del PO originale. La domanda, tuttavia, era "Come faccio ad avere il computer per eseguire la funzione rps su ogni elemento in questo vettore, e darmi i risultati?" –

+1

@GaryWeissman: è vero, ma a volte può essere meglio offrire miglioramenti agli attuali metodi dell'OP. –

+0

@RichardScriven anche questo è vero. –

risposta

8

Qui ci sono un paio di suggerimenti. Innanzitutto, un aggiornamento della tua funzione. È possibile ridurre tutte le affermazioni if() utilizzando alcune "o" istruzioni con l'operatore | per la vittoria o la perdita e la funzione identical() per un pareggio. Inoltre, è a mia conoscenza che i giochi randomizzati come questo dovrebbero essere giocati un singolo round alla volta e replicati per più di un round. Pertanto, questa funzione controlla un vettore a lunghezza singola dato in move.

rps <- function (move) { 
    opts <- c("rock", "paper", "scissors") 
    stopifnot(length(move) == 1L, move %in% opts) 
    cpu <- sample(opts, 1) 
    names(cpu) <- if (identical(move, cpu)) { 
     "tie" 
    } 
    else if (move == "rock" & cpu == "scissors" | move == "paper" & 
     cpu == "rock" | move == "scissors" & cpu == "paper") { 
     "win" 
    } 
    else { 
     "loss" 
    } 
    cpu 
} 

Qui ci sono un paio di esempio viene eseguito -

rps("paper") 
# win 
# "rock" 
rps("rock") 
# loss 
# "paper" 

Ora non c'è bisogno di creare manualmente un vettore di 50 elementi. Possiamo solo replicare il processo 50 volte utilizzando un campione nell'argomento move.

replicate(50, rps(sample(c("rock", "paper", "scissors"), 1))) 
#  win  win  loss  win  loss  tie  tie 
# "scissors" "paper" "paper" "paper"  "rock" "paper" "scissors" 
#  win  loss  loss  tie  loss  win  win 
#  "rock" "paper" "paper" "paper" "paper" "scissors" "scissors" 
#  tie  loss  tie  win  win  tie  loss 
# "scissors"  "rock" "scissors" "paper" "paper" "scissors"  "rock" 
#  tie  tie  loss  tie  win  win  win 
#  "rock" "scissors" "scissors" "scissors"  "rock" "scissors" "scissors" 
#  win  win  loss  win  tie  tie  win 
# "scissors" "scissors" "paper" "paper" "paper" "paper" "paper" 
#  win  tie  win  tie  tie  win  win 
# "paper"  "rock"  "rock" "paper" "scissors" "paper" "scissors" 
#  loss  tie  tie  loss  tie  win  win 
#  "rock"  "rock" "paper" "scissors" "scissors"  "rock"  "rock" 
#  win 
# "paper" 

Naturalmente, se si ha avuto un vettore di ingresso possiamo eseguirlo tramite sapply() per vedere gli stessi risultati di cui sopra (con o senza il vettore di ingresso nei nomi).

sapply(c("rock", "paper", "scissors"), rps) 
# rock.loss paper.win scissors.tie 
#  "paper"  "rock" "scissors" 
sapply(c("rock", "paper", "scissors"), rps, USE.NAMES = FALSE) 
#  tie  loss  win 
# "rock" "scissors" "paper" 

Aggiornamento: E 'appena venuto in mente che si avrà idea di cosa l'input è stato nei casi di cui sopra, che abbiamo ottenuto dalla replicate(), ecco una correzione. Se cambiamo l'ultima riga se la funzione è una matrice (o una lista), possiamo anche includere l'input. Possiamo usare qualcosa di simile per l'ultima riga =

matrix(c(move, cpu), 1, dimnames = list(wlt, c("move", "cpu"))) 

Poi ci sarebbe il seguente per i risultati -

rps("paper") 
#  move cpu  
# loss "paper" "scissors" 
rps("paper") 
#  move cpu  
# tie "paper" "paper" 

Ora sappiamo quello che abbiamo messo in come input senza fare alcun lavoro supplementare. E possiamo anche riunire le repliche in una matrice con il nostro vecchio amico do.call(rbind, ...).

2

È possibile utilizzare la famiglia di funzioni apply. Nel tuo caso, prova:

lapply(human.move, rps) 
6

Come suggerito Gary, per qualsiasi funzione che funziona su 'una cosa', è possibile utilizzare lapply o sapply per farlo funzionare per molte cose.

Ma direi che non è proprio necessario qui perché quello che c'è dentro rps gestisce già la situazione quando move è più lungo di 1. Si sarebbe solo bisogno di cambiare sample(options, size = 1)-sample(options, size = length(move), replace = TRUE).

Google 'campionamento con sostituzione' se non si è sicuri della parte replace = TRUE.

Penso che ci sia anche un modo più semplice per capire se è stata una vittoria, una perdita o un pareggio.

rps = function(move){ 

    # possible selections 
    options = c("rock", "paper", "scissors") 

    # the sample function is already vectorised, so it will work when 
    # move is longer than one 
    comp.move = sample(options, size = length(move), replace = TRUE) 

    #create a result vector that defaults to 'loss' 
    results <- rep('loss', length(move)) 

    # update the rest of the results (these are vectorised too) 
    results[move == comp.move]        <- 'tie' 
    results[move == 'rock'  & comp.move == 'scissors'] <- 'win' 
    results[move == 'paper'  & comp.move == 'rock']  <- 'win' 
    results[move == 'scissors' & comp.move == 'paper'] <- 'win' 

    # set the names 
    names(comp.move) <- results 

    # return the vector 
    comp.move 
} 

Quindi è possibile utilizzarlo in questo modo

> rps(human.move) 
     loss  win  win  loss  loss  win  loss  tie  loss  loss  loss  loss  win  win 
    "paper"  "rock" "paper" "scissors" "scissors" "scissors"  "rock"  "rock" "paper" "scissors" "scissors"  "rock" "scissors" "scissors" 
     loss  loss  loss  loss  tie  tie  loss  tie  tie  loss  tie  win  tie  tie 
"scissors" "scissors" "scissors"  "rock" "paper"  "rock" "scissors"  "rock"  "rock"  "rock" "scissors"  "rock"  "rock" "paper" 
     tie  win  loss  loss  win  loss  loss  win  loss  tie  tie  tie  win  loss 
"scissors" "scissors" "scissors" "scissors" "paper" "paper" "scissors" "scissors" "scissors" "paper" "scissors" "scissors"  "rock" "paper" 
     tie  win  tie  tie  loss  tie  tie  tie 
    "rock" "paper" "scissors"  "rock" "scissors" "scissors" "scissors"  "rock" 
5

Kek

rps <- function(player) { 
    p <- c('rock','paper','scissors') 
    player <- if (missing(player)) 
    sample(p, 1) else match.arg(player, p, FALSE) 
    computer <- sample(p, 1) 
    message(sprintf('Computer picks %s', computer)) 
    message(sprintf('You chose %s', player)) 
    plays <- cbind(expand.grid(p = p, c = p), 
       result = I(c('tie','win','loss','loss','tie','win','win','loss','tie'))) 

    res <- plays[plays$p %in% player & plays$c %in% computer, 'result'] 
    if (res == 'tie') 
    return(res) 

    for (ii in 1:10) { 
    par(mar = c(0,0,0,0), bg = sample(colors(), 1)) 
    plot(1:10, ann = FALSE, axes = FALSE, type = 'n') 
    text(runif(1, 1, 10), runif(1, 1, 10), toupper(res), srt = sample(0:360, 1), 
     font = 3, cex = 4, col = sample(colors(), 1)) 
    Sys.sleep(.1) 
    } 
    graphics.off() 
    res 
} 

rps() 
Problemi correlati