Creating a Tic-Tac-Toe Game in Matlab - matlab

I'm very new to Matlab and am creating a simple Tic Tac Toe game where a user plays against the computer. I have 3x3 push buttons in a GUI and for each button's callback I have set it up so that an 'X' will appear if the square is empty, and set a '1' value into a 3x3 zeros matrix in the corresponding spot.
I want to put a 'player2' function after this in each callback so that the computer will find any spot in the matrix that is a zero, randomly pick one and give me the coordinates which I will then translate over to its corresponding push button to place an 'O' there.
The matrix is handles.move=zeros(3,3).
I know I'll probably need to use an 'if' statement, and '[i,j] = find(move==0);' but I don't know what random command to use with this to pick from the zeros that will give me back the coordinates. Any suggestions?

Calling find(move==0) will return linear indices of elements in move which are equal to zero. For example:
move =
1 0 1
0 0 0
0 1 0
>>indices = find(move==0)
indices =
2
3
4
5
8
9
You can take this result and scramble the indices randomly using...
>>scrambled = indices(randperm(length(indices)))
scrambled =
9
2
8
4
3
5
Then choose the first element, scrambled(1), as the computer's next choice. There are probably several ways to go about this. The nice thing about this one is that it can be called until the very end of the game to retrieve the computer's next move.
EDIT:
computerMove = indices(randperm(length(indices),1));
This will return the first element automatically as Dennis pointed out.

Apparently it's a very popular game - have a look here, here, here, here, here, here, here, here, here, here, here.

Related

Matlab- finding the smallest deviation in a struct

