Skip to content

Instantly share code, notes, and snippets.

@adam-phillipps
Created March 19, 2016 07:09
Show Gist options
  • Save adam-phillipps/fc823b33edab971b0838 to your computer and use it in GitHub Desktop.
Save adam-phillipps/fc823b33edab971b0838 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace Connect4
{
class PanelBackend
{
public SolidColorBrush[,] panel;
public PanelBackend()
{
panel = new SolidColorBrush[6, 7];
}
public int DropDisk(int? currentMove, SolidColorBrush diskColor)
{
int slot = currentMove ?? default(int);
int height = GetHeight(slot);
panel[height, slot] = diskColor;
return height;
}
public bool CheckForWin(int height, int slot)
{
return (CheckDiagonal(height, slot)
|| CheckHorizontal(height, slot)
|| CheckVertical(height, slot));
}
private bool CheckDiagonal(int height, int slot)
{
int count = 0;
int reverseCount = 0;
int tempHeight = height;
// count from all four lines going diagonally away from the current move
// counts up and to the right
for (int tempSlot = slot; (tempSlot < panel.GetLength(1) && tempHeight < panel.GetLength(0)); tempSlot++)
{
if (panel[tempHeight, tempSlot] == panel[height, slot])
{
count += 1;
}
else
{ break; }
tempHeight += 1;
}
tempHeight = height;
if (count == 4)
return true;
// counts down and to the left to join the first partial line with this one
for (int tempSlot = slot; (tempSlot > 0 && tempHeight > 0); tempSlot++)
{
if (panel[tempHeight, tempSlot] == panel[height, slot])
{ // don't count the origin again
if (tempSlot != slot && tempHeight != height)
count += 1;
}
else { break; }
tempHeight -= 1;
}
if (count == 4)
return true;
tempHeight = height;
// counts up and to the left
for (int tempSlot = slot; (tempSlot > 0 && tempHeight < panel.GetLength(0)); tempSlot--)
{
if (panel[tempHeight, tempSlot] == panel[height, slot])
{
reverseCount += 1;
}
else { break; }
tempHeight += 1;
}
tempHeight = height;
// counts down and to the right to finish the up and to the left line
for (int tempSlot = slot; (tempSlot < panel.GetLength(1) && tempHeight > 0); tempSlot++)
{
if (panel[tempHeight, tempSlot] == panel[height, slot])
{ // don't count the origin again
if (tempSlot != slot && tempHeight != height)
reverseCount += 1;
}
else { break; }
tempHeight -= 1;
}
if (reverseCount == 4)
return true;
return (count >= 4 || reverseCount >= 4);
}
private bool CheckHorizontal(int height, int slot)
{
int count = 0;
for (int col = 0; col < panel.GetLength(1); col++)
{
if (panel[height, col] == panel[height, slot])
{
if ((count += 1) == 4)
break;
}
else
count = 0;
}
return count == 4;
}
private bool CheckVertical(int height, int slot)
{
int count = 0;
for (int row = 0; row < panel.GetLength(0); row++)
{
if (panel[row, slot] == panel[height, slot])
{
if ((count += 1) == 4)
break;
}
else
count = 0;
}
return count == 4;
}
public int GetHeight(int slot)
{
int number = 6;
for (int lastFilledRow = 0; lastFilledRow < 5; ++lastFilledRow)
{
if (panel[lastFilledRow, slot] == null)
{
number = lastFilledRow;
}
else
break;
}
return number;
}
}
}
<Window x:Class="Connect4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Connect4"
mc:Ignorable="d"
Title="Connect 4" Height="350" Width="525">
<!-- contains and organizes the game area and reset button -->
<Grid x:Name="BaseOrganizer" Background="Black">
<!--
top grid row = top row that placeholder disk moves in
middle six grid rows = game area
bottom grid row = reset button
-->
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="6*"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- where the action happens -->
<Grid x:Name="gamePanel"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="7"
Background="Blue"
ShowGridLines="True">
<Canvas x:Name="animationBoard" />
</Grid>
<!-- user controls -->
<DockPanel x:Name="UserControlls" Grid.Row="2" >
<Button x:Name="resetButton"
Content="Reset the game"
Click="resetButton_Click">
<Button.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Button.Background>
</Button>
</DockPanel>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace Connect4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private DispatcherTimer timer = new DispatcherTimer();
private int startTop = 80;
private int currentTop;
private int bottom = 330;
private SolidColorBrush yellow = Brushes.Yellow;
private SolidColorBrush red = Brushes.Red;
private SolidColorBrush turn;
private PanelBackend panel;
private int[] XY = new int[2];
private int animationStopRow;
private Ellipse currentEllipse;
public MainWindow()
{
InitializeComponent();
SetUpGamePanel();
Play();
}
public void Play()
{
int turnCounter = 0;
do
{
turn = ((turnCounter += 1) % 2 == 0)
? red
: yellow;
Ellipse disk = Disk(turn);
currentEllipse = disk;
Keyboard.Focus(disk);
}
while (!IsWinningMove() && turnCounter < 42);
if (turnCounter < 42)
FlashingHappyFunTime();
else
Reset();
panel = new PanelBackend();
}
private int[] GetMove(Ellipse currentDisk)
{
int lastCol = XY[1];
int currentCol = lastCol;
while (currentCol == lastCol)
{
currentCol = lastCol + 1;
}
return XY;
}
private bool IsWinningMove()
{
SolidColorBrush b = Brushes.Yellow;
animationStopRow = panel.DropDisk(XY[1], ((SolidColorBrush)currentEllipse.Fill));
return panel.CheckForWin(animationStopRow, XY[1]);
}
private void InitTimer()
{
timer.Interval = new TimeSpan(0, 0, 0, 0, 25);
timer.Tick += AnimateDiskDrop;
}
private void AnimateDiskDrop(object sender, EventArgs e)
{
const int updateDistance = 10;
if (currentTop + updateDistance <= bottom)
{
currentTop += updateDistance;
Canvas.SetTop(Disk(Brushes.Yellow), currentTop);
}
else
{
timer.Stop();
}
}
private void FlashingHappyFunTime()
{
//throw new NotImplementedException();
}
private Grid SetUpGamePanel()
{
panel = new PanelBackend();
gamePanel.ColumnDefinitions.Add(Col());
for (int row = 0; row < 6; row++)
{
gamePanel.RowDefinitions.Add(Row());
gamePanel.ColumnDefinitions.Add(Col());
}
return gamePanel;
}
private Ellipse Disk(SolidColorBrush turn)
{
const int size = 30;
Ellipse disk = new Ellipse();
disk.Fill = turn;
disk.Width = disk.Height = size;
disk.KeyDown += Disk_KeyDown;
return disk;
}
private void Disk_KeyDown(object sender, KeyEventArgs e)
{
while (e.Key != Key.Enter)
{
if (e.Key == Key.Right)
{
// cd.location -= UpdateDistance;
}
else if (e.Key == Key.Left)
{
// cd.location += updateDistance;
}
}
// XY[0] = cd.location;
int current = XY[1];
//var currentPosition = sender.TranslatePoint(new Point(0, 0), gamePanel);
}
private RowDefinition Row()
{
return new RowDefinition();
}
private ColumnDefinition Col()
{
return new ColumnDefinition();
}
private void resetButton_Click(object sender, RoutedEventArgs e)
{
Reset();
}
private void Reset()
{
//SetUpGamePanel();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment