Hi,
Im working on Visual Studio Winforms and I'm trying to build tic-tac-toe.
I got stuck in the Check if player win method.
I have tried to do that in activated. little example:
private void StartForm_Activated(object sender, EventArgs e)
{
if ((_pcb1.Image == imagecircle) && (_pcb2.Image == imagecircle) && (_pcb3.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb4.Image == imagecircle) && (_pcb5.Image == imagecircle) && (_pcb6.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb7.Image == imagecircle) && (_pcb8.Image == imagecircle) && (_pcb9.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
}
(I know that there are more situations to win).
It's never get into the method, I trying to find a method that active always when the form is open. please help :)
You should check player's victory after each move of that player. I assume, that your players make their moves by clicking on "Make a Move" button or clicking on the game field. Also I assume, that you have Click event of your button or game field. So you should paste your check code in Click event of your button or game field.
Here is some code that will extend to whatever game size:
public class Level
{
private readonly Team[,] _game;
public Level(int extent)
{
_game = new Team[extent, extent];
}
public bool HasWon(Team team)
{
var yMax = GetYMax();
var xMax = GetXMax();
var won = false;
// check horizontally
for (var y = 0; y < yMax; y++)
{
won = false;
for (var x = 0; x < xMax; x++)
won |= _game[y, x] == team;
if (won) return true;
}
// TODO check vertically
// TODO check diagonally
return won;
}
public void SetTile(Team team, int x, int y)
{
var xMax = GetXMax();
var yMax = GetYMax();
if ((x < 0) || (x > xMax))
throw new ArgumentOutOfRangeException("x");
if ((y < 0) || (y > yMax))
throw new ArgumentOutOfRangeException("y");
_game[y, x] = team;
}
private int GetXMax()
{
var xMax = _game.GetUpperBound(1);
return xMax;
}
private int GetYMax()
{
var yMax = _game.GetUpperBound(0);
return yMax;
}
}
public enum Team
{
Red,
Blue
}
Things for you to do:
implement logic for checking if a team has won vertically or diagonally
implement your game using this class, drawing pictures according the array _game (make it available publicly)
study the | OR operator to understand how it's used in here : https://msdn.microsoft.com/en-us/library/6373h346.aspx
further debug the code (I haven't :)
If you want to find some method that is constantly called, so as to check whether the players have won, you can just create a Timer that runs every 1 millisecond. Then the event handler for Timer.Tick would be such a method.
However, you shouldn't find such a method to check for winning/losing. It's a waste of resources to check for that every 1 millisecond.
Think, what action can affect the result of a game of tic tac toe? It's of course when either player places something (X or O) on the board! That is when you need to check whether someone has won. Also, if the thing placed is a X, you don't need to check whether the player who is playing O has won, because that's simply impossible!
Also, checking whether the image in a picture box is equal to the X or O image is really "non abstract" code. Try to put these things into a model by abstraction.
Related
I'm revising a code so that a camera will cycle through 3 different locations on a ship. The problem I've come across with this code is that it will only go to a 2nd location & stays there. It needs to cycle through but doesn't.
This is the code I'm working with:
public void CycleCameraView (Vector3 inputValue, int customPlayerInputEventType)
{
// Cycle the current camera view index to the next view.
currentCameraViewIndex = (currentCameraViewIndex + 1) % 3;
SetCurrentView(currentCameraViewIndex);
}
public int GetCurrentCameraViewIndex ()
{
return currentCameraViewIndex;
}
public int GetNextCameraViewIndex ()
{
return (currentCameraViewIndex + 1) % 3;
}
public void SetCurrentView(int viewIndex)
{
if (viewIndex >= 0 && viewIndex < 3 && shipCameraModule != null)
{
currentCameraViewIndex = viewIndex;
if (currentCameraViewIndex == 0)
{
// Camera view 1
// Set the camera parameters to match camera view 1
}
else if (currentCameraViewIndex == 1)
{
// Camera view 2
// Set the camera parameters to match camera view 2
}
else
{
// Camera view 3
// Set the camera parameters to match camera view 3
}
}
}
#endregion
}
First, you are repeating your code here which is obviously not a good practice.
(currentCameraViewIndex + 1) % 3;
Call the GetNextCameraViewIndex and bring the above logic there.
public void CycleCameraView (Vector3 inputValue, int customPlayerInputEventType)
{
// Cycle the current camera view index to the next view.
currentCameraViewIndex = GetNextCameraViewIndex;
SetCurrentView(currentCameraViewIndex);
}
public int GetNextCameraViewIndex ()
{
return (currentCameraViewIndex + 1) % 3; // Please correct if required, I'm not on a dev machine.
}
I think we need more stuff if you want us to be able to help you mate. Also, you shouyld definitly use a switch in your SetCurrentView(int viewIndex)
I'm making a board game in Unity with multiple branching paths where the players can decide which one to follow. (Think the Mario Part game board) But the player input on which path to follow isn't working.
So I have a script that has the tokens follow a set path and (Linked List for the path) with a for loop to have the tokens move their allocated amount. Within the loop, I have an If statement that checks how many paths the tile has and if there are more than one if runs a separate script that pauses the game and offers a menu prompt for the players to pick one path or the other.
I've tried tossing in a few contitions for continuing the game within the loop but they either ignore the player input, are an input behind or just break the code.
`for (int i = 0; i < spacesToMove; i++)
{
if (final_Waypoint == null)
{
final_Waypoint = Starting_Waypoint;
}
else
{
if (final_Waypoint.Next_Waypoint == null || final_Waypoint.Next_Waypoint.Length == 0)
{
//we are overshooting the final waypoint, so just return some nulls in the array
//just break and we'll return the array, which is going to have nulls at the end.
Debug.Log(Current_Waypoint);
break;
}
else if (final_Waypoint.Next_Waypoint.Length > 1) // && if playerID == 0 so it only appears for players.
{
menu.Pause_for_Choice();
//if (menu.ButtonPress == true)
final_Waypoint = final_Waypoint.Next_Waypoint[menu.choice_int];
//***There's a bug here. It calls menu as per normal, and the game pauses.
//But when I click 'no', choice_int isn't updated first: this function finishes first,
//so this function gets old choice_int. THEN the button function executes.
Debug.Log("test 3 " + menu.choice_int);
}
else
{
final_Waypoint = final_Waypoint.Next_Waypoint[0];
}
}
listOfWaypoints[i] = final_Waypoint;
Debug.Log("i:" + i);
}
return listOfWaypoints;
}`
`{
public GameObject choice_Menu;
public bool isPaused = true;
public int choice_int=0;
public int choice_placeholder = 0;
public void Pause_for_Choice()
{
isPaused = true;
choice_Menu.SetActive(true);
Time.timeScale = 0;
}
public void Yes()
{
choice_placeholder = 0;
UnPause_Game();
}
public void No()
{
choice_placeholder = 1;
UnPause_Game();
}
public void UnPause_Game()
{
isPaused = false;
choice_Menu.SetActive(false);
Time.timeScale = 1;
}
}`
I am wondering what the best way to make a button in MonoGame is. I tried to look for an answer but none seem to be out there. Is it bad practice to use WinForm buttons? If so, what viable alternatives exist?
I always like making a custom button class, this gives me a lot of flexibility for creating creative buttons.
The class creates a button with a texture and a position x and position y and a unique name, after i've done that i'll check my mouse position and see if it's inside the button or not, if it is inside the button then it can click the button and it will search the button by name and execute the given command :)
Here is an example of my button class: (not the best way, but hey it works perfectly for me)
public class Button : GameObject
{
int buttonX, buttonY;
public int ButtonX
{
get
{
return buttonX;
}
}
public int ButtonY
{
get
{
return buttonY;
}
}
public Button(string name, Texture2D texture, int buttonX, int buttonY)
{
this.Name = name;
this.Texture = texture;
this.buttonX = buttonX;
this.buttonY = buttonY;
}
/**
* #return true: If a player enters the button with mouse
*/
public bool enterButton()
{
if (MouseInput.getMouseX() < buttonX + Texture.Width &&
MouseInput.getMouseX() > buttonX &&
MouseInput.getMouseY() < buttonY + Texture.Height &&
MouseInput.getMouseY() > buttonY)
{
return true;
}
return false;
}
public void Update(GameTime gameTime)
{
if (enterButton() && MouseInput.LastMouseState.LeftButton == ButtonState.Released && MouseInput.MouseState.LeftButton == ButtonState.Pressed)
{
switch (Name)
{
case "buy_normal_fish": //the name of the button
if (Player.Gold >= 10)
{
ScreenManager.addFriendly("normal_fish", new Vector2(100, 100), 100, -3, 10, 100);
Player.Gold -= 10;
}
break;
default:
break;
}
}
}
public void Draw()
{
Screens.ScreenManager.Sprites.Draw(Texture, new Rectangle((int)ButtonX, (int)ButtonY, Texture.Width, Texture.Height), Color.White);
}
}
So I created a monster which I want to be consistently moving right and left between x= 156 and x = 501
Here's what i have done so far in my move() method:
public void move()
{
int left = 156;
int right = 501;
if (left <= x)
{
x++;
}
if (x >= 501)
{
x -= 1;
}
}
Then I call the method using a timer
private void tmr2_Tick(object sender, EventArgs e)
{
foreach (Monster m in monsters_)
{
m.move();
}
screen.Refresh();
}
This doesn't work. Could someone please help out.
Thanks
Beside coordinates X and Y the monster has to have one more property, let's call it Direction. When monster reaches one of the goals you change this Direction property, and only then you adjust the coordinates.
This might do the work for you
public class Monster
{
private const int MIN_X = 156;
private const int MAX_X = 501;
private int _x;
//your TL(probably) will tell you to use Enum
private bool _toLeft;
public Monster()
{
_toLeft = false;
_x = MIN_X;
}
public void Move()
{
if (_toLeft)
{
_x--;
}
else
{
_x++;
}
CheckEdges();
}
private void CheckEdges()
{
if (_x == MAX_X || _x == MIN_X)
_toLeft = !_toLeft;
}
}
You are missing the notion of direction in your code. You can do it in hundreds of ways so I'm not going to write the code here.
But once your x is equal to 501, you are decreasing its value by one, so on the next call its value is 500 therefore resetting it to 501 and so on. This is why it stops moving. You need to change direction on the edges, therefore increase or decrease X until you hit the other edge.
I want to make a Kinect program thanks to, when your left hand X position cross your right shoulder X position, it plays the following slide on PowerPoint. I've already done the program part which draws the skeleton stream, and it's work correctly. For the second part, I've tried this :
private void NextSlide(Skeleton skeleton)
{
Joint leftHand = skeleton.Joints[JointType.HandLeft];
Joint spine = skeleton.Joints[JointType.Spine];
Joint shoulderRight = skeleton.Joints[JointType.ShoulderRight];
bool check = false;
if (leftHand.Position.X == shoulderRight.Position.X && check == false)
{
check = true;
System.Windows.Forms.SendKeys.Send("{RIGHT}");
}
if (leftHand.Position.X == spine.Position.X && check == true)
{
check = false
}
}
Can anyone explain me what is the problem in my code ?
Thanks,
Edit :
I've also tried this :
private void NextSlide(Skeleton skeleton)
{
Joint leftHand = skeleton.Joints[JointType.HandLeft];
Joint spine = skeleton.Joints[JointType.Spine];
Joint shoulderRight = skeleton.Joints[JointType.ShoulderRight];
double lefthandposition = (int)leftHand.Position.X;
double shoulderrightposition = (int)shoulderRight.Position.X;
double spineposition = (int)spine.Position.X;
bool turn = false;
double right = lefthandposition - shoulderrightposition;
bool finish = false;
double ok = lefthandposition - spineposition;
if (right < 0)
{
turn = true;
}
if (ok > 0)
{
finish = true;
}
bool check = false;
if (turn == true && check == false && finish == false)
{
System.Windows.Forms.SendKeys.Send("{RIGHT}");
check = true;
turn = false;
}
if (finish == true && check == true && turn == false)
{
check = false;
finish = false;
}
}
But it doesn't work too :/
The trouble you are running into is that you using == as a check. You will rarely, if ever, run into a situation where two joints are exactly the same value. You need to be using >= or <= for your checks, depending on your needs.
For example, check the JointType.LeftHand >= JointType.RightShoulder, and that JointType.LeftHand <= JointType.Spine, for your position checks.
Another solution could be to use an existing gesture library to accomplish what you want. Here are two of them:
http://kinecttoolbox.codeplex.com/
https://github.com/EvilClosetMonkey/Fizbin.Kinect.Gestures
The Fizbin library's GitHub page explains how to set up and execute on existing gestures: Executing on Gestures. Included in the existing gesture set is a "Swipe Right" and a "Swipe Left" gesture, which execute similar to what you are wanting to do.
The GitHub pages goes into more detail, but a quick rundown would start with setting up the gesture library and a callback:
gestureController = new GestureController();
gestureController.GestureRecognized += OnGestureRecognized;
You'd then initialize the gesture(s) you want to use:
IRelativeGestureSegment[] swipeleftSegments = new IRelativeGestureSegment[3];
swipeleftSegments[0] = new SwipeLeftSegment1();
swipeleftSegments[1] = new SwipeLeftSegment2();
swipeleftSegments[2] = new SwipeLeftSegment3();
gestureController.AddGesture("SwipeLeft", swipeleftSegments);
You can modify the existing gesture components or write your own. The several examples will demonstrate how you can compare joint positions. For example, the first segment in the "SwipeLeft" gesture follows:
public class SwipeLeftSegment1 : IRelativeGestureSegment
{
/// <summary>
/// Checks the gesture.
/// </summary>
/// <param name="skeleton">The skeleton.</param>
/// <returns>GesturePartResult based on if the gesture part has been completed</returns>
public GesturePartResult CheckGesture(Skeleton skeleton)
{
// right hand in front of right shoulder
if (skeleton.Joints[JointType.HandRight].Position.Z < skeleton.Joints[JointType.ElbowRight].Position.Z && skeleton.Joints[JointType.HandLeft].Position.Y < skeleton.Joints[JointType.ShoulderCenter].Position.Y)
{
// right hand below shoulder height but above hip height
if (skeleton.Joints[JointType.HandRight].Position.Y < skeleton.Joints[JointType.Head].Position.Y && skeleton.Joints[JointType.HandRight].Position.Y > skeleton.Joints[JointType.HipCenter].Position.Y)
{
// right hand right of right shoulder
if (skeleton.Joints[JointType.HandRight].Position.X > skeleton.Joints[JointType.ShoulderRight].Position.X)
{
return GesturePartResult.Succeed;
}
return GesturePartResult.Pausing;
}
return GesturePartResult.Fail;
}
return GesturePartResult.Fail;
}
}
Notice it goes through a series of joint checks and returns one of three results:
Succeed: The gesture has completed in full (fired when all the 'if' statements succeed)
Pausing: The gesture is partially complete (fired when you want to indicate the gesture is "in motion" but not complete)
Fail: The gesture is not being executed at all
When you have the gesture you want initialized you just need to send the 'skeleton' data to the gesture library:
private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame == null)
return;
// resize the skeletons array if needed
if (skeletons.Length != frame.SkeletonArrayLength)
skeletons = new Skeleton[frame.SkeletonArrayLength];
// get the skeleton data
frame.CopySkeletonDataTo(skeletons);
foreach (var skeleton in skeletons)
{
// skip the skeleton if it is not being tracked
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
continue;
// update the gesture controller
gestureController.UpdateAllGestures(skeleton);
}
}
}
Finally, execute on the gesture:
private void OnGestureRecognized(object sender, GestureEventArgs e)
{
switch (e.GestureName)
{
case "SwipeLeft":
// do what you want to do
break;
default:
break;
}
}