Rock, Paper, Scissors in MATLAB - matlab
Alrighty, it's that time of week again where I am officially throwing my hands up in the air with MATLAB and asking for help. My goal this week is to try and make a function that takes in two inputs, which are strings that say 'Rock, Paper, Scissors' (or whatever the choices are), it then outputs one of three strings 'Player 1 Wins!', 'Player 2 Wins!' or 'Keep Playing!'. To win, the player must beat the other two out of three times (a tie counts as a loss for both players)
function[winner] = RockPaperScissors(player1, player2)
[move1, others] = strtok(player1, ',');
[move2, rest] = strtok(others, ',');
[move3, ~] = strtok(rest, ',');
[go1, others] = strtok(player2, ',');
[go2, rest] = strtok(others, ',');
[go3, ~] = strtok(rest, ',');
Counter1 = 0;
Counter2 = 0;
for i = 1:3
if strcmp(move1, 'Rock') && strcmp(go1, 'Paper')
Counter2 = Counter2 + 1;
elseif strcmp(move1, 'Rock') && strcmp(go1, 'Scissors')
Counter2 = Counter2 + 1;
elseif strcmp(move1, 'Rock') && strcmp(go1, 'Rock')
Counter1 = 0;
elseif strcmp(move1, 'Paper') && strcmp(go1, 'Paper')
Counter1 = 0;
elseif strcmp(move1, 'Paper') && strcmp(go1, 'Rock')
Counter1 = Counter1 + 1;
elseif strcmp(move1, 'Paper') && strcmp(go1, 'Scissors')
Counter2 = Counter2 + 1;
elseif strcmp(move1, 'Scissors') && strcmp(go1, 'Scissors')
Counter1 = 0;
elseif strcmp(move1, 'Scissors') && strcmp(go1, 'Paper')
Counter1 = Counter1 + 1;
elseif strcmp(move1, 'Scissors') && strcmp(go1, 'Rock')
Counter2 = Counter2 + 1;
end
if strcmp(move2, 'Rock') && strcmp(go2, 'Paper')
Counter2 = Counter2 + 1;
elseif strcmp(move2, 'Rock') && strcmp(go2, 'Scissors')
Counter2 = Counter2 + 1;
elseif strcmp(move2, 'Rock') && strcmp(go2, 'Rock')
Counter1 = 0;
elseif strcmp(move2, 'Paper') && strcmp(go2, 'Paper')
Counter1 = 0;
elseif strcmp(move2, 'Paper') && strcmp(go2, 'Rock')
Counter1 = Counter1 + 1;
elseif strcmp(move2, 'Paper') && strcmp(go2, 'Scissors')
Counter2 = Counter2 + 1;
elseif strcmp(move2, 'Scissors') && strcmp(go2, 'Scissors')
Counter1 = 0;
elseif strcmp(move2, 'Scissors') && strcmp(go2, 'Paper')
Counter1 = Counter1 + 1;
elseif strcmp(move2, 'Scissors') && strcmp(go2, 'Rock')
Counter2 = Counter2 + 1;
end
if strcmp(move3, 'Rock') && strcmp(go3, 'Paper')
Counter2 = Counter2 + 1;
elseif strcmp(move3, 'Rock') && strcmp(go3, 'Scissors')
Counter2 = Counter2 + 1;
elseif strcmp(move3, 'Rock') && strcmp(go3, 'Rock')
Counter1 = 0;
elseif strcmp(move3, 'Paper') && strcmp(go3, 'Paper')
Counter1 = 0;
elseif strcmp(move3, 'Paper') && strcmp(go3, 'Rock')
Counter1 = Counter1 + 1;
elseif strcmp(move3, 'Paper') && strcmp(go3, 'Scissors')
Counter2 = Counter2 + 1;
elseif strcmp(move3, 'Scissors') && strcmp(go3, 'Scissors')
Counter1 = 0;
elseif strcmp(move3, 'Scissors') && strcmp(go3, 'Paper')
Counter1 = Counter1 + 1;
elseif strcmp(move3, 'Scissors') && strcmp(go3, 'Rock')
Counter2 = Counter2 + 1;
end
if max(Counter1, Counter2) == Counter2
winner = 'Player 2 Wins!';
elseif max(Counter1, Counter2) == Counter1
winner = 'Player 1 Wins!';
elseif max(Counter1, Counter2) ~= (Counter1 || Counter2) % I tried making a Counter 3, did not work out
winner = 'Keep Playing!';
end
end
As you can see, I have most of this bad boy running. My issue now is that when I run the test case ' [winner1] = rockPaperScissors('Rock,Scissors,Scissors','Paper,Rock,Scissors')
It outputs my answer in a vertical 'ans' and not as winner. Additionally, it gives me 'Player 2 Win!' even though it should be a tie. I tried debugging it all, but can't figure out where my issue is. Bah!
Have you actually thought about using a table? It's perfect for your purpose!
Just an idea, how to do it alternatively. Please don't nail me on the fact, that I haven't considered all your restrictions and conditions, but it should be easy for you to adapt my function how you like it.
function RockPaperScissorsLizardSpock(player1, player2, rounds)
%// creating the table with all combinations
header = {'Rock';'Paper';'Scissors';'Lizard';'Spock'};
Rock = [0;-1;1;1;-1];
Paper = [1;0;-1;-1;1];
Scissors = [-1;1;0;1;-1];
Lizard = [-1;1;-1;0;1];
Spock = [1;-1;1;-1;0];
T = table(Rock,Paper,Scissors,Lizard,Spock,'RowNames',header);
%// play and display winners of every round
points = 0;
for ii = 1:rounds
pointsRound = T{player1(ii), player2(ii)}; %// no need for if-conditions
%// one line is enough
points = points + pointsRound;
if pointsRound > 0; disp(['Player 1 wins round ' num2str(ii) '!'])
elseif pointsRound < 0; disp(['Player 2 wins round ' num2str(ii) '!'])
else disp(['Draw in round ' num2str(ii) '!'])
end
end
%// display overall winner
if points > rounds/2; disp('Player 1 Wins!')
elseif points == 0; disp(['Draw!' num2str(ii) '!'])
else disp('Player 2 Wins!')
end
and now lets play:
player1 = {'Rock','Scissors','Scissors'}
player2 = {'Paper','Rock','Scissors'}
RockPaperScissorsLizardSpock(player1, player2, 3)
returns:
Player 1 wins round 1!
Player 1 wins round 2!
Tie in round 3!
Player 1 Wins!
you can also implement some advanced features, for example give names to the players:
function RockPaperScissorsLizardSpock(player1, player2, rounds)
plname = inputname(1);
p2name = inputname(2);
...
if pointsRound > 0; disp([plname ' wins round ' num2str(ii) '!'])
...
else disp([p2name ' Wins!'])
end
and
Sheldon = {'Spock','Spock','Spock'}
Penny = {'Paper','Rock','Scissors'}
RockPaperScissorsLizardSpock(sheldon, penny, 3)
yields
Sheldon wins round 1!
Penny wins round 2!
Penny wins round 3!
Penny Wins!
If you insist on your string input with commas:
Sheldon = 'Spock,Spock,Spock'
Penny = 'Paper,Rock,Scissors'
you need to add strsplit to the function:
player1= strsplit(player1,',')
player2= strsplit(player2,',')
You need to use the function strcmp instead of the == operator. The inputs are char arrays, which is why == is complaining about the dimensions.
Here's an example for your first if statement:
if strcmp(move1, 'Rock') && strcmp(go1, 'Paper')
winner1 = 'Player 2 Wins!';
Here I've made 2 changes, the first is to use strcmp, and the second to use scalar AND i.e. &&
See help strcmp and help && for more details.
Related
Diagonals in winning conditions in connect four program are not working correctly and I do not know why
My winning conditions for rows and columns works completely fine. However, my diagonals do not. It will say you have won if you get your own number in 4 different rows and not in a direct diagonal as the game is meant to be played. %check if won by columns for column = 1:7 counter = 0; for row = 1:6 if(board(row,column) == players(1,2)) counter = counter + 1; if(counter == 4) fprintf('You win! \n') break end else counter = 0; end end end %check if won by rows for row = 1:6 counter = 0; for column = 1:7 if(board(row, column) == players(1,2)) counter = counter + 1; if(counter == 4) fprintf('You win! \n') break end else counter = 0; end end end %check if won by diagonal \ 1 for column = 1:4 for row = 1:3 counter = 0; if(board(row, column) == players(1)) counter = (row+1), (column+1), (row+2), (column+2), (row+3), (column+3); if(counter == 4) fprintf('You win! \n') break end else counter = 0; end end end %check if won by diagonal / 1 for column = 7:-1:4 for row = 1:3 counter = 0; if(board(row, column) == players(1)) counter = (row+1), (column-1), (row+2), (column-2), (row+3), (column-3); if(counter == 4) fprintf('You win! \n') break end else counter = 0; end end end
While loop keeps going even though creteria has been met
Hello I need this count to stop once my variable 'fourMil' is <= o but the loop keeps going and IDK why. Some help would be appreciated. % Sum of the Fibonacci pair numbers until 4 million clc clear fibo_list = []; for i = (0:31) if (i == 0 || i == 1 || i == 2) fibo_list(end+1) = i + 1; else fibo_list(end+1) = fibo_list(end) + fibo_list(end-1); end end filtered_list = []; fourMil = 4000000; while fourMil > 0 for i = fibo_list if mod(i,2) == 0 filtered_list(end+1) = i; fourMil = fourMil - filtered_list(end); end end end sumation = sum(filtered_list); fprintf('the sum of the Fibo numbers is %i\n', sumation)
You can use a break statement to break the while loop when a condition is met: while fourMil > 0 for i = fibo_list if mod(i,2) == 0 filtered_list(end+1) = i; if (fourMil - filtered_list(end)<0) break; %This will break the loop end fourMil = fourMil - filtered_list(end) end end end
Matlab: "Matrix Exceeds Dimensions Error" in While Loop?
My tutor and I were solving problem simulating the war card game. The only variation in the rules is that two cards with same value are both discarded. My tutor and I came up with a solution deck1 = randi(13,1,26); deck2 = randi(13,1,26); winner1 = 0; winner2 = 0; n = 1; while (length(deck1) ~= 0 || length(deck1) ~= 0) n = length(deck1); m = length(deck2); if deck1(1) == deck2(1) deck1(1) = []; deck2(1) = []; elseif deck1(1) < deck2(1) winner2 = winner2 + 1; deck2(m+1) = deck2(1); deck1(1) = []; deck2(1) = []; else deck1(27) = deck1(1); deck1(n+1) = deck2(1); deck1(1) = []; deck2(1) = []; winner1 = winner1 + 1; end end if winner1 > winner2 k = 1; elseif winner1 == winner2 k = 0; else k = 2; end disp(k) The loop works for k=2 and k=0 but not for k=1. It return the following Index exceeds matrix dimensions. Error in TutorVersionWarCardGame (line 16) if deck1(1) == deck2(1) How should I edit the loop?
You compare deck1 2 times in the while loop as below while (length(deck1) ~= 0 || length(deck1) ~= 0) I think it should be while (length(deck1) ~= 0 || length(deck2) ~= 0) Edit: I added try catch to check the if conditions inside the while loop. I found matrix keep decrease until its size reaches to 0, therefore, I replace the || with && while (length(deck1) ~= 0 && length(deck2) ~= 0) but the result now always k=2.
This works for me: deck1 = randi(13,1,26); deck2 = randi(13,1,26); winner1 = 0; winner2 = 0; n = 1; while (~isempty(deck1) && ~isempty(deck2)) n = length(deck1); m = length(deck2); if deck1(1) == deck2(1) deck1(1) = []; deck2(1) = []; elseif deck1(1) < deck2(1) winner2 = winner2 + 1; deck2(m+1) = deck2(1); deck1(1) = []; deck2(1) = []; else deck1(27) = deck1(1); deck1(n+1) = deck2(1); deck1(1) = []; deck2(1) = []; winner1 = winner1 + 1; end end if winner1 > winner2 k = 1; elseif winner1 == winner2 k = 0; else k = 2; end disp(k);
Simple MATLAB lexer program
I created a simple lexer program from MATLAB code where, when the user types a string, the lexemes in that string are categorized. However, when I enter a string in the command window the identifiers are not getting displayed. The code is as follows : function determineLexemes() j = 0; prompt = 'Enter string : '; str = input(prompt); arr = char(str); strTwo = ''; display('Symbol Table'); fprintf('Lexeme \t\t Token \n'); k = length(arr); for i = 1: k if(arr(i) == '+') fprintf('+ \t\t ADD_OP \n'); end if(arr(i) == '-') fprintf('- \t\t SUB_OP \n'); end if(arr(i) == '*') fprintf('* \t\t MULT_OP \n'); end if(arr(i) == '/') fprintf('/ \t\t DIV_OP \n'); end if(arr(i) == '(') fprintf('( \t\t LEFT_PAREN \n'); end if(arr(i) == ')') fprintf(') \t\t RIGHT_PAREN \n'); end if(arr(i) == '=') fprintf('= \t\t EQUAL_OP \n'); end x = str2num(arr(i)); y = isletter(arr(i)); if(y || (isempty(x) ==0)) strTwo = strcat(strTwo,arr(i)); end if(~ischar(arr(i)) && ~isnumeric(arr(i))) if(~isspace(arr(i)) && ~isempty(strTwo)) m(j) = strTwo; if(isNumeric(strTwo(1)) && regexp('.*[a-zA-]+.*')) disp(strcat('Error. Potential variable (', strTwo, ') whose name starts with digit found')); strTwo = ''; j = j + 1; end if(~(isNumeric(strTwo(1) && regexp('.*[a-zA-]+.*')))) disp(strcat(m(j), ('\t\t IDENTIFIER'))); strTwo = ''; j = j + 1; end end end end end And the intended output, when '(2a + b)' is entered to the user prompt,is as follows: However, the output currently does not identify identifiers (i.e. 2a and b in this example). Any help on this problem is appreciated.
I tried to keep the changes needed by your code to a minimum, but there were quite a number of mistakes (even things like isNumeric instead of isnumeric or a missing argument for the regex function). Hope you'll be satisfied with this. function determineLexemes() j = 1; prompt = 'Enter string : '; str = input(prompt); arr = char(str); strTwo = ''; display('Symbol Table'); fprintf('Lexeme \t\t Token \n'); k = length(arr); for i = 1: k if(arr(i) == '+') fprintf('+ \t\t ADD_OP \n'); end if(arr(i) == '-') fprintf('- \t\t SUB_OP \n'); end if(arr(i) == '*') fprintf('* \t\t MULT_OP \n'); end if(arr(i) == '/') fprintf('/ \t\t DIV_OP \n'); end if(arr(i) == '(') fprintf('( \t\t LEFT_PAREN \n'); end if(arr(i) == ')') fprintf(') \t\t RIGHT_PAREN \n'); end if(arr(i) == '=') fprintf('= \t\t EQUAL_OP \n'); end x = str2num(arr(i)); y = isletter(arr(i)); if(y || ~isempty(x)) strTwo = strcat(strTwo,arr(i)); end if(~isspace(arr(i)) && ~isempty(strTwo)) if(~isempty(str2num(strTwo(1))) && any(regexp(strTwo,'.*[a-zA-]+.*'))) fprintf(strcat('Error. Potential variable (', strTwo, ') whose name starts with digit found \n')); strTwo = ''; j = j + 1; else if isempty(str2num(strTwo(1))) fprintf(strcat(strTwo, ('\t\t IDENTIFIER \n'))); strTwo = ''; j = j + 1; end end end end end
Matlab coder "Error indenting generated C code"
I am Trying to convert a MATLAB code to C++ using MATLAB coder but this error apears: Error indenting generated C code The error points to the name of the function itself and has no more explanations in it. can someone tell me what is this error? here is the function i want to conver: function [Report_Clustered,ClusterCounter_new]=InitClusterGenerator_test(Report_In,~,FreqEpsilon,DegreeEpsilon,~,ClusterCounter_old, BlockCount, Report_old) Report_M = zeros(size(Report_In,1),size(Report_In,2),4); for i=1:size(Report_In,1) for j=1:size(Report_In,2) Report_M(i,j,1)=Report_In(i,j,1); Report_M(i,j,2)=Report_In(i,j,2); Report_M(i,j,3)=0; % Cluster number that the point belongs to. Report_M(i,j,4)=0; Report_In{i,j} end end ClusterCounter = 0; for i=1:size(Report_M,1) for j=1:size(Report_M,2) if (Report_M(i,j,3) == 0) ClusterCounter = ClusterCounter + 1; Report_M(i,j,3) = ClusterCounter; for ii=1:size(Report_M,1) for jj=1:size(Report_M,2) if (Report_M(ii,jj,3) == 0) if (abs(Report_M(i,j,1)-Report_M(ii,jj,1))<FreqEpsilon &&... (abs(Report_M(i,j,2)-Report_M(ii,jj,2)) <DegreeEpsilon ||... abs(-360 + Report_M(i,j,2)-Report_M(ii,jj,2)) <DegreeEpsilon ||... abs(360 + Report_M(i,j,2)-Report_M(ii,jj,2)) <DegreeEpsilon)) Report_M(ii,jj,3) = ClusterCounter; end end end end end end end if (BlockCount> 20 && ClusterCounter<4) warning = 1; end ClusterCounter_new = ClusterCounter; %clear Report_new; flag = 0; Report_new = zeros(ClusterCounter,size (Report_M, 2),4); index = zeros(1, ClusterCounter_new); for i = 1: size (Report_M, 1) for j = 1: size (Report_M, 2) for k = 1: ClusterCounter_new if (Report_M(i,j,3) == k) index(1,k) = index(1,k) + 1; Report_new(k,index(1,k), 1:3) = Report_M(i,j,1:3); flag = flag + 1; end end end end for j = 1: size (Report_new, 2) for i = 1: size (Report_new, 1) if (Report_new(i,j,1) == 0) Report_new(i,j,1:3) = Report_new(i,1,1:3); end end end %Report_new = Report; MedoidF_old = zeros(1, size(Report_old,1)); MedoidA_old = zeros(1, size(Report_old,1)); for i=1:size(Report_old,1) SumF = 0; SumA = 0; MinAngle = 361; MaxAngle = -1; for j=1:size(Report_old,2) SumF = SumF + Report_old(i,j,1); SumA = SumA + Report_old(i,j,2); if Report_old(i,j,2) > MaxAngle MaxAngle = Report_old(i,j,2); elseif Report_old(i,j,2) < MinAngle MinAngle = Report_old(i,j,2); end end MedoidF_old(1, i) = SumF/size(Report_old,2); if (MaxAngle - MinAngle) > 350 MedoidA_old(1, i) = 0; else MedoidA_old(1, i) = SumA/size(Report_old,2); end end MedoidF_new = zeros(1, size(Report_new,1)); MedoidA_new = zeros(1, size(Report_new,1)); for i=1:size(Report_new,1) SumF = 0; SumA = 0; MinAngle = 361; MaxAngle = -1; for j=1:size(Report_new,2) SumF = SumF + Report_new(i,j,1); SumA = SumA + Report_new(i,j,2); if Report_new(i,j,2) > MaxAngle MaxAngle = Report_new(i,j,2); elseif Report_new(i,j,2) < MinAngle MinAngle = Report_new(i,j,2); end end MedoidF_new(1, i) = SumF/size(Report_new,2); if (MaxAngle - MinAngle) > 350 MedoidA_new(1, i) = 0; else MedoidA_new(1, i) = SumA/size(Report_new,2); end end TempCluster = zeros(1, size(Report_new, 1)); CurrentCluster = ClusterCounter_old; for i = 1: 1: size(Report_new,1) for j = 1: 1: size(Report_old,1) if (abs(MedoidF_old(1,j)-MedoidF_new(1,i))<FreqEpsilon &&... (abs(MedoidA_old(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||... abs(360 + MedoidA_old(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||... abs(-360 + MedoidA_old(1,j)-MedoidA_new(1,i))<DegreeEpsilon)) %%if the new cluster is the rest of an old cluster use the old one's index for it TempCluster(1,i) = Report_old(j,1,3); end end %%this part is for seperating the clusters which where in the collision state in the past time if (TempCluster(1,i)>0) %%if the new cluster is one of the old ones the index should be set for j = 1:1:size(Report_new, 2) Report_new(i,j,3) = TempCluster(1,i); Report_new(i,j,4) = 1;% Alive end else %%first search if the new cluster is a part of a newly found cluster found before this one for j = 1: 1: i-1 if (abs(MedoidF_new(1,j)-MedoidF_new(1,i))<FreqEpsilon &&... (abs(MedoidA_new(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||... abs(360 + MedoidA_new(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||... abs(-360 + MedoidA_new(1,j)-MedoidA_new(1,i))<DegreeEpsilon)) %%if the new cluster is the rest of an old cluster use the old one's index for it TempCluster(1,i) = Report_new(j,1,3); end end end if (TempCluster(1,i)>0) %%if the new cluster is one of the old ones the index should be set for j = 1:1:size(Report_new, 2) Report_new(i,j,3) = TempCluster(1,i); Report_new(i,j,4) = 1;% Alive end else %%new cluster is just began so it needs a new index CurrentCluster = CurrentCluster + 1; ClusterCounter_new = CurrentCluster; TempCluster(1,i) = CurrentCluster; for j = 1:1:size(Report_new, 2) Report_new(i,j,3) = TempCluster(1,i); Report_new(i,j,4) = 1; % Alive end end end NewClusters = zeros(1, size (Report_new, 1)); for i = 1: size(Report_new, 1) NewClusters (1,i) = Report_new(i,1,3); end OldClusters = zeros(1, size (Report_old, 1)); OldClustersLine = zeros(1, size (Report_old, 1)); for i = 1: size(Report_old, 1) OldClusters (1,i) = Report_old(i,1,3); OldClustersLine (1, i) = i; end NumberOfDead = 0; %clear AddDead; AddDead = zeros (16,size(Report_new, 2),4); if (BlockCount>10) for i = 1: size (OldClusters, 2) IsDead = 1; for j = 1: size (NewClusters, 2) if OldClusters(1, i) == NewClusters(1,j) IsDead = 0; end end if (IsDead == 1) NumberOfDead = NumberOfDead + 1; %clear TempLine; TempLine = zeros(1, size(Report_old,2), 4); TempLine(1,:,1:3) = Report_old(OldClustersLine(1, i),:,1:3); for k= 1: size(TempLine, 2) TempLine(1,k,4) = 0; % Dead end TempSize = size(TempLine, 2); Thresh = size(Report_new, 2); if (TempSize >= Thresh) AddDead (NumberOfDead, 1:Thresh, 1:4) = TempLine(1,1:Thresh, 1:4); else for l = 1: Thresh-TempSize TempLine(1, TempSize+l, 1:4) = TempLine(1, TempSize, 1:4); end AddDead (NumberOfDead, 1:Thresh, 1:4) = TempLine(1,1:Thresh, 1:4); end end end xR = size (Report_new,1); if (NumberOfDead == 0) Report_Clustered = zeros (size(Report_new,1),size(Report_new,2),size(Report_new,3)); else Report_Clustered = zeros (size(Report_new,1) + NumberOfDead,size(Report_new,2),size(Report_new,3)); end Report_Clustered (1:size(Report_new,1), :, :) = Report_new(:,:,:); for i = 1: NumberOfDead Report_Clustered(xR + i, :) = AddDead(i, :); end end and I'm using matlab 2012a Tnx.
From what you've said in the comments, it appears that you simply need to call clear functions from the command line before recompiling the function to allow Matlab to overwrite the files. See this Matlab forum or the documentation for clear for more detail.