I have implemented the Rosetta Code Rock Paper Scissors game in Red, but I'm sure that there are better ways to do every thing that I did. I would appreciate any feedback on this code, which does work according to spec:
Implement the classic children's game Rock-Paper-Scissors, as well as a simple predictive AI (artificial intelligence) player.
Rock Paper Scissors is a two player game.
Each player chooses one of rock, paper or scissors, without knowing the other player's choice.
The winner is decided by a set of rules:
- Rock beats scissors
- Scissors beat paper
- Paper beats rock
If both players choose the same thing, there is no winner for that round.
For this task, the computer will be one of the players.
The operator will select Rock, Paper or Scissors and the computer will keep a record of the choice frequency, and use that information to make a weighted random choice in an attempt to defeat its opponent.
Red [ Problem: %http://www.rosettacode.org/wiki/Rock-paper-scissors Code: %https://github.com/metaperl/red-rosetta/blob/master/rock-paper-scissors.red ] help1: %https://stackoverflow.com/questions/54272942/how-to-find-the-first-element-of-a-block-of-strings-whose-first-character-matche help2: %https://stackoverflow.com/questions/54272956/how-to-increment-element-of-block-after-found-element help3: %https://stackoverflow.com/questions/54273057/two-dimensional-dispatch-table-with-templated-response help4: %https://stackoverflow.com/questions/54273161/in-red-how-do-i-search-through-a-block-for-a-string-matching-a-pattern/54275072#54275072 games-played: 0 weapons: ["rock" "scissors" "paper"] matching-weapon: func [abbrev][ foreach weapon weapons [ if (first weapon) = first abbrev [ return weapon ] ] ] player-choices: ["rock" 0 "scissors" 0 "paper" 0 ] player-choice-tally: func [choice][player-choices/(choice): player-choices/(choice) + 1] player-choice: "x" valid-choice: func [c][find "rpsq" c] player-wins: [ ["rock" "scissors"] "breaks" ["paper" "rock"] "covers" ["scissors" "paper"] "cut" ] player-wins?: function [player1 player2] [ game: reduce [player1 player2] winning: player-wins/(game) ] report-win: func [player1 player2][rejoin [player1 " " (player-wins? player1 player2) " " player2]] draw: func [player computer][player = computer] update-stats: func [player-choice][ player-choice-tally player-choice games-played: games-played + 1 ] make-computer-choice: func [ either games-played >= 3 [ tmp: random games-played tally: select "rock" player-choices either tmp <= tally [return "rock"][ tally: tally + select "scissors" player-choices either tmp <= tally [return "scissors"][ return "paper" ] ] ][random/only weapons] ] while [not player-choice = "q"][ player-choice: ask "(r)ock, (s)cissors, (p)aper or (q)uit? " either (player-choice = "q") [ if (valid-choice player-choice) [ computer-choice: random/only weapons player-choice: matching-weapon player-choice update-stats player-choice print rejoin ["Player choice: " player-choice "tally" player-choices "Computer choice:" computer-choice] either draw player-choice computer-choice [print "Draw"][ tmp: player-wins? player-choice computer-choice print either tmp [rejoin ["Player wins: " report-win player-choice computer-choice]] [rejoin ["Computer wins: " report-win computer-choice player-choice]] ] ] ] ]