I’m doing a turn based game... the only information transferred is the score of the player and whether a turn has been sent.
When the next player receives the turn. The data gets stored into “scoreToBeat” and turnSent=1. The player then takes their turn. Afterward the game ended gets called because turnSent=1. I used the turn based tutorial by Ray Wenderlich at http://www.raywenderlich.com/5480/beginning-turn-based-gaming-with-ios-5-part-1.
In his case the game ends and is a tie. Like this... I can’t seem to get it to show the person that lost.
for (GKTurnBasedParticipant *part in currentMatch.participants) {
part.matchOutcome = GKTurnBasedMatchOutcomeTied;
}
I can’t seem to get it to show the person that lost it always shows a win. This is my latest attempt of many... Exactly 2 players in the match btw... Any ideas would be greatly appreciated.
for (GKTurnBasedParticipant *part in currentMatch.participants) {
if(part==currentMatch.currentParticipant)
{
if(points>scoreToBeat)
{
part.matchOutcome=GKTurnBasedMatchOutcomeWon;
}
else {
part.matchOutcome=GKTurnBasedMatchOutcomeLost;
}
}
else {
if(points>scoreToBeat)
{
part.matchOutcome=GKTurnBasedMatchOutcomeLost;
}
else {
part.matchOutcome=GKTurnBasedMatchOutcomeWon;
}
}
This is an excerpt from my latest project, good for a 2 player game. It's called during the sendTurn process, when the game is decided to be ending. This is more correct than the previous answer (first code block), in my opinion, because you must set the matchOutcome for all participants before ending the game.
If you had more than 2 players, then you'd have to loop through all participants and set the matchOutcome accordingly.
GKTurnBasedParticipant *curr = currentMatch.currentParticipant;
NSUInteger currentIndex = [currentMatch.participants indexOfObject:currentMatch.currentParticipant];
NSUInteger nextIndex = (currentIndex + 1) % [currentMatch.participants count];
GKTurnBasedParticipant *next = [currentMatch.participants objectAtIndex:nextIndex];
if (currScore < otherScore)
{
// Curr player lost
curr.matchOutcome = GKTurnBasedMatchOutcomeLost;
next.matchOutcome = GKTurnBasedMatchOutcomeWon;
}
else if (currScore == otherScore)
{
// Tied
curr.matchOutcome = GKTurnBasedMatchOutcomeTied;
next.matchOutcome = GKTurnBasedMatchOutcomeTied;
}
else
{
// Won
curr.matchOutcome = GKTurnBasedMatchOutcomeWon;
next.matchOutcome = GKTurnBasedMatchOutcomeLost;
}
Note that you will see "Won" on both devices by design.
One will say "Me" with "Won" underneath, and the other will say "(Winners Name)" with "Won" underneath.
points is the local points scored on the device right? if so, I would do the following:
if([part.playerID isEqualToString [GKLocalPlayer localPlayer].playerID]]) {
if(points>scoreToBeat) {
part.matchOutcome = GKTurnBasedMatchOutComeWon;
} else {
part.matchOutcome = GKTurnBasedMatchOutComeLost;
}
} else {
if(points>scoreToBeat) {
part.matchOutcome=GKTurnBasedMatchOutcomeLost;
} else {
part.matchOutcome=GKTurnBasedMatchOutcomeWon;
}
}
}
Also, remember to use a NSLog to see if score to beat is actually transferred. One mistake you can do to keep on using currentTurnBasedMatch.matchData, you should set the currentTurnBasedMatch to GKTurnBasedMatch that is returned in delegate methods.
EDIT: A code snipped I use looks like this
if([participant.playerID isEqualToString:[GKLocalPlayer localPlayer].playerID]){
NSLog(#"we are the last player in the game -end the game");
for (GKTurnBasedParticipant *part in match.participants) {
part.matchOutcome = GKTurnBasedMatchOutcomeTied;
}
[match endMatchInTurnWithMatchData:match.matchData completionHandler:^(NSError *error) {
if ([AppDelegate mainMenuController].multiGameMenu.turnBasedMenu !=nil) {
[[AppDelegate mainMenuController].multiGameMenu.turnBasedMenu reloadTableView];
}
} ];
}
Related
I have below code in Update() to drag camera and also detect clicks on objects. When we try on iphone 6 and X it works all well, but when we try on iPhone7 the drag screen is very unresponsive and clicking objects works only when you touch the screen very very lightly. Anybody have an idea on what is going on?
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) {
fingerMoved = false;
if (_eventSystem.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) {
fingerMoved = true;
}
hit_position = Input.GetTouch(0).position;
camera_position = cam.position;
} else if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
current_position = Input.GetTouch(0).position;
LeftMouseDrag();
if (Vector2.Distance(hit_position, current_position) > 7f) {
fingerMoved = true;
}
cam.DOMoveY(target_position.y, 0.75f);
} else if (!fingerMoved && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) {
foreach (var item in storageList) {
if (Vector2.Distance(item.transform.position, Camera.main.ScreenToWorldPoint(hit_position)) < 0.5f) {
sideMenu.Open(item.myNo);
}
}
}
void LeftMouseDrag() {
Vector3 direction = Camera.main.ScreenToWorldPoint(current_position) - Camera.main.ScreenToWorldPoint(hit_position);
direction.x = 0f;
direction = direction * -1;
target_position = camera_position + direction;
if (target_position.y > camMaxY) {
target_position.y = camMaxY;
}
if (target_position.y < camMinY) {
target_position.y = camMinY;
}
}
I am unsure if it makes a difference but for this kind of stuff its easier and more reliable to use EventSystems and OnPointerClick / OnPointerDrag hanlders. This way, at least in theory, any sensitivity differences could be leveled out by Unity itself. (I am not aware weather it does it or not its just
The problem has gone by itself, I have no idea what went wrong at first.
I was having the same problem and fixed it by adding the second line of the code displayed below.
else if (Input.GetTouch(0).phase == TouchPhase.Moved)
if (master.calcDelta(Input.GetTouch(0).position) > 0f)
Which in turn, calculates the length of the vector that represents the dislocation from the previous location to the actual one.
calculatedDelta = Mathf.Abs(_touchPos.magnitude - pastPos.magnitude);
What is does is prevents the jittering from interfering with the built in function from unity "TouchPhase.Moved".
I would like to create an object with a custom Object Id. The reason I want to do this is because I would like the save method to fail if it tries to create a row with the same data. For example: Parse automatically fails to save if you try to sign up with an email that is already taken. I would like the same thing to happen for data in a class that is not a User class.
Alternatively I could make things work if I knew how to do this
if(class contains column with "this string of data"){
do nothing}
else{
save "this string of data"}
What I'm doing is implementing an up-voting and down-voting system, and I don't want users to be able to vote more than once on a single post.
Each time a user votes, it would enter into parse a row of data with a column that is of string type that would be content of post + voter. and so if that combination of content of post + voter would try to be saved again, I want it to fail.
This is the code for a cell in the tableview. This is the downVote code. (the upVote code would be very similar)
//intVotes goes into a label with the amount of votes
//thisReview contains the content of the post
//downVote() increments number of votes by -1 in Parse
#IBAction func downVote(sender: AnyObject) {
var reviewQuery: PFQuery = PFQuery(className: "reviews")
reviewQuery.whereKey("content", equalTo: reviewTextView.text)
reviewQuery.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects{
let review:PFObject = object as! PFObject
self.defaults.setValue(review["content"], forKey: "thisReview")
}
}
}
var vote:PFObject = PFObject(className: "votes")
if String(stringInterpolationSegment: vote.valueForKey("votes")) != String(stringInterpolationSegment: defaults.valueForKey("thisReview")) + String(stringInterpolationSegment: PFUser.currentUser()){
vote.setValue(String(stringInterpolationSegment: defaults.valueForKey("thisReview")) + String(stringInterpolationSegment: PFUser.currentUser()), forKey: "objectId")
vote.saveInBackgroundWithBlock {
(succeeded: Bool, error: NSError!) -> Void in
if error == nil {
self.downVote()
var intVotes: Int = self.votes.text!.toInt()!
intVotes = intVotes - 1
self.votes.text = "\(intVotes)"
} else {
println ("Failed")
}
}
}
else{
//do nothing
}
}
This ALMOST works, except the left side of the equation in the if statement (the vote.valueForKey part) returns nil every time.
You should just translate what Parse already shows you in their tutorial named "AnyPic" they implment and up/down voting "like button" system in ObjC, here's the main element translated to Swift you will have to import PAPCache.h/m PAPConstants.h/m and PAPUtility.h/m into your project and build out a bridging header to link to these files. From there, the only part you need to figure out is how to modify the following code to fit your needs, but this is already working, you just need to rearrange the variables, and change stuff to Optionals or NON-optionals to make this work for you. I'd assume that this method is THE BEST method since Parse uses this method themself in their ObjC BIG tutorial to show off everything which is the app "AnyPic", you'll have to declare a property in your UIVIewController of type PFObject and more, but this is the guts of the code. No one is going to give you the full code since this is going to take a lot of code and it would be easier if you did this in Swift instead of needing to do what I just did in the last 30 minutes. Bridging this to match the ObjC code is going to be laborious, but this is how it's done. Good luck!
What you need to declare, at minnimum:
var likeUsers : NSArray?
var likeButton: UIButton?
var someObject: PFObject?
Method:
func didTapLikeButtonAction(button: UIButton) {
var liked = Bool()
liked = !button.selected
button.removeTarget(self, action: "didTapLikeButtonAction(button)", forControlEvents: UIControlEvents.TouchUpInside)
var originalLikeUsersArray = NSArray()
originalLikeUsersArray = self.likeUsers!
var newLikeUsersSet = NSMutableSet(capacity: self.likeUsers!.count)
for id in self.likeUsers! {
if id.objectId != PFUser.currentUser()?.objectId {
newLikeUsersSet.addObject(id)
}
}
if liked {
PAPCache.sharedCache().incrementLikerCountForPhoto(self.someObject)
newLikeUsersSet.addObject(PFUser.currentUser()!)
} else {
PAPCache.sharedCache().decrementLikerCountForPhoto(self.someObject)
}
PAPCache.sharedCache().setPhotoIsLikedByCurrentUser(self.someObject, liked: liked)
likeUsers = newLikeUsersSet.allObjects
if liked {
PAPUtility.likePhotoInBackground(self.someObject, block: {(success: Bool, error: NSError?) -> Void in
if !success {
button.addTarget(self, action: "didTapLikeButtonAction(button)", forControlEvents:UIControlEvents.TouchUpInside)
self.likeUsers = originalLikeUsersArray
self.setLikeButtonState(true)
}
})
} else {
PAPUtility.unlikePhotoInBackground(self.someObject, block: {(success: Bool, error: NSError?) -> Void in
if !success {
button.addTarget(self, action: "didTapLikeButtonAction(button)", forControlEvents:UIControlEvents.TouchUpInside)
self.likeUsers = originalLikeUsersArray
self.setLikeButtonState(false)
}
})
}
}
LikeButtonFunction translated from ObjC
func setLikeButtonState(selected: Bool) {
if selected {
likeButton?.titleEdgeInsets = UIEdgeInsetsMake( -1.0, 0.0, 0.0, 0.0)
} else {
likeButton?.titleEdgeInsets = UIEdgeInsetsMake( 0.0, 0.0, 0.0, 0.0)
}
likeButton?.selected = selected
}
You will need to download the "Anypic" project from here:
https://parse.com/tutorials/anypic
and you will need to import into you Swift project, at minnimum, the following:
#import "PAPCache.h"
#import "PAPConstants.h"
#import "PAPUtility.h"
You will then need to recode the PAPCache, PAPUtility, and PAPConstants to fit your needs. Good luck, this will be a lot of coding due to Swift, but could be close to no coding if you were to use ObjC as Parse has said over and over again that they will not make a big push into Swift until it's battle tested. The last time they said this again was just two months ago in June.
The original code, from Objective-C, there's some things I didn't do for you since this is YOUR app and you will have to do these things yourself if you see it necessary, again, the ObjC code is done, but you chose to use Swift, so recoding what has already been provided basically, "out of the box" is what you are going to have to deal with:
- (void)didTapLikePhotoButtonAction:(UIButton *)button {
BOOL liked = !button.selected;
[button removeTarget:self action:#selector(didTapLikePhotoButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self setLikeButtonState:liked];
NSArray *originalLikeUsersArray = [NSArray arrayWithArray:self.likeUsers];
NSMutableSet *newLikeUsersSet = [NSMutableSet setWithCapacity:[self.likeUsers count]];
for (PFUser *likeUser in self.likeUsers) {
if (![[likeUser objectId] isEqualToString:[[PFUser currentUser] objectId]]) {
[newLikeUsersSet addObject:likeUser];
}
}
if (liked) {
[[PAPCache sharedCache] incrementLikerCountForPhoto:self.photo];
[newLikeUsersSet addObject:[PFUser currentUser]];
} else {
[[PAPCache sharedCache] decrementLikerCountForPhoto:self.photo];
}
[[PAPCache sharedCache] setPhotoIsLikedByCurrentUser:self.photo liked:liked];
[self setLikeUsers:[newLikeUsersSet allObjects]];
if (liked) {
[PAPUtility likePhotoInBackground:self.photo block:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
[button addTarget:self action:#selector(didTapLikePhotoButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self setLikeUsers:originalLikeUsersArray];
[self setLikeButtonState:NO];
}
}];
} else {
[PAPUtility unlikePhotoInBackground:self.photo block:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
[button addTarget:self action:#selector(didTapLikePhotoButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self setLikeUsers:originalLikeUsersArray];
[self setLikeButtonState:YES];
}
}];
}
[[NSNotificationCenter defaultCenter] postNotificationName:PAPPhotoDetailsViewControllerUserLikedUnlikedPhotoNotification object:self.photo userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:liked] forKey:PAPPhotoDetailsViewControllerUserLikedUnlikedPhotoNotificationUserInfoLikedKey]];
}
- (void)didTapLikerButtonAction:(UIButton *)button {
PFUser *user = [self.likeUsers objectAtIndex:button.tag];
if (delegate && [delegate respondsToSelector:#selector(photoDetailsHeaderView:didTapUserButton:user:)]) {
[delegate photoDetailsHeaderView:self didTapUserButton:button user:user];
}
}
- (void)didTapUserNameButtonAction:(UIButton *)button {
if (delegate && [delegate respondsToSelector:#selector(photoDetailsHeaderView:didTapUserButton:user:)]) {
[delegate photoDetailsHeaderView:self didTapUserButton:button user:self.photographer];
}
}
The ObjC code from above comes from the file "PAPPhotoDetailsHeaderView.m" of the Parse.com AnyPic github repo and you can see their OBJECTIVE-C tutorial on this on their web site at the web site I've listed above.
And, by the way, this DOES work for me, and it does compile for me, but I don't use Swift, so this is useless to me, but if you set things up correctly, you don't need to mess around with the PAPCache, PAPConstants, and PAPUtility. But this assumes you are well versed in all things Parse. Anyway, good luck.
I just added the likeButtonOn/Off function, translated from ObjC
I am trying to implement IDA* algorithm to solve 15 puzzle problem in objective C, I have implemented the algorithm very well but not getting the exact result. Here is my code-
- (TreeNode *)IDAStarSolution:(TreeNode *)startState {
int limit = 5;//2*[startState fx];
appDelegate.CN=[NSNumber numberWithInt:limit];
TreeNode *result=nil;
while (result==nil) {
[appDelegate.closedList addObject:startState];
newLimit = 99999;
result = [self depthLimitSearch:startState costLimit:limit];
limit = newLimit;
appDelegate.CN=[NSNumber numberWithInt:newLimit];
[appDelegate.closedList removeAllObjects];
}
return result;
}
- (TreeNode*)depthLimitSearch:(TreeNode *)current costLimit:(int)currentCostBound {
NSArray *neighbors =[current expandNodeToChilds];
for (TreeNode *s in neighbors) {
if ([s.puzzleBox isFinalStateBox]) {
appDelegate.result=s.moveString;
return s;
}
if (![self closedSetContains:s]) {
int currentCost = [s.cost intValue] + [s.puzzleBox.manhattanDistance intValue];
if (currentCost <= currentCostBound) {
[appDelegate.closedList addObject:s];
[s.puzzleBox displayPuzzleBox];
TreeNode *solution = [self depthLimitSearch:s costLimit:currentCostBound];
if (solution!=nil&& (bestSolution ==nil|| [solution.cost intValue] < [bestSolution.cost intValue])) {
bestSolution = solution;
//return solution;
}
}else {
if (currentCost < newLimit) {
NSLog(#"new limit %d", currentCost);
newLimit = currentCost;
}
}
}
}
return bestSolution;
}
-(BOOL)closedSetContains:(TreeNode *)node{
for (TreeNode *tNode in appDelegate.closedList) {
if (tNode==node) {
return YES;
}
}
return NO;
}
The depthLimitedSearch always returning null, and then expand the same node again and again.
So what i have done wrong please suggest.
Implementation is similar to java code given at :
Iterative Deepening A Star (IDA*) to solve n-puzzle (sliding puzzle) in Java
As i am returning bestSolution now, if i set the limit more than optimum cost then it returns the first solution it found, which is not optimum. What to do now?
I think your mutation/enumeration problem is caused by the structure of your closedSetContains method. You are enumerating appDelegate.closedList but return from the middle of the enumeration. I suspect that when you then modify appDelegate.closedList it causes the error, because it looks like the enumeration is still active. You should be able to confirm this by checking the array reference from the exception with the array appDelegate.closedList in the debugger.
Changing your closedSetContains to this -
-(BOOL)closedSetContains:(TreeNode *)node{
BOOL ret=NO;
for (TreeNode *tNode in appDelegate.closedList) {
if (tNode==node) {
ret=YES;
break;
}
}
return ret;
}
may help. But if appDelegate.closedList is an NSMutableArray you can replace the whole method with [appDelegate.closedList containsObject:node]
Below sample code never come out of while loop and its printing the number of running actions as 1 always. What I am missing?
Thanks in advance
Krishna
-(id)init
{
if(self == [super init])
{
CCSPrite *mySprt = [CCSprite spriteWithFile:#"myFile.png"];
mySprt.position = ccp(160,240);
mySprt.tag = 331;
CCFadeTo *fadeSprt = [CCFadeTo actionWithDuration:20.0 opacity:0];
[mySprt runAction:fadeSprt];
[self addChild:mySprt];
[self checkActionCount];
}
return self;
}
-(void)checkActionCount
{
while([self getchildByTag:331].numberofrunningactions > 0)
{
NSLog(#"Number of actions = %d",[self getchildByTag:331].numberofrunningactions);
continue;
}
NSLog(#"Number of actions = %d",[self getchildByTag:331].numberofrunningactions);
}
You have an endless loop:
while([self getchildByTag:331].numberofrunningactions > 0)
{
NSLog(..);
continue;
}
The continue statement will exit the current block to re-evaluate the while condition, which is true, which will do a continue, and re-evaluate the while condition, and so on for all eternity.
Instead try this:
if ([self getchildByTag:331].numberofrunningactions > 0)
{
NSLog(..);
}
and call the checkActionCount method from a scheduled selector, for instace update:, so that the condition is evaluated once every frame.
CCFadeTo *fadeSprt = [CCFadeTo actionWithDuration:20.0 opacity:0];
[mySprt runAction:fadeSprt];
You initialize a CCAction with duration 20.0 seconds.
Now you run it on the mySprt. this increase the numberofRunningActions count by 1.
which is what you are checking in while loop and it logs 1.
After 20 seconds when the action finishes. it will log 0 (unless you add other action).
in this following else if ,the last else condtion is not executing ?
Please help me
if (Flag==1)
{
...
}
else if ([totalBooksId containsObject:currentbook])
{
...
}
else if (![totalBooksId containsObject:currentbook])
{
...
} else {
...
}
All variable have some values but still else is not executing.
the above else statement is not executing at all? Please help me
This is will work
if(Flag==1){
if([OwnList containsObject:currentbook]){
if(fileExists) {
[self renameReadButton];
}else if(!fileExists){
[self renameDownloadButton];
}
[self renameLendButton];
}
}
else if([totalBooksId containsObject:currentbook]){
//Checking bought books
if([OwnList containsObject:currentbook]){
if(fileExists){
[self renameReadButton];
}else {
[self renameDownloadButton];
}
} else{
[self renameBuyButton];
}
}
else if(![totalBooksId containsObject:currentbook]) {
if([freeList containsObject:currentbook]){
if(fileExists){
[self renameReadButton];
}else{
[self renameDownloadButton];
}
} else{
[self renameBuyButton];
}
}
If the last else on an else-if block is not hit it usually means either of these:
One of the conditions in the initial if clause or the following else-if clauses was true
One of the evaluated conditions altered the program path (exception, stack corruption, etc.)
The code of the entire if-else block was never reached
In your case it seems to be the first case, because one of the else if conditions is the inverse of another.
Either ([totalBooksId containsObject:currentbook]) is true, or !([totalBooksId containsObject:currentbook]) is true. To hit the final else, both of them must be false.
You have three statement
else if([totalBooksId containsObject:currentbook]) // first
{
}
else if(![totalBooksId containsObject:currentbook]) // second
{
}
else { [self renameBuyButton]; } // last
Last statement is not executed because first and second catch all possible situations.
First catch [totalBooksId containsObject:currentbook] == true , second cath [totalBooksId containsObject:currentbook] == false and there is no third possibility.