I have a struct like this mesh.m_1_0.Deformation_Entformung;
the second field is a struct from m_1_0 till m_3_5 in 6 steps;
the Deformation_Entformung is a matrix with 6 columns and 325562 rows, whereby the first 3 columns contain coordinates (x,y,z).
Now I'm interested in the coordinates that are the closest to (33.5 -88.7801,-0.4480).
This is my code:
SNames = fieldnames(mesh); % SName = m_1_0,m_1_5...m_3_5
for loopIndex = 1:numel(SNames)
stuff = mesh.(SNames{loopIndex}).Deformation_Entformung;
mesh.(SNames{loopIndex}).('Deformation_Entformung_Koordi')=...
stuff(min(stuff(:,1)-33.5) & min(stuff(:,2)--88.7801) & ...
min(stuff(:,3)-0.4480), :);
end
The code runs, but the problem is that the answer is always the first row of the matrix Deformation_Entformung.
I would be glad, if someone could give me a hint.
Well, first of all you mix up indices with values.
min(stuff) returns the minimal value of stuff. So when you write stuff(min(stuff)) that's certainly not doing what you want it to do.
Secondly, if min(stuff(:,1)-33.5) would actually return an index (which it doesn't), then the index would be the same whether you searched for min(stuff(:,1)+100) or min(stuff(:,1)-500000). So the program would still not be doing what you want it to do.
Additionally, the way you are trying to search for the closest point does not even work from a mathematical point of view (even if your programming had no errors). The closest point is not necessarily the closest in each single coordinate. For example, [1 1 1] is certainly closer to [0 0 0] than [20 0 0], [0 20 0] and [0 0 20]. But it is not the closest one in each single coordinate. In fact it is not the closest one in any coordinate.
There might be even more issues with your code, but for starters you should work on how to determine distances. After you master that you should try to pick points with minimal distance. And only after you master both of these should you try to integrate everything into the rest of your stuff. No point in trying to do everything at once.

recording 'bursts' of samples at 300 samples per sec

I am recording voltage changes over a small circuit- this records mouse feeding. When the mouse is eating, the circuit voltage changes, I convert that into ones and zeroes, all is well.
BUT- I want to calculate the number and duration of 'bursts' of feeding- that is, instances of circuit closing that occur within 250 ms (75 samples) of one another. If the gap between closings is larger than 250ms I want to count it as a new 'burst'
I guess I am looking for help in asking matlab to compare the sample number of each 1 in the digital file with the sample number of the next 1 down- if the difference is more than 75, call the first 1 the end of one bout and the second one the start of another bout, classifying the difference as a gap, but if it is NOT, keep the sample number of the first 1 and compare it against the next and next and next until there is a 75-sample difference
I can compare each 1 to the next 1 down:
n=1; m=2;
for i = 1:length(bouts4)-1
if bouts4(i+1) - bouts4(i) >= 75 %250 msec gap at a sample rate of 300
boutend4(n) = bouts4(i);
boutstart4(m)= bouts4(i+1);
m = m+1;
n = n+1;
end
I don't really want to iterate through i for both variables though...
any ideas??
-DB
You can try the following code
time_diff = diff(bouts4);
new_feeding = time_diff > 75;
boutend4 = bouts4(new_feeding);
boutstart4 = [0; bouts4(find(new_feeding) + 1)];
That's actually not too bad. We can actually make this completely vectorized. First, let's start with two signals:
A version of your voltages untouched
A version of your voltages that is shifted in time by 1 step (i.e. it starts at time index = 2).
Now the basic algorithm is really:
Go through each element and see if the difference is above a threshold (in your case 75).
Enumerate the locations of each one in separate arrays
Now onto the code!
%// Make those signals
bout4a = bouts4(1:end-1);
bout4b = bouts4(2:end);
%// Ensure column vectors - you'll see why soon
bout4a = bout4a(:);
bout4b = bout4b(:);
% // Step #1
loc = find(bouts4b - bouts4a >= 75);
% // Step #2
boutend4 = [bouts4(loc); 0];
boutstart4 = [0; bouts4(loc + 1)];
Aside:
Thanks to tail.b.lo, you can also use diff. It basically performs that difference operation with the copying of those vectors like I did before. diff basically works the same way. However, I decided not to use it so you can see how exactly your code that you wrote translates over in a vectorized way. Only way to learn, right?
Back to it!
Let's step through this slowly. The first two lines of code make those signals I was talking about. An original one (up to length(bouts) - 1) and another one that is the same length but shifted over by one time index. Next, we use find to find those time slots where the time index was >= 75. After, we use these locations to access the bouts array. The ending array accesses the original array while the starting array accesses the same locations but moved over by one time index.
The reason why we need to make these two signals column vector is the way I am appending information to the starting vector. I am not sure whether your data comes in rows or columns, so to make this completely independent of orientation, I'm going to make sure that your data is in columns. This is because if I try to append a 0, if I do it to a row vector I have to use a space to denote that I'm going to the next column. If I do it for a column vector, I have to use a semi-colon to go to the next row. To completely avoid checking to see whether it's a row or column vector, I'm going to make sure that it's a column vector no matter what.
By looking at your code m=2. This means that when you start writing into this array, the first location is 0. As such, I've artificially placed a 0 at the beginning of this array and followed that up with the rest of the values.
Hope this helps!

Sudoku Solver, check each 3x3 box

To sum my problem up in a nutshell, I am checking each 3x3 box if there is one missing value, if there is, it computes what that number is, and then fills that number in. However, it only does the upper left 3x3 box, and stops there. Here is the snippet of my code that relates to my issue. If you'd like to see the rest of the code just ask and I'll post the rest.
EDIT: The user inputs the board. For test purposes I tried inputting a completed Sudoku puzzle, and then take out the top right value in each box. It only filled in the first 3x3, it still output the board at the end, but had 8 other blanks to fill in (from the other 8 3x3 boxes)
% Check each 3x3 box for one through nine, fill in
for i = 0:2
for j = 0:2
if sum(sum(board([1:3]+i*3,[1:3]+j*3)~=0))==8
[row,col] = find(board([1:3]+i*3,[1:3]+j*3)==0);
answer = 45 - sum(sum(board([1:3]+i*3,[1:3]+j*3)));
board(row,col) = answer;
end
end
end
disp(board);
You are very close. The problem is that for each block you are getting the row and column index of the 3x3 block. So, for each block the following is true: row <= 3 and col <= 3.
You can easily solve this by adding these two lines after the line where you use find:
row = row + (3*i);
col = col + (3*j);
This way you convert the block-relative index back to the board-relative index.

Creating a path on coordinate system without repeating values (Matlab)

I'm trying to create a random "path" on a coordinate system on Matlab. I am doing this by creating a for loop where for each iteration it fills in a new value on a matrix that has initial values of zeros.
For example, I have 5 points so I have an initial matrix a=[0 0 0 0 0; 0 0 0 0 0] (row1 = x values, row2 = y values).
The path can move right/left or up/down (no diagonals). In my for loop, I call randi(4) and say something like "if randi(4)=1, then move 1 point to the left (x-1). if randi(4)=2, then move to the right (x+1), etc."
The problem is that you cannot visit a specific point more than once. For example, the path can start at (0,0), then go to (0,1), then (1,1), then (1,0), and then it CANNOT go back to (0,0).. in my current code I don't have this restriction so I was hoping I could get some suggestions..
Since in this example the matrix would look something like a=[0 0 1 1 0; 0 1 1 0 0].
I was thinking of maybe subtracting each new coordinate (here (0,0)) from each column on the matrix a and if any of the columns give me values of zero for both rows (since it's the same coordinate subtracted from itself), then go back one step and let randi(4) run again.. but
How could I tell it to "go back one step" (or two or three)?
How do you compare one column against each column of the already established matrix?
This was just an idea.. are there any functions in Matlab that would let me do this? or maybe compare if two columns are the same within a matrix?
To your questions.
to go back - I suppose this means just throwing away the rightmost columns in your matrix.
to find if it is present you could use ismember
unfortunately it only takes rows so you will need to transpose. Snippet:
a = [1:10; repmat(1:2,1,5)]'
test = ismember(a,[3,2],'rows')
any(test) % not found
test = ismember(a,[3,1],'rows')
any(test) % found
Of course your idea would also work.
I can answer this:
How do you compare one column against each column of the already
established matrix?
Use two different matrices. Compare them using the setdiff() function: http://www.mathworks.com/help/matlab/ref/setdiff.html

matlab percentage change between cells

I'm a newbie to Matlab and just stumped how to do a simple task that can be easily performed in excel. I'm simply trying to get the percent change between cells in a matrix. I would like to create a for loop for this task. The data is setup in the following format:
DAY1 DAY2 DAY3...DAY 100
SUBJECT RESULTS
I could only perform getting the percent change between two data points. How would I conduct it if across multiple days and multiple subjects? And please provide explanation
Thanks a bunch
FOR EXAMPLE, FOR DAY 1 SUBJECT1(RESULT=1), SUBJECT2(RESULT=4), SUBJECT3(RESULT=5), DAY 2 SUBJECT1(RESULT=2), SUBJECT2(RESULT=8), SUBJECT3(RESULT=10), DAY 3 SUBJECT1(RESULT=1), SUBJECT2(RESULT=4), SUBJECT3(RESULT=5).
I WANT THE PERCENT CHANGE SO OUTPUT WILL BE DAY 2 SUBJECT1(RESULT=100%), SUBJECT2(RESULT=100%), SUBJECT3(RESULT=100%). DAY3 SUBJECT1(RESULT=50%), SUBJECT2(RESULT=50%), SUBJECT3(RESULT=50%)
updated:
Hi thanks for responding guys. sorry for the confusion. zebediah49 is pretty close to what I'm looking for. My data is for example a 10 x 10 double. I merely wanted to get the percentage change from column to column. For example, if I want the percentage change from rows 1 through 10 on all columns (from columns 2:10). I would like the code to function for any matrix dimension (e.g., 1000 x 1000 double) zebediah49 could you explain the code you posted? thanks
updated2:
zebediah49,
(data(1:end,100)- data(1:end,99))./data(1:end,99)
output=[data(:,2:end)-data(:,1:end-1)]./data(:,1:end-1)*100;
Observing the code above, How would I go about modifying it so that column 100 is used as the index against all of the other columns(1-99)? If I change the code to the following:
(data(1:end,100)- data(1:end,:))./data(1:end,:)
matlab is unable because of exceeding matrix dimensions. How would I go about implementing that?
UPDATE 3
zebediah49,
Worked perfectly!!! Originally I created a new variable for the index and repmat the index to match the matrices which was not a good idea. It took forever to replicate when dealing with large numbers.
Thanks for you contribution once again.
Thanks Chris for your contribution too!!! I was looking more on how to address and manipulate arrays within a matrix.
It's matlab; you don't actually want a loop.
output=input(2:end,:)./input(1:end-1,:)*100;
will probably do roughly what you want. Since you didn't give anything about your matlab structure, you may have to change index order, etc. in order to make it work.
If it's not obvious, that line defines output as a matrix consisting of the input matrix, divided by the input matrix shifted right by one element. The ./ operator is important, because it means that you will divide each element by its corresponding one, as opposed to doing matrix division.
EDIT: further explanation was requested:
I assumed you wanted % change of the form 1->1->2->3->1 to be 100%, 200%, 150%, 33%.
The other form can be obtained by subtracting 100%.
input(2:end,:) will grab a sub-matrix, where the first row is cut off. (I put the time along the first dimension... if you want it the other way it would be input(:,2:end).
Matlab is 1-indexed, and lets you use the special value end to refer to the las element.
Thus, end-1 is the second-last.
The point here is that element (i) of this matrix is element (i+1) of the original.
input(1:end-1,:), like the above, will also grab a sub-matrix, except that that it's missing the last column.
I then divide element (i) by element (i+1). Because of how I picked out the sub-matrices, they now line up.
As a semi-graphical demonstration, using my above numbers:
input: [1 1 2 3 1]
input(2,end): [1 2 3 1]
input(1,end-1): [1 1 2 3]
When I do the division, it's first/first, second/second, etc.
input(2:end,:)./input(1:end-1,:):
[1 2 3 1 ]
./ [1 1 2 3 ]
---------------------
== [1.0 2.0 1.5 0.3]
The extra index set to (:) means that it will do that procedure across all of the other dimension.
EDIT2: Revised question: How do I exclude a row, and keep it as an index.
You say you tried something to the effect of (data(1:end,100)- data(1:end,:))./data(1:end,:). Matlab will not like this, because the element-by-element operators need them to be the same size. If you wanted it to only work on the 100th column, setting the second index to be 100 instead of : would do that.
I would, instead, suggest setting the first to be the index, and the rest to be data.
Thus, the data is processed by cutting off the first:
output=[data(2:end,2:end)-data(2:end,1:end-1)]./data(2:end,1:end-1)*100;
OR, (if you neglect the start, matlab assumes 1; neglect the end and it assumes end, making (:) shorthand for (1:end).
output=[data(2:,2:end)-data(2:,1:end-1)]./data(2:,1:end-1)*100;
However, you will probably still want the indices back, in which case you will need to append that subarray back:
output=[data(1,1:end-1) data(2:,2:end)-data(2:,1:end-1)]./data(2:,1:end-1)*100];
This is probably not how you should be doing it though-- keep data in one matrix, and time or whatever else in a separate array. That makes it much easier to do stuff like this to data, without having to worry about excluding time. It's especially nice when graphing.
Oh, and one more thing:
(data(:,2:end)-data(:,1:end-1))./data(:,1:end-1)*100;
is identically equivalent to
data(:,2:end)./data(:,1:end-1)*100-100;
Assuming zebediah49 guessed right in the comment above and you want
1 4 5
2 8 10
1 4 5
to turn into
1 1 1
-.5 -.5 -.5
then try this:
data = [1,4,5; 2,8,10; 1,4,5];
changes_absolute = diff(data);
changes_absolute./data(1:end-1,:)
ans =
1.0000 1.0000 1.0000
-0.5000 -0.5000 -0.5000
You don't need the intermediate variable, you can directly write diff(data)./data(1:end,:). I just thought the above might be easier to read. Getting from that result to percentage numbers is left as an exercise to the reader. :-)
Oh, and if you really want 50%, not -50%, just use abs around the final line.