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.