A small sketch for playing rock paper scissors
with an "AI" (actually just a Markov model). It will try to beat you based on patterns in your gameplay.
Choose either rock, paper or scissor by clicking at their respective images and try to win against the AI.
“Rock Paper Scissors with AI” by RedstoneTim
https://openprocessing.org/sketch/923067
License CreativeCommons Attribution ShareAlike
https://creativecommons.org/licenses/by-sa/3.0
{{filePath}}
{{width}} x {{height}}
Report Sketch
Oh, that naughty sketch! Please let us know what the issue is below.
Apply Template
Applying this template will reset your sketch and remove all your changes. Are you sure you would like to continue?
Report Sketch
Report Comment
Please confirm that you would like to report the comment below.
We will review your submission and take any actions necessary per our Community Guidelines. In addition to reporting this comment, you can also block the user to prevent any future interactions.
Please report comments only when necessary. Unnecessary or abusive use of this tool may result in your own account being suspended.
Are you sure you want to delete your sketch?
Any files uploaded will be deleted as well.
Delete Comment?
This will also delete all the replies to this comment.
Delete this tab? Any code in it will be deleted as well.
Select a collection to submit your sketch
We Need Your Support
Since 2008, OpenProcessing has provided tools for creative coders to learn, create, and share over a million open source projects in a friendly environment.
Niche websites like ours need your continued support for future development and maintenance, while keeping it an ad-free platform that respects your data and privacy!
Please consider subscribing below to show your support with a "Plus" badge on your profile and get access to many other features!
Choose either rock, paper or scissor by clicking at their respective images and try to win against the AI.
CC Attribution ShareAlike
Rock Paper Scissors with AI
xxxxxxxxxx
// 1: rock 2: paper 3: scissors
int order = 2; // how intelligent the "AI" is supposed to be, the higher the number the longer the "AI" takes to learn
TurnList turnList;
int playerWins = 0;
int aiWins = 0;
float textHeight;
PImage rockImg;
PImage paperImg;
PImage scissorsImg;
int imageDisplayHeight;
int imageSize;
TurnData[] data;
byte status = 0; // 0: nothing 1: win 2: lose 3: tie
void setup() {
fullscreen();
size(1000, 900);
textHeight = 0.07 * height;
textFont(createFont("monospace", 0.018 * height, true), textHeight);
rockImg = loadImage("https://upload.wikimedia.org/wikipedia/commons/7/7e/Rock-paper-scissors_%28rock%29.png");
paperImg = loadImage("https://upload.wikimedia.org/wikipedia/commons/a/af/Rock-paper-scissors_%28paper%29.png");
scissorsImg = loadImage("https://upload.wikimedia.org/wikipedia/commons/5/5f/Rock-paper-scissors_%28scissors%29.png");
image(rockImg, 0, imageDisplayHeight, imageSize, imageSize);
image(paperImg, imageSize, imageDisplayHeight, imageSize, imageSize);
image(scissorsImg, imageSize * 2, imageDisplayHeight, imageSize, imageSize);
imageSize = width / 3;
imageDisplayHeight = 0.55 * height;
turnList = new TurnList();
data = new TurnData[3334];
}
void draw() {
background(255);
image(rockImg, 0, imageDisplayHeight, imageSize, imageSize);
image(paperImg, imageSize, imageDisplayHeight, imageSize, imageSize);
image(scissorsImg, imageSize * 2, imageDisplayHeight, imageSize, imageSize);
fill(0);
text("Score: " + playerWins + " - " + aiWins + "\nYour last turn: " + getTurnName(turnList.getLastPlayerTurn()) + "\nAI's last turn: " + getTurnName(turnList.getLastAiTurn()), 10, 100);
fill((status == 2) ? 255 : 0, (status == 1) ? 255 : 0, (status == 3) ? 255 : 0);
String statusMessage = ((status == 1) ? "Win" : ((status == 2) ? "Lose" : ((status == 3) ? "Tie" : "")));
text(statusMessage, (this.width - textWidth(statusMessage)) / 2, 100 + (textHeight + 10) * 3.5);
}
// perform turns
void keyReleased() {
if(key=='R' || key=='r') {
performPlayerTurn(1);
} else if(key=='P' || key=='p') {
performPlayerTurn(2);
} else if(key=='S' || key=='s') {
performPlayerTurn(3);
} else if(key=='X' || key=='x') {
// perform a random turn
performPlayerTurn(int(random(3) + 1));
}
}
void mouseReleased() {
if(mouseY >= imageDisplayHeight && mouseY <= imageDisplayHeight + imageSize) {
performPlayerTurn(int(mouseX / width * 3) + 1);
}
}
void performPlayerTurn(byte turn) {
byte lastPlayerTurn = turn;
byte lastAiTurn = getAiTurn();
turnList.addTurns(lastPlayerTurn, lastAiTurn);
status = 3;
if(lastPlayerTurn != lastAiTurn) {
if((lastPlayerTurn == 1 && lastAiTurn == 3) || (lastPlayerTurn == 2 && lastAiTurn == 1) || (lastPlayerTurn == 3 && lastAiTurn == 2)) {
playerWins++;
status = 1;
} else if((lastAiTurn == 1 && lastPlayerTurn == 3) || (lastAiTurn == 2 && lastPlayerTurn == 1) || (lastAiTurn == 3 && lastPlayerTurn == 2)) {
aiWins++;
status = 2;
}
}
}
byte getAiTurn() {
if(!turnList.hasEnoughData()) { // search through whole array for 0s?
float randomNumber = random(0, 3);
return (randomNumber < 1) ? 1 : ((randomNumber < 2) ? 2 : 3);
}
int index = getIndexFromTurns();
TurnData turnData = data[index];
if(turnData == null) {
turnData = new TurnData();
data[index] = turnData;
}
return getOpposite(data[getIndexFromTurns()].predictNextPlayerTurn());
}
String getTurnName(byte turn) {
switch(turn) {
case 1:
return "Rock";
case 2:
return "Paper";
case 3:
return "Scissors";
default:
return "None";
}
}
// TODO: Better encoding
int getIndexFromTurns() {
int index = 0;
for(byte turn : turnList.getLastTurns()) {
index = index * 10 + turn;
}
return index;
}
byte getOpposite(byte turn) {
return turn == 1 ? 2 : (turn == 2 ? 3 : (turn == 3 ? 1 : 0));
}
class TurnList {
byte[] turns;
int tail = -1;
TurnList() {
turns = new byte[order * 2];
}
byte getLastAiTurn() {
return turns[tail];
}
byte getLastPlayerTurn() {
return turns[tail > 0 ? tail - 1 : 0];
}
private void addTurn(byte newTurn) {
tail++;
if(tail >= turns.length) {
tail = 0;
}
turns[tail] = newTurn;
}
void addTurns(byte playerTurn, byte aiTurn) {
if(hasEnoughData()) {
int index = getIndexFromTurns();
TurnData turnData = data[index];
if(turnData == null) {
turnData = new TurnData();
data[index] = turnData;
}
turnData.addPlayerTurn(playerTurn);
}
addTurn(playerTurn);
addTurn(aiTurn);
}
byte[] getLastTurns() {
byte[] lastTurns = new byte[turns.length];
for(int i = 0; i < lastTurns.length; i++) {
int turnsIndex = tail + i + 1;
if(turnsIndex >= turns.length) {
turnsIndex = turnsIndex - turns.length;
}
lastTurns[i] = turns[turnsIndex];
}
return lastTurns;
}
boolean hasEnoughData() {
return turns[turns.length - 1] != 0; // search through whole array for 0s?
}
}
class TurnData {
int[] gameData = new int[3];
TurnData() {
for(int i = 0; i < gameData.length; i++) {
gameData[i] = 1;
}
}
void addPlayerTurn(byte turn) {
gameData[turn - 1]++;
}
byte predictNextPlayerTurn() {
int all = gameData[0] + gameData[1] + gameData[2];
float randomNumber = random(0, all);
if(randomNumber < gameData[0]) {
return 1;
} else if (randomNumber < (gameData[0] + gameData[1])) {
return 2;
} else {
return 3;
}
}
}
See More Shortcuts