I'm creating a TicTacToe game using command line in Xcode. I've got everything working properly except I can't figure out how to avoid a player from taking another players spot. So if player one chooses spot [1][1], if either player enters spot [1][1] throughout the game they will get "Invalid entry, please try again" and they will have to choose another spot. Any suggestions?
- (void) getChoice1
{
do
{
if (player == 1 && winner == 0 && turns < 9)
{
do {
//player 1's input
NSLog(#"Player 1, please choose a cell.");
NSLog(#"Enter row number(1, 2, or 3).");
scanf("%ld", &row);
} while ((row != 1 && row != 2 && row != 3));
do{
NSLog(#"Enter column number(1, 2, or 3).");
scanf("%ld", &column);
} while ((column != 1 && column != 2 && column != 3));
//decrement players input -1
row--;
column--;
//ensure spot is unselected
if (arr[row][column] == 1 || arr[row][column] == 2) {
NSLog(#"Invalid entry, try another spot");
[self getChoice1];
}
else
{
//add input to board
arr [row][column] = 1;
//display updated board
[self showBoard];
//switch players
player = 2;
//add a turn
turns++;
//check for winner
[self checkWinner];
}
}
} while (turns < 9 && winner == 0 );
}
You have to make userInteraction disabled for that block.
For example if block1 is touched, make :
block1.userInteractionEnabled = NO;
Once, game is complete, make userInteractionEnabled fro all blocks again to YES.
This will work as I have also made one similar game.
In case of command line , you can set some variables for example if for x set 1, for 0 set 2, for no play set 0.
Then, once someone new press there check for 1 and 2 and do the required
With the help of a friend I realized I have to restructure the method completely. Here's my working answer.
do
{
if (winner == 0 && turns < 9)
{
do {
//player 1's input
if (player == 1) {
NSLog(#"Player 1, please choose a cell.");
} else {
NSLog(#"Player 2, please choose a cell.");
}
NSLog(#"Enter row number(1, 2, or 3).");
scanf("%ld", &row);
} while ((row != 1 && row != 2 && row != 3));
do{
NSLog(#"Enter column number(1, 2, or 3).");
scanf("%ld", &column);
} while ((column != 1 && column != 2 && column != 3));
//decrement players input -1
row--;
column--;
//add input to board
if (arr [row][column] == 0) {
arr [row][column] = player;
if (player == 1) {
player = 2;
} else {
player = 1;
}
//display updated board
[self showBoard];
//add a turn
turns++;
} else {
NSLog (#"Cell already used pick a different cell.");
}
//check for winner
[self checkWinner];
}
} while (turns < 9 && winner == 0 );
}
Related
I’ve got a really large file, circa 10m rows, in which I’m trying to populate a column based on conditions on another column via a jsee macro. While it is quite quick for small files, it does take some time for the large file.
//pseudocode
//No sorting on Col1, which can have empty cells too
For all lines in file
IF (cell in Col2 IS empty) AND (cell in Col1 IS NOT empty) AND (cell in Col1 = previous cell in Col1)
THEN cell in Col2 = previous cell in Col2
//jsee code
document.CellMode = true; // Must be cell selection mode
totalLines = document.GetLines();
for( i = 1; i < totalLines; i++ ) {
nref = document.GetCell( i, 1, eeCellIncludeNone );
gsize = document.GetCell( i, 2, eeCellIncludeNone );
if (gsize == "" && nref != "" && nref == document.GetCell( i-1, 1, eeCellIncludeNone ) ) {
document.SetCell( i, 2, document.GetCell( i-1, 2, eeCellIncludeNone ) , eeAutoQuote);
}
}
Input File:
Reference
Group Size
14/12/01819
1
14/12/01820
1
15/01/00191
4
15/01/00191
15/01/00191
15/01/00198
15/01/00292
3
15/01/00292
15/01/00292
15/01/00401
5
15/01/00401
15/01/00402
1
15/01/00403
2
15/01/00403
15/01/00403
15/01/00403
15/01/00404
20/01/01400
1
Output File:
Reference
Group Size
14/12/01819
1
14/12/01820
1
15/01/00191
4
15/01/00191
4
15/01/00191
4
15/01/00198
15/01/00292
3
15/01/00292
3
15/01/00292
3
15/01/00401
5
15/01/00401
5
15/01/00402
1
15/01/00403
2
15/01/00403
2
15/01/00403
2
15/01/00403
2
15/01/00404
20/01/01400
1
Any ideas on how to optimise this and make it run even faster?
I wrote a JavaScript for EmEditor macro for you. You might need to set the correct numbers in the first 2 lines for iColReference and iColGroupSize.
iColReference = 1; // the column index of "Reference"
iColGroupSize = 2; // the column index of "Group Size"
document.CellMode = true; // Must be cell selection mode
sDelimiter = document.Csv.Delimiter; // retrieve the delimiter
nOldHeadingLines = document.HeadingLines; // retrieve old headings
document.HeadingLines = 0; // set No Headings
yBottom = document.GetLines(); // retrieve the number of lines
if( document.GetLine( yBottom ).length == 0 ) { // -1 if the last line is empty
--yBottom;
}
str = document.GetColumn( iColReference, sDelimiter, eeCellIncludeQuotes, 1, yBottom ); // get whole 1st column from top to bottom, separated by TAB
sCol1 = str.split( sDelimiter );
str = document.GetColumn( iColGroupSize, sDelimiter, eeCellIncludeQuotes, 1, yBottom ); // get whole 2nd column from top to bottom, separated by TAB
sCol2 = str.split( sDelimiter );
s1 = "";
s2 = "";
for( i = 0; i < yBottom; ++i ) { // loop through all lines
if( sCol2[i].length != 0 ) {
s1 = sCol1[i];
s2 = sCol2[i];
}
else {
if( s1.length != 0 && sCol1[i] == s1 ) { // same value as previous line, copy s2
if( s2.length != 0 ) {
sCol2[i] = s2;
}
}
else { // different value, empty s1 and s2
s1 = "";
s2 = "";
}
}
}
str = sCol2.join( sDelimiter );
document.SetColumn( iColGroupSize, str, sDelimiter, eeDontQuote ); // set whole 2nd column from top to bottom with the new values
document.HeadingLines = nOldHeadingLines; // restore the original number of headings
To run this, save this code as, for instance, Macro.jsee, and then select this file from Select... in the Macros menu. Finally, select Run Macro.jsee in the Macros menu.
LeetCode medium 120. Triangle (Dynamic Programming)
Question:
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
//The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
//Note:
//Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
I always get
fatal error: Can't form Range with end < start
on "for i in (row-1)...0".
Thank you so much! Appreciate your time!
class Solution
{
func minimumTotal(triangle: [[Int]]) -> Int
{
if triangle.count == 0
{
return 0
}
if triangle.count == 1
{
return triangle[0][0]
}
var arr = [Int](count: triangle.last!.count, repeatedValue: 0)
let row = triangle.count
for i in (row-1)...0
{
let col = triangle[i].count
for j in 0...col-1
{
if i == row-1
{
arr[i] = triangle[i][j]
continue
}
arr[j] = min(arr[j], arr[j+1]) + triangle[i][j]
}
}
return arr[0]
}
}
var test1 = Solution()
//var input = [[10]]
//var input = [[1],[2,3]]
var input = [[-1],[2,3],[1,-1,-3]]
var result = test1.minimumTotal(input)
print(result)
for in (0...row-1).reverse()
Swift can't read row-1...0
It's a bad idea to create a range where the start is higher than the end: your code will compile, but it will crash at runtime, so use stride instead of ranage
for i in (row-1).stride(to: 0, by: 1) { }
I came across this question, where the OP wanted to improve the following if-block. I open this as a new question because I'm searching a more general solution to this kind of problem.
public int fightMath(int one, int two) {
if(one == 0 && two == 0) { result = 0; }
else if(one == 0 && two == 1) { result = 0; }
else if(one == 0 && two == 2) { result = 1; }
else if(one == 0 && two == 3) { result = 2; }
else if(one == 1 && two == 0) { result = 0; }
else if(one == 1 && two == 1) { result = 0; }
else if(one == 1 && two == 2) { result = 2; }
else if(one == 1 && two == 3) { result = 1; }
else if(one == 2 && two == 0) { result = 2; }
else if(one == 2 && two == 1) { result = 1; }
else if(one == 2 && two == 2) { result = 3; }
else if(one == 2 && two == 3) { result = 3; }
else if(one == 3 && two == 0) { result = 2; }
else if(one == 3 && two == 1) { result = 1; }
else if(one == 3 && two == 2) { result = 3; }
else if(one == 3 && two == 3) { result = 3; }
return result;
}
Now there are n^k possibilities to get a result, where n = 2 and k = 4.
Some answers are suggesting to use an multi-array as a table to reduce the if-jungle.
But I would like to know how to solve such a problem with big n and k? Because a solution with if, switch and the suggested array approach will not scale well and to type things like that in code should be avoided.
If I think about combinatoric problems, there have to be a way to evaluate them easy.
It's just a table of data. The answer to the question is found by multiple keys. It is no different to returning some data held in a database table which could itself be huge and perhaps span multiple tables.
There are two ways to solve this:
Data-based. For example you could create a HashMap mapping the pair of values to the result.
class Pair {
int one, two;
//Generate hashcode and equals
}
Map<Pair, Integer> counts = new HashMap<>();
Pattern-based. Identify a rule/formula that can be used to determine the new value.
This is obviously better but relies on being able to identify a rule that covers all cases.
I would like to know how to solve such a problem with big n and k.
Since the output is determined arbitrarily (a game designer's whims) instead of mathematically (a formula), there's no guarantee of any pattern. Therefore the only general solution is some kind of lookup table.
Essentially, the question is similar to asking for a program that does f(a,b) -> c mapping, but you don't know any of the data beforehand -- instead it's provided at runtime. That program could process the data and find a pattern/formula (which might not exist) or it could build a lookup table.
Personally, I think it's clearer to change the logic to operate on intent (so reading the code explains how the attack works) instead of the actual outcomes (enumerating the list of inputs and matching outputs). Instead of building an if-jungle or a lookup table, structure your code based on how you want the logic to work. JAB's enum-based solution expresses the fight logic explicitly which makes it easier to see where to add new functionality and easier to see bugs (an off by one error in a lookup table isn't obviously wrong on inspection). A lookup table is a likely optimization, but that's only necessary if a profiler says so.
Looking at your question and the original one there appears to be no deducible pattern between the input from the two players and the output (perhaps I'm wrong). Given this the only options are the "if-jungle" you mention or to use a data structure.
To solve such a problem for big n and k values my suggestion would be to create a rule to determine the output (either none, one or both players hit), but ensuring that this rule isn't easily deducible to the players. You could do this by making the rule a function of turn number (e.g. if both players press button 1 on turn #1 the output will be different to if they take the same action on turn #2).
I'm trying to solve this problem:
1 2 3
4 5 6
7 8 9
* 0 #
Given a starting number, find all 6-digit numbers possible, numbers can only be dialed horizontally or vertically. Repetitions not allowed. Number can't start from zero and doesn't include * and #. For example, if last dialed number is 3, the next one could be 1, 2, 6 or 9.
I'm trying this making by creating a graph, in which a number has only those numbers adjacent which are in the same row and column, and then finding all possible paths of length 5 from the starting number. But I don't know any algorithm for doing that yet..
Any suggestions?
Assume the numbers are stored in a 2-d array NUMPAD, where "1" is at index [0][0], "2" is at index [0][1], etc.
Func permute_nums(digits_so_far)
If digits_so_far has 6 elements
print digits_so_far
return
Let L = last element of digits_so_far
Find index (x,y) of L in NUMPAD
For i from -2 to +2
if (x+i,y) is NOT out of bounds
Find number n at (x+i,y)
permute_nums(digits_so_far + [n])
if (x,y+i) is NOT out of bounds
Find number m at (x,y+i)
permute_nums(digits_so_far + [m])
Given the starting digit s, do permute_nums([s])
I think you're on the right path.
Just traverse the tree (mark every visited node, to avoid repetitions), and output every path of length 5.
You don't really need anything new here, even a basic Breadth first search that is limited to depth 5 will do.
hmmm. That should be pretty easy.
static var a:Array=[[8],[2,4],[1,3,5],[2,6],[1,5,7],[2,4,6,8],[3,5,9],[4,8],[5,7,9,0],[6,8]];
function giveAllnumbers(numbersSoFar:String,lastSelectedNumber:int,:int) {
if (howManyToSelectLeft==0) {
trace(numbersSoFar); // output goes here
return;
}
for (var i:int=a[lastSelectedNumber].length-1;i>=0;i--)
giveAllNumbers(numbersSoFar+a[lastSelectedNumber][i].toString(),
a[lastSelectedNumber][i],
howManyToSelectLeft-1);
}
This is Actionscript, but can be accommodated to any other language. Invoke with giveAllNumbers(''+yourNumber.toString(),yourNumber,desiredLength);
This problem can be solved recursively, and the returning point will be when length == 6.
private static void countMaxNumbers(String i) {
if(i.length() == 6)
{
numberCount++;
return;
}
if(i.charAt(i.length() - 1) == '1'){
countMaxNumbers(i+'2');
countMaxNumbers(i+'3');
countMaxNumbers(i+'4');
countMaxNumbers(i+'7');
}
else if(i.charAt(i.length() - 1) == '2'){
countMaxNumbers(i+'5');
countMaxNumbers(i+'8');
countMaxNumbers(i+'0');
countMaxNumbers(i+'1');
countMaxNumbers(i+'3');
}
else if(i.charAt(i.length() - 1) == '3'){
countMaxNumbers(i+'1');
countMaxNumbers(i+'2');
countMaxNumbers(i+'6');
countMaxNumbers(i+'9');
}
else if(i.charAt(i.length() - 1) == '4'){
countMaxNumbers(i+'1');
countMaxNumbers(i+'7');
countMaxNumbers(i+'5');
countMaxNumbers(i+'6');
}
else if(i.charAt(i.length() - 1) == '5'){
countMaxNumbers(i+'2');
countMaxNumbers(i+'8');
countMaxNumbers(i+'0');
countMaxNumbers(i+'4');
countMaxNumbers(i+'6');
}
else if(i.charAt(i.length() - 1) == '6'){
countMaxNumbers(i+'3');
countMaxNumbers(i+'9');
countMaxNumbers(i+'4');
countMaxNumbers(i+'5');
}
else if(i.charAt(i.length() - 1) == '7'){
countMaxNumbers(i+'1');
countMaxNumbers(i+'4');
countMaxNumbers(i+'8');
countMaxNumbers(i+'9');
}else if(i.charAt(i.length() - 1) == '8'){
countMaxNumbers(i+'7');
countMaxNumbers(i+'9');
countMaxNumbers(i+'2');
countMaxNumbers(i+'5');
countMaxNumbers(i+'0');
}else if(i.charAt(i.length() - 1) == '9'){
countMaxNumbers(i+'3');
countMaxNumbers(i+'6');
countMaxNumbers(i+'7');
countMaxNumbers(i+'8');
}else if(i.charAt(i.length() - 1) == '0'){
countMaxNumbers(i+'2');
countMaxNumbers(i+'8');
countMaxNumbers(i+'5');
}
}
Answer should be : 12855
I have an array (of 9 elements, say) which I must treat as a (3 by 3) square.
For the sake of simplifying the question, this is a one-based array (ie, indexing starts at 1 instead of 0).
My goal is to determine valid adjacent squares relative to a starting point.
In other words, how it's stored in memory: 1 2 3 4 5 6 7 8 9
How I'm treating it:
7 8 9
4 5 6
1 2 3
I already know how to move up and down and test for going out of bounds (1 >= current_index <= 9)
edit: I know the above test is overly general but it's simple and works.
//row_size = 3, row_step is -1, 0 or 1 depending on if we're going left,
//staying put or going right respectively.
current_index += (row_size * row_step);
How do I test for an out of bounds condition when going left or right? Conceptually I know it involves determining if 3 (for example) is on the same row as 4 (or if 10 is even within the same square as 9, as an alternate example, given that multiple squares are in the same array back to back), but I can't figure out how to determine that. I imagine there's a modulo in there somewhere, but where?
Thanks very much,
Geoff
Addendum:
Here's the resulting code, altered for use with a zero-based array (I cleaned up the offset code present in the project) which walks adjacent squares.
bool IsSameSquare(int index0, int index1, int square_size) {
//Assert for square_size != 0 here
return (!((index0 < 0) || (index1 < 0))
&& ((index0 < square_size) && (index1 < square_size)))
&& (index0 / square_size == index1 / square_size);
}
bool IsSameRow(int index0, int index1, int row_size) {
//Assert for row_size != 0 here
return IsSameSquare(index0, index1, row_size * row_size)
&& (index0 / row_size == index1 / row_size);
}
bool IsSameColumn(int index0, int index1, int row_size) {
//Assert for row_size != 0 here
return IsSameSquare(index0, index1, row_size * row_size)
&& (index0 % row_size == index1 % row_size);
}
//for all possible adjacent positions
for (int row_step = -1; row_step < 2; ++row_step) {
//move up, down or stay put.
int row_adjusted_position = original_position + (row_size * row_step);
if (!IsSameSquare(original_position, row_adjusted_position, square_size)) {
continue;
}
for (int column_step = -1; column_step < 2; ++column_step) {
if ((row_step == 0) & (column_step == 0)) { continue; }
//hold on to the position that has had its' row position adjusted.
int new_position = row_adjusted_position;
if (column_step != 0) {
//move left or right
int column_adjusted_position = new_position + column_step;
//if we've gone out of bounds again for the column.
if (IsSameRow(column_adjusted_position, new_position, row_size)) {
new_position = column_adjusted_position;
} else {
continue;
}
} //if (column_step != 0)
//if we get here we know it's safe, do something with new_position
//...
} //for each column_step
} //for each row_step
This is easier if you used 0-based indexing. These rules work if you subtract 1 from all your indexes:
Two indexes are in the same square if (a/9) == (b/9) and a >= 0 and b >= 0.
Two indexes are in the same row if they are in the same square and (a/3) == (b/3).
Two indexes are in the same column if they are in the same square and (a%3) == (b%3).
There are several way to do this, I'm choosing a weird one just for fun. Use modulus.
Ase your rows are size 3 just use modulus of 3 and two simple rules.
If currPos mod 3 = 0 and (currPos+move) mod 3 = 1 then invalid
If currPos mod 3 = 1 and (currPos+move) mod 3 = 0 then invalid
this check for you jumping two a new row, you could also do one rule like this
if (currPos mod 3)-((currPos+move) mod 3)> 1 then invalid
Cheers
You should be using a multidimensional array for this.
If your array class doesn't support multidimensional stuff, you should write up a quick wrapper that does